文档修改
This commit is contained in:
834
Project/fonrey/PRD/TASK.md
Normal file
834
Project/fonrey/PRD/TASK.md
Normal file
@@ -0,0 +1,834 @@
|
|||||||
|
## Project Task Board
|
||||||
|
|
||||||
|
### 项目状态总览
|
||||||
|
|
||||||
|
- 产品名称:Fonrey 房睿
|
||||||
|
- 当前阶段:MVP Phase 1
|
||||||
|
- 技术栈:Django 4.x + HTMX + Alpine.js + Tailwind CSS + PostgreSQL 16 + Redis + Celery + Cloudflare R2
|
||||||
|
- 最后更新:2026-04-26
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 索引总览
|
||||||
|
|
||||||
|
> 点击 US 编号可直接跳转到对应 Task 详情。
|
||||||
|
|
||||||
|
#### Phase 1 — MVP(P0)
|
||||||
|
|
||||||
|
| US 编号 | 模块 | Task 描述 | 状态 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| [US-ACCOUNT-001](#US-ACCOUNT-001-经纪人管理员使用账号密码登录系统) | 用户登录 | 经纪人/管理员使用账号密码登录系统 | [ ] |
|
||||||
|
| [US-ACCOUNT-002](#US-ACCOUNT-002-系统识别多租户子域名域名路由) | 用户登录 | 系统识别多租户(子域名/域名路由) | [ ] |
|
||||||
|
| [US-ACCOUNT-003](#US-ACCOUNT-003-系统管理-Token-与会话超时) | 用户登录 | 系统管理 Token 与会话超时 | [ ] |
|
||||||
|
| [US-COMPLEX-001](#US-COMPLEX-001-管理员录入与维护楼盘基础信息) | 楼盘管理 | 管理员录入与维护楼盘基础信息 | [ ] |
|
||||||
|
| [US-COMPLEX-002](#US-COMPLEX-002-经纪人查看楼盘列表与详情) | 楼盘管理 | 经纪人查看楼盘列表与详情 | [ ] |
|
||||||
|
| [US-COMPLEX-003](#US-COMPLEX-003-管理员维护区域管理城区商圈) | 楼盘管理 | 管理员维护区域管理(城区/商圈) | [ ] |
|
||||||
|
| [US-PROPERTY-001](#US-PROPERTY-001-经纪人录入二手住宅出售出租) | 房源管理 | 经纪人录入二手住宅(出售/出租) | [ ] |
|
||||||
|
| [US-PROPERTY-002](#US-PROPERTY-002-经纪人查看与筛选房源列表) | 房源管理 | 经纪人查看与筛选房源列表 | [ ] |
|
||||||
|
| [US-PROPERTY-003](#US-PROPERTY-003-经纪人查看房源详情页) | 房源管理 | 经纪人查看房源详情页 | [ ] |
|
||||||
|
| [US-PROPERTY-004](#US-PROPERTY-004-经纪人写入与查看房源跟进记录) | 房源管理 | 经纪人写入与查看房源跟进记录 | [ ] |
|
||||||
|
| [US-PROPERTY-005](#US-PROPERTY-005-经纪人管理房源图片上传分类排序) | 房源管理 | 经纪人管理房源图片(上传/分类/排序) | [ ] |
|
||||||
|
| [US-PROPERTY-006](#US-PROPERTY-006-经纪人管理业主联系人) | 房源管理 | 经纪人管理业主联系人 | [ ] |
|
||||||
|
| [US-PROPERTY-007](#US-PROPERTY-007-经纪人调整房源价格) | 房源管理 | 经纪人调整房源价格 | [ ] |
|
||||||
|
| [US-PROPERTY-008](#US-PROPERTY-008-经纪人变更房源状态) | 房源管理 | 经纪人变更房源状态 | [ ] |
|
||||||
|
| [US-CLIENT-001](#US-CLIENT-001-经纪人录入新私客) | 客源管理 | 经纪人录入新私客 | [ ] |
|
||||||
|
| [US-CLIENT-002](#US-CLIENT-002-经纪人查看与筛选私客列表全部求购求租) | 客源管理 | 经纪人查看与筛选私客列表(全部/求购/求租) | [ ] |
|
||||||
|
| [US-CLIENT-003](#US-CLIENT-003-经纪人批量操作私客列表) | 客源管理 | 经纪人批量操作私客列表 | [ ] |
|
||||||
|
| [US-CLIENT-004](#US-CLIENT-004-经纪人查看私客详情页) | 客源管理 | 经纪人查看私客详情页 | [ ] |
|
||||||
|
| [US-CLIENT-005](#US-CLIENT-005-经纪人查看与编辑需求信息) | 客源管理 | 经纪人查看与编辑需求信息 | [ ] |
|
||||||
|
| [US-CLIENT-006](#US-CLIENT-006-经纪人写入与查看跟进记录) | 客源管理 | 经纪人写入与查看跟进记录 | [ ] |
|
||||||
|
| [US-CLIENT-007](#US-CLIENT-007-经纪人管理带看记录预约带看新增带看) | 客源管理 | 经纪人管理带看记录(预约带看/新增带看) | [ ] |
|
||||||
|
| [US-CLIENT-008](#US-CLIENT-008-经纪人管理客源联系人查看新增编辑) | 客源管理 | 经纪人管理客源联系人(查看/新增/编辑) | [ ] |
|
||||||
|
| [US-CLIENT-009](#US-CLIENT-009-经纪人修改客源等级) | 客源管理 | 经纪人修改客源等级 | [ ] |
|
||||||
|
| [US-CLIENT-010](#US-CLIENT-010-经纪人修改客源状态) | 客源管理 | 经纪人修改客源状态 | [ ] |
|
||||||
|
| [US-CLIENT-011](#US-CLIENT-011-经纪人手动将私客转为公客) | 客源管理 | 经纪人手动将私客转为公客 | [ ] |
|
||||||
|
| [US-CLIENT-012](#US-CLIENT-012-经纪人将私客转为成交客) | 客源管理 | 经纪人将私客转为成交客 | [ ] |
|
||||||
|
| [US-CLIENT-013](#US-CLIENT-013-经纪人将客源标记为无效) | 客源管理 | 经纪人将客源标记为无效 | [ ] |
|
||||||
|
| [US-CLIENT-014](#US-CLIENT-014-经纪人编辑客源完整信息联系人基础信息需求) | 客源管理 | 经纪人编辑客源完整信息(联系人/基础信息/需求) | [ ] |
|
||||||
|
| [US-CLIENT-015](#US-CLIENT-015-经纪人管理客源相关员工查看编辑归属人首录人) | 客源管理 | 经纪人管理客源相关员工(查看/编辑归属人/首录人) | [ ] |
|
||||||
|
| [US-CLIENT-016](#US-CLIENT-016-系统自动将超时无跟进的私客转为公客) | 客源管理 | 系统自动将超时无跟进的私客转为公客 | [ ] |
|
||||||
|
| [US-CLIENT-017](#US-CLIENT-017-系统自动检测重复客源并提示) | 客源管理 | 系统自动检测重复客源并提示 | [ ] |
|
||||||
|
| [US-ORG-001](#US-ORG-001-管理员维护公司组织结构部门门店树) | 组织人事 | 管理员维护公司组织结构(部门/门店树) | [ ] |
|
||||||
|
| [US-ORG-002](#US-ORG-002-管理员查看与维护员工列表) | 组织人事 | 管理员查看与维护员工列表 | [ ] |
|
||||||
|
| [US-ORG-003](#US-ORG-003-管理员办理员工入职并创建系统账号) | 组织人事 | 管理员办理员工入职并创建系统账号 | [ ] |
|
||||||
|
| [US-PERMISSION-001](#US-PERMISSION-001-管理员配置角色预设角色自定义角色) | 权限管理 | 管理员配置角色(预设角色/自定义角色) | [ ] |
|
||||||
|
| [US-PERMISSION-002](#US-PERMISSION-002-管理员查看与管理人员权限列表) | 权限管理 | 管理员查看与管理人员权限列表 | [ ] |
|
||||||
|
| [US-PERMISSION-003](#US-PERMISSION-003-管理员批量为员工分配角色) | 权限管理 | 管理员批量为员工分配角色 | [ ] |
|
||||||
|
| [US-PERMISSION-004](#US-PERMISSION-004-系统执行功能权限控制菜单级) | 权限管理 | 系统执行功能权限控制(菜单级) | [ ] |
|
||||||
|
| [US-PERMISSION-005](#US-PERMISSION-005-系统执行数据权限控制部门个人全司) | 权限管理 | 系统执行数据权限控制(部门/个人/全司) | [ ] |
|
||||||
|
| [US-SETTING-001](#US-SETTING-001-管理员配置房源相关设置字段必填自定义字段标签) | 系统配置 | 管理员配置房源相关设置(字段必填/自定义字段/标签) | [ ] |
|
||||||
|
|
||||||
|
#### Phase 2 — 增强功能(P1)
|
||||||
|
|
||||||
|
| US 编号 | 模块 | Task 描述 | 状态 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| [US-ACCOUNT-010](#US-ACCOUNT-010-经纪人使用短信验证码登录) | 用户登录 | 经纪人使用短信验证码登录 | [ ] |
|
||||||
|
| [US-ACCOUNT-011](#US-ACCOUNT-011-经纪人重置账号密码) | 用户登录 | 经纪人重置账号密码 | [ ] |
|
||||||
|
| [US-ACCOUNT-012](#US-ACCOUNT-012-系统记住用户登录状态) | 用户登录 | 系统记住用户登录状态 | [ ] |
|
||||||
|
| [US-COMPLEX-010](#US-COMPLEX-010-管理员管理楼盘照片) | 楼盘管理 | 管理员管理楼盘照片 | [ ] |
|
||||||
|
| [US-COMPLEX-011](#US-COMPLEX-011-管理员维护楼盘价格走势) | 楼盘管理 | 管理员维护楼盘价格走势 | [ ] |
|
||||||
|
| [US-COMPLEX-012](#US-COMPLEX-012-管理员维护周边配套学校管理) | 楼盘管理 | 管理员维护周边配套(学校管理) | [ ] |
|
||||||
|
| [US-PROPERTY-010](#US-PROPERTY-010-经纪人查看房源维护完成度诊断面板) | 房源管理 | 经纪人查看房源维护完成度(诊断面板) | [ ] |
|
||||||
|
| [US-PROPERTY-011](#US-PROPERTY-011-经纪人管理敏感信息跟进权限控制) | 房源管理 | 经纪人管理敏感信息跟进(权限控制) | [ ] |
|
||||||
|
| [US-PROPERTY-012](#US-PROPERTY-012-经纪人管理房源附件) | 房源管理 | 经纪人管理房源附件 | [ ] |
|
||||||
|
| [US-PROPERTY-013](#US-PROPERTY-013-经纪人查看房源市场报盘) | 房源管理 | 经纪人查看房源市场报盘 | [ ] |
|
||||||
|
| [US-PROPERTY-014](#US-PROPERTY-014-经纪人查看房源价格解读) | 房源管理 | 经纪人查看房源价格解读 | [ ] |
|
||||||
|
| [US-CLIENT-020](#US-CLIENT-020-经纪人使用二手配房功能查看匹配房源) | 客源管理 | 经纪人使用二手配房功能查看匹配房源 | [ ] |
|
||||||
|
| [US-CLIENT-021](#US-CLIENT-021-经纪人查看客源解读AI行为分析) | 客源管理 | 经纪人查看客源解读(AI行为分析) | [ ] |
|
||||||
|
| [US-CLIENT-022](#US-CLIENT-022-经纪人将重点客源收藏至收藏夹) | 客源管理 | 经纪人将重点客源收藏至收藏夹 | [ ] |
|
||||||
|
| [US-CLIENT-023](#US-CLIENT-023-经纪人通过快捷入口编辑客源基础信息) | 客源管理 | 经纪人通过快捷入口编辑客源基础信息 | [ ] |
|
||||||
|
| [US-CLIENT-024](#US-CLIENT-024-经纪人查看客源操作日志) | 客源管理 | 经纪人查看客源操作日志 | [ ] |
|
||||||
|
| [US-ORG-010](#US-ORG-010-管理员办理员工离职与调动) | 组织人事 | 管理员办理员工离职与调动 | [ ] |
|
||||||
|
| [US-ORG-011](#US-ORG-011-管理员维护员工通讯录) | 组织人事 | 管理员维护员工通讯录 | [ ] |
|
||||||
|
| [US-ORG-012](#US-ORG-012-管理员管理员工职务) | 组织人事 | 管理员管理员工职务 | [ ] |
|
||||||
|
| [US-PERMISSION-010](#US-PERMISSION-010-管理员配置字段级权限敏感字段可见性) | 权限管理 | 管理员配置字段级权限(敏感字段可见性) | [ ] |
|
||||||
|
| [US-PERMISSION-011](#US-PERMISSION-011-管理员配置个人特定权限覆盖) | 权限管理 | 管理员配置个人特定权限覆盖 | [ ] |
|
||||||
|
| [US-SETTING-010](#US-SETTING-010-管理员配置首页展示内容) | 系统配置 | 管理员配置首页展示内容 | [ ] |
|
||||||
|
| [US-SETTING-011](#US-SETTING-011-管理员配置相关方规则) | 系统配置 | 管理员配置相关方规则 | [ ] |
|
||||||
|
| [US-SETTING-012](#US-SETTING-012-管理员配置客源相关参数) | 系统配置 | 管理员配置客源相关参数 | [ ] |
|
||||||
|
| [US-SYSTEM-010](#US-SYSTEM-010-平台管理员管理租户开通暂停配置) | 系统管理 | 平台管理员管理租户(开通/暂停/配置) | [ ] |
|
||||||
|
| [US-SYSTEM-011](#US-SYSTEM-011-平台管理员监控系统健康状态) | 系统管理 | 平台管理员监控系统健康状态 | [ ] |
|
||||||
|
| [US-RELEASE-010](#US-RELEASE-010-系统发布Windows桌面客户端安装包) | 客户端发布 | 系统发布Windows桌面客户端安装包 | [ ] |
|
||||||
|
| [US-RELEASE-011](#US-RELEASE-011-客户端自动检测并更新至最新版本) | 客户端发布 | 客户端自动检测并更新至最新版本 | [ ] |
|
||||||
|
|
||||||
|
#### Phase 3 — 路线图功能(P2)
|
||||||
|
|
||||||
|
| US 编号 | 模块 | Task 描述 | 状态 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| [US-PROPERTY-020](#US-PROPERTY-020-经纪人录入别墅商铺商住写字楼其他类型房源) | 房源管理 | 经纪人录入别墅/商铺/商住/写字楼/其他类型房源 | [ ] |
|
||||||
|
| [US-PROPERTY-021](#US-PROPERTY-021-经纪人查看全部商铺写字楼列表) | 房源管理 | 经纪人查看全部商铺/写字楼列表 | [ ] |
|
||||||
|
| [US-COMPLEX-020](#US-COMPLEX-020-管理员使用应用数据标准功能) | 楼盘管理 | 管理员使用应用数据标准功能 | [ ] |
|
||||||
|
| [US-CLIENT-030](#US-CLIENT-030-经纪人查看与管理公客列表) | 客源管理 | 经纪人查看与管理公客列表 | [ ] |
|
||||||
|
| [US-CLIENT-031](#US-CLIENT-031-经纪人查看与管理成交客列表) | 客源管理 | 经纪人查看与管理成交客列表 | [ ] |
|
||||||
|
| [US-CLIENT-032](#US-CLIENT-032-经纪人管理暂缓私客) | 客源管理 | 经纪人管理暂缓私客 | [ ] |
|
||||||
|
| [US-ORG-020](#US-ORG-020-管理员查看员工异动记录) | 组织人事 | 管理员查看员工异动记录 | [ ] |
|
||||||
|
| [US-ORG-021](#US-ORG-021-管理员管理员工奖惩记录) | 组织人事 | 管理员管理员工奖惩记录 | [ ] |
|
||||||
|
| [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-SYSTEM-020](#US-SYSTEM-020-平台管理员查看操作审计日志) | 系统管理 | 平台管理员查看操作审计日志 | [ ] |
|
||||||
|
| [US-SYSTEM-021](#US-SYSTEM-021-平台管理员管理灰度发布滚动升级) | 系统管理 | 平台管理员管理灰度发布/滚动升级 | [ ] |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 1 - MVP(P0,上线前必须完成)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 用户登录
|
||||||
|
|
||||||
|
##### US-ACCOUNT-001 经纪人管理员使用账号密码登录系统
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/登录管理/用户登录管理模块PRD.md` - 账号密码登录
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_LOGIN.md`
|
||||||
|
- 参考UI_Design文档:`Project/fonrey/UI_DESIGN/登录管理/登录_UI.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:输入正确账号密码后跳转首页;密码错误时展示"账号或密码错误"提示;连续错误5次后账号锁定提示;登录成功后 Token 写入 Cookie
|
||||||
|
|
||||||
|
##### US-ACCOUNT-002 系统识别多租户子域名域名路由
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/登录管理/用户登录管理模块PRD.md` - 多租户识别
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_LOGIN.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:访问不同子域名时系统自动切换对应租户 Schema;非法/不存在子域名返回404页面;跨租户请求被拦截并返回403
|
||||||
|
|
||||||
|
##### US-ACCOUNT-003 系统管理 Token 与会话超时
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/登录管理/用户登录管理模块PRD.md` - Token 管理/会话超时
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_LOGIN.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:会话超时后自动跳转登录页;Token 刷新机制正常工作;登出后 Token 立即失效,再次请求跳转登录页
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 楼盘管理
|
||||||
|
|
||||||
|
##### US-COMPLEX-001 管理员录入与维护楼盘基础信息
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/房源管理/楼盘管理模块PRD.md` - 楼盘信息管理
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_COMPLEX.md`
|
||||||
|
- 参考UI_Design文档:`Project/fonrey/UI_DESIGN/楼盘管理/楼盘详情_UI.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:可录入楼盘名称、地址、楼栋、结构等基础字段;保存成功后楼盘出现在楼盘列表;必填字段未填时高亮错误提示;楼盘编号系统自动生成且唯一
|
||||||
|
|
||||||
|
##### US-COMPLEX-002 经纪人查看楼盘列表与详情
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/房源管理/楼盘管理模块PRD.md` - 楼盘列表/楼盘详情
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_COMPLEX.md`
|
||||||
|
- 参考UI_Design文档:`Project/fonrey/UI_DESIGN/楼盘管理/楼盘列表_UI.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:楼盘列表支持按名称/地址关键词搜索;支持分页(默认20条/页);点击楼盘名称跳转详情页;详情页展示楼盘基本信息、楼栋结构信息
|
||||||
|
|
||||||
|
##### US-COMPLEX-003 管理员维护区域管理城区商圈
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/房源管理/楼盘管理模块PRD.md` - 区域管理
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_COMPLEX.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:可新增/编辑/删除城区和商圈;商圈必须归属于城区;区域数据被房源和客源模块正确关联引用;删除有关联数据的区域时系统给出警告
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 房源管理
|
||||||
|
|
||||||
|
##### US-PROPERTY-001 经纪人录入二手住宅出售出租
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/房源管理/房源管理模块PRD.md` - 录入住宅(二手出售/出租)
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_PROPERTY.md`
|
||||||
|
- 参考UI_Design文档:`Project/fonrey/UI_DESIGN/房源管理/新增房源_UI.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:可在3分钟内完成住宅基本信息录入;必填字段(楼盘/楼层/面积/价格)未填时高亮错误提示;保存成功后跳转房源详情页并显示"保存成功";录入后即刻出现在房源列表
|
||||||
|
|
||||||
|
##### US-PROPERTY-002 经纪人查看与筛选房源列表
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/房源管理/房源管理模块PRD.md` - 房源列表(二手&租赁)
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_PROPERTY.md`
|
||||||
|
- 参考UI_Design文档:`Project/fonrey/UI_DESIGN/房源管理/房源列表_UI.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:列表支持按楼盘名/业主姓名/电话/房源编号关键词搜索;支持状态/区域/价格/房型多维度组合筛选;列表分页(默认20条/页)且89000条数据下查询响应<2秒;支持导出当前筛选结果为Excel
|
||||||
|
|
||||||
|
##### US-PROPERTY-003 经纪人查看房源详情页
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/房源管理/房源管理模块PRD.md` - 房源详情页
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_PROPERTY.md`
|
||||||
|
- 参考UI_Design文档:`Project/fonrey/UI_DESIGN/房源管理/房源详情_UI.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:详情页完整展示基本信息、产证信息、交易信息;号码默认打码,点击"查看号码"后解密展示并记录审计日志;页面各功能 Tab 可正常切换
|
||||||
|
|
||||||
|
##### US-PROPERTY-004 经纪人写入与查看房源跟进记录
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/房源管理/房源管理模块PRD.md` - 跟进记录(全部/写入/修改/其他)
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_PROPERTY.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:跟进记录按时间线倒序展示;支持写入跟进/修改跟进/其他跟进(钥匙/委托/实勘)子Tab切换;跟进内容最少6字校验;写入成功后记录实时出现在列表顶部
|
||||||
|
|
||||||
|
##### US-PROPERTY-005 经纪人管理房源图片上传分类排序
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/房源管理/房源管理模块PRD.md` - 图片管理(相册上传/分类/排序)
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_PROPERTY.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:支持上传 bmp/jpg/png/gif 格式图片,单文件最大20MB;上传成功后自动按分类展示;支持拖拽排序;封面图可手动指定
|
||||||
|
|
||||||
|
##### US-PROPERTY-006 经纪人管理业主联系人
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/房源管理/房源管理模块PRD.md` - 业主联系人管理
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_PROPERTY.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:支持新增/编辑业主联系人(姓名/电话/微信);手机号加密存储,展示时默认打码;可查看同业主名下其他房源;至少保留一个联系人
|
||||||
|
|
||||||
|
##### US-PROPERTY-007 经纪人调整房源价格
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/房源管理/房源管理模块PRD.md` - 价格调整(调价/调价记录)
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_PROPERTY.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:调价弹窗需填写新价格和调价原因;调价成功后房源列表和详情页价格实时更新;调价记录以时间线形式留存且不可删除;调价幅度在列表中以"降价XX万"标签展示
|
||||||
|
|
||||||
|
##### US-PROPERTY-008 经纪人变更房源状态
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/房源管理/房源管理模块PRD.md` - 房源状态变更(在售/暂缓/成交/下架)
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_PROPERTY.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:状态变更严格遵循状态机流转规则(在售→暂缓/成交/下架);每次状态变更需填写原因;状态变更后列表状态标签实时更新;状态变更记录写入跟进日志
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 客源管理
|
||||||
|
|
||||||
|
##### US-CLIENT-001 经纪人录入新私客
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/客源管理/客源管理模块PRD.md` - Story 1:经纪人录入新私客;5.2 录入私客
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md`
|
||||||
|
- 参考UI_Design文档:`Project/fonrey/UI_DESIGN/客源管理/新增客源_UI.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:录入页面可通过顶部导航「客源」→「+新增私客」或右侧快捷入口「增客」触达;联系人1必填(姓名/性别/电话1),联系人2起可增加删除;基础信息必填字段(状态/用途/等级/来源)缺填时高亮错误并定位到第一个错误处;保存成功后跳转该客源详情页并显示"保存成功"提示
|
||||||
|
|
||||||
|
##### US-CLIENT-002 经纪人查看与筛选私客列表全部求购求租
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/客源管理/客源管理模块PRD.md` - Story 2/3/4:经纪人查看与筛选私客列表;5.1 客源列表
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md`
|
||||||
|
- 参考UI_Design文档:`Project/fonrey/UI_DESIGN/客源管理/客源列表_UI.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:顶部Tab导航(私客/资料客/营销客/成交客/公客)及二级Tab(求购/求租/暂缓/全部私客)可正常切换;搜索框支持按客源姓名/号码/号码后4位/客源编号/备注检索;筛选栏支持状态/等级/位置/价格/房室等多维度组合筛选;列表底部实时显示当前筛选总条数,分页默认20条/页,89000条数据量下查询<2秒
|
||||||
|
|
||||||
|
##### US-CLIENT-003 经纪人批量操作私客列表
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/客源管理/客源管理模块PRD.md` - Story 2:列表批量操作;5.1.3 批量操作
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md`
|
||||||
|
- 参考UI_Design文档:`Project/fonrey/UI_DESIGN/客源管理/客源列表_UI.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:勾选客源后激活批量操作按钮(修改相关方/修改来源/删除客源/合并客户);批量删除执行软删除,可在"已删客源"中查看;批量修改相关方成功后列表归属人字段实时刷新;列表支持导出当前筛选结果为Excel(Celery异步处理)
|
||||||
|
|
||||||
|
##### US-CLIENT-004 经纪人查看私客详情页
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/客源管理/客源管理模块PRD.md` - Story 6:经纪人查看私客详情页;Story 15:经纪人查看客源信息概览面板
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md`
|
||||||
|
- 参考UI_Design文档:`Project/fonrey/UI_DESIGN/客源管理/客源详情_UI.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:详情页顶部展示需求标题+联系人姓名+带看进度标签;右侧固定信息概览面板展示客户编号/委托日期/需求类型等字段且不随页面滚动消失;主内容区Tab导航(需求信息/跟进记录/带看/客源解读/智能配房)默认激活"需求信息"Tab;右侧面板三个主操作按钮(打电话/写跟进/报备带看)可正常触发对应流程
|
||||||
|
|
||||||
|
##### US-CLIENT-005 经纪人查看与编辑需求信息
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/客源管理/客源管理模块PRD.md` - Story 7:经纪人查看与编辑需求信息
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md`
|
||||||
|
- 参考UI_Design文档:`Project/fonrey/UI_DESIGN/客源管理/客源详情_UI.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:需求信息Tab展示总价/面积/居室/装修/朝向/楼层/楼龄/意向商圈/意向小区等字段(三栏布局);字段值为空时显示"-"占位符;右上角「编辑」链接点击后字段转为输入框/选择器;保存成功后返回详情页并刷新需求信息区块
|
||||||
|
|
||||||
|
##### US-CLIENT-006 经纪人写入与查看跟进记录
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/客源管理/客源管理模块PRD.md` - Story 8:经纪人写入与查看跟进记录
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md`
|
||||||
|
- 参考UI_Design文档:`Project/fonrey/UI_DESIGN/客源管理/客源详情_UI.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:跟进记录分5个子Tab(全部/写入跟进/敏感信息跟进/修改跟进/其他跟进);全部Tab支持时间范围筛选及「有录音」「有图片」快速过滤;跟进记录以时间线形式按日期分组倒序展示;写入跟进时跟进目的支持23项多选,跟进内容最少6字校验;系统自动生成的操作日志(如新增私客/状态变更)出现在"其他跟进"Tab
|
||||||
|
|
||||||
|
##### US-CLIENT-007 经纪人管理带看记录预约带看新增带看
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/客源管理/客源管理模块PRD.md` - Story 9:经纪人管理带看记录
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md`
|
||||||
|
- 参考UI_Design文档:`Project/fonrey/UI_DESIGN/客源管理/客源详情_UI.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:带看Tab分"预约"和"带看"两个子Tab;新增带看表单必填字段(带看时间/带看情况≥6字/带看房源≥1套)校验通过才可提交;带看记录以时间线展示,含带看房源蓝色可点击链接和带看进度标签;员工选择器弹层支持组织树搜索和多选;带看房源选择器支持按编号/楼盘/业主关键词搜索
|
||||||
|
|
||||||
|
##### US-CLIENT-008 经纪人管理客源联系人查看新增编辑
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/客源管理/客源管理模块PRD.md` - Story 23:经纪人管理客源联系人
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md`
|
||||||
|
- 参考UI_Design文档:`Project/fonrey/UI_DESIGN/客源管理/客源详情_UI.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:联系人面板默认打码显示电话("+86 135\*\*\*\*\*\*\*\*"),点击「查看号码」后展示完整号码并写入敏感信息跟进日志;新增联系人必填字段(姓名/称呼/电话1)校验;编辑联系人时电话1需点击「查看号码」后才可编辑;保存成功后联系人面板实时刷新
|
||||||
|
|
||||||
|
##### US-CLIENT-009 经纪人修改客源等级
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/客源管理/客源管理模块PRD.md` - Story 17:经纪人修改客源等级
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md`
|
||||||
|
- 参考UI_Design文档:`Project/fonrey/UI_DESIGN/客源管理/客源详情_UI.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:点击「改等级」触发弹窗,展示当前等级(只读)和新等级下拉选择器(A急迫/B较强/C一般/D较弱/E暂不关注);新等级未选择时「确定」按钮置灰;保存成功后信息概览面板等级标签实时更新;操作日志中自动新增"改等级"记录
|
||||||
|
|
||||||
|
##### US-CLIENT-010 经纪人修改客源状态
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/客源管理/客源管理模块PRD.md` - Story 18:经纪人修改客源状态
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md`
|
||||||
|
- 参考UI_Design文档:`Project/fonrey/UI_DESIGN/客源管理/客源详情_UI.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:点击「改状态」触发弹窗,展示当前状态(只读)、新状态下拉(求购/求租/租购)、等级下拉和必填更改理由文本框;新状态未选或理由未填时「确定」按钮置灰;保存成功后信息概览面板状态标签实时更新;操作日志新增"改状态"记录(含更改理由)
|
||||||
|
|
||||||
|
##### US-CLIENT-011 经纪人手动将私客转为公客
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/客源管理/客源管理模块PRD.md` - Story 19:经纪人手动将私客转为公客
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md`
|
||||||
|
- 参考UI_Design文档:`Project/fonrey/UI_DESIGN/客源管理/客源详情_UI.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:点击「转公客」触发弹窗,状态和等级均为必填;确认后客源从私客列表移除并进入公客池(client_type='public',transfer_to_public_type='manual');操作日志新增"转公客"记录(含操作人/操作时间);权限控制:仅归属人、首录人或有管理权限的店长/经理可操作
|
||||||
|
|
||||||
|
##### US-CLIENT-012 经纪人将私客转为成交客
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/客源管理/客源管理模块PRD.md` - Story 20:经纪人将私客转为成交客
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md`
|
||||||
|
- 参考UI_Design文档:`Project/fonrey/UI_DESIGN/客源管理/客源详情_UI.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:点击「转成交」触发"客户成交"弹窗,必填字段(状态/房源类型/成交房源/成交日期/成交价格/成交方)全部填写后「确定」按钮高亮;成交房源选择浮层支持关键词搜索和区域/状态筛选;提交后客源移入成交客列表,状态更新为"成交";操作日志新增"转成交"记录(含成交信息摘要)
|
||||||
|
|
||||||
|
##### US-CLIENT-013 经纪人将客源标记为无效
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/客源管理/客源管理模块PRD.md` - Story 21:经纪人将客源标记为无效
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md`
|
||||||
|
- 参考UI_Design文档:`Project/fonrey/UI_DESIGN/客源管理/客源详情_UI.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:点击「转无效」触发弹窗,展示蓝色提示框说明"将把所有电话标记无效",无效原因单选(号码无效/同行中介/广告推销/客户无意向/其他)默认选中"号码无效";确认后所有联系人电话标记为无效,客源从私客活跃列表移除;操作日志新增"转无效"记录(含无效原因);权限控制:仅归属人、首录人或有管理权限者可操作
|
||||||
|
|
||||||
|
##### US-CLIENT-014 经纪人编辑客源完整信息联系人基础信息需求
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/客源管理/客源管理模块PRD.md` - Story 14:经纪人编辑客源信息
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md`
|
||||||
|
- 参考UI_Design文档:`Project/fonrey/UI_DESIGN/客源管理/编辑客源_UI.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:编辑页面分三个Tab(联系人/基础信息/二手或新房或租房);联系人Tab的电话1需点击「查看号码」后才可编辑,旁边提供「标记无效」链接;基础信息Tab包含需求类型/购房目的/付款方式/名下房产/贷款记录等扩展字段;保存时校验所有必填字段,成功后返回详情页并刷新需求信息区块
|
||||||
|
|
||||||
|
##### US-CLIENT-015 经纪人管理客源相关员工查看编辑归属人首录人
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/客源管理/客源管理模块PRD.md` - Story 24:经纪人管理客源相关员工
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md`
|
||||||
|
- 参考UI_Design文档:`Project/fonrey/UI_DESIGN/客源管理/客源详情_UI.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:相关员工面板展示首录人/归属人的所属门店+小组+姓名及参与时间;点击「编辑」触发弹窗,首录人和归属人均为必填下拉选择器(支持搜索姓名);保存后面板实时更新,操作日志新增"修改相关员工"记录;权限控制:跨团队/跨店修改需店长及以上权限
|
||||||
|
|
||||||
|
##### US-CLIENT-016 系统自动将超时无跟进的私客转为公客
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/客源管理/客源管理模块PRD.md` - 关键业务规则:私客自动转公
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:Celery Beat 定时任务每日凌晨执行;超过运营配置天数(如30天)无跟进且非保护客的私客自动转入公客池(transfer_to_public_type='auto');自动转公后 client_status_logs 生成一条 to_public 记录;即将过期的私客在列表中显示"即将掉公"提示标签
|
||||||
|
|
||||||
|
##### US-CLIENT-017 系统自动检测重复客源并提示
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/客源管理/客源管理模块PRD.md` - Story 2:顶部重复检测提示;关键业务规则:私客手机号唯一性
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:录入/编辑联系人手机号时实时通过phone_hash检测与现有私客/成交客/公客的重复;客源列表顶部实时显示"私客与成交客重复:XX"和"私客与公客重复:XX"蓝色可点击链接;点击重复数字链接可查看重复名单
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 组织人事
|
||||||
|
|
||||||
|
##### US-ORG-001 管理员维护公司组织结构部门门店树
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/组织人事管理/组织人事管理模块PRD.md` - 公司组织结构(部门/门店树)
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_ORG.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:支持新增/编辑/删除部门和门店节点;组织树以层级结构展示(公司→区域→门店→小组);删除有员工的部门时系统提示并阻止操作;组织结构变更实时反映在员工选择器弹层中
|
||||||
|
|
||||||
|
##### US-ORG-002 管理员查看与维护员工列表
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/组织人事管理/组织人事管理模块PRD.md` - 员工列表/员工详情
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_ORG.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:员工列表支持按姓名/手机号关键词搜索;支持按部门/状态筛选;列表展示员工姓名/所属门店/职位/状态等字段;点击员工姓名跳转员工详情页
|
||||||
|
|
||||||
|
##### US-ORG-003 管理员办理员工入职并创建系统账号
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/组织人事管理/组织人事管理模块PRD.md` - 员工入职/账号创建
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_ORG.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:入职表单必填字段(姓名/手机号/所属门店/职位)校验;创建账号后系统自动生成登录密码并可发送给员工;新员工账号立即可登录系统;员工账号与组织树节点正确关联
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 权限管理
|
||||||
|
|
||||||
|
##### US-PERMISSION-001 管理员配置角色预设角色自定义角色
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/权限管理/权限管理模块PRD.md` - 角色管理(预设角色+自定义角色)
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_PERMISSION.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:系统预设角色(经纪人/店长/管理员等)不可删除但可复制;支持创建自定义角色并配置功能权限;角色名称在同租户内唯一;删除自定义角色前需解除所有人员绑定
|
||||||
|
|
||||||
|
##### US-PERMISSION-002 管理员查看与管理人员权限列表
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/权限管理/权限管理模块PRD.md` - 人员权限列表
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_PERMISSION.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:人员权限列表展示员工姓名/所属部门/当前角色;支持按部门/角色筛选;列表支持分页;点击员工行可查看详细权限配置
|
||||||
|
|
||||||
|
##### US-PERMISSION-003 管理员批量为员工分配角色
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/权限管理/权限管理模块PRD.md` - 角色批量分配
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_PERMISSION.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:勾选多名员工后可批量指定角色;批量分配成功后所有选中员工角色立即生效;分配后员工下次登录或刷新页面权限即更新(Redis权限快照失效重载)
|
||||||
|
|
||||||
|
##### US-PERMISSION-004 系统执行功能权限控制菜单级
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/权限管理/权限管理模块PRD.md` - 功能权限(菜单级)
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_PERMISSION.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:无权限的菜单在导航中不展示;直接访问无权限URL返回403页面;权限变更后Redis缓存自动失效,用户下一次请求即应用新权限;经纪人无法访问管理员专属功能页
|
||||||
|
|
||||||
|
##### US-PERMISSION-005 系统执行数据权限控制部门个人全司
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/权限管理/权限管理模块PRD.md` - 数据权限(部门/个人/全司)
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_PERMISSION.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:经纪人只能看到自己名下的房源和客源数据;店长可见本门店所有员工的房源和客源;管理员可见全司数据;不同数据权限级别的用户查询结果严格隔离,不可通过URL参数绕过
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 系统配置
|
||||||
|
|
||||||
|
##### US-SETTING-001 管理员配置房源相关设置字段必填自定义字段标签
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/系统配置/系统配置.md` - 房源设置(字段必填/自定义字段/标签)
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_PUBLIC.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:可配置房源录入表单中哪些字段为必填;可新增自定义字段并在房源表单中展示;标签配置后可在房源筛选中使用;配置变更后房源录入表单实时生效
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 2 - 增强功能(P1,MVP 后第一迭代)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 用户登录
|
||||||
|
|
||||||
|
##### US-ACCOUNT-010 经纪人使用短信验证码登录
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/登录管理/用户登录管理模块PRD.md` - 短信验证码登录
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_LOGIN.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:点击"发送验证码"后60秒内不可重复点击;验证码5分钟内有效;输入正确验证码后登录成功跳转首页;错误验证码给出明确提示
|
||||||
|
|
||||||
|
##### US-ACCOUNT-011 经纪人重置账号密码
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/登录管理/用户登录管理模块PRD.md` - 密码重置
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_LOGIN.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:通过手机号验证码或邮箱链接验证身份;新密码需二次确认且满足强度要求(8位以上含字母+数字);重置成功后原会话立即失效需重新登录;重置操作写入审计日志
|
||||||
|
|
||||||
|
##### US-ACCOUNT-012 系统记住用户登录状态
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/登录管理/用户登录管理模块PRD.md` - 记住登录状态
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_LOGIN.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:勾选"记住我"后关闭浏览器重新打开仍处于登录态;记住登录的有效期为7天;超过有效期自动跳转登录页;管理员可在后台强制让指定账号的所有会话失效
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 楼盘管理
|
||||||
|
|
||||||
|
##### US-COMPLEX-010 管理员管理楼盘照片
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/房源管理/楼盘管理模块PRD.md` - 楼盘照片管理
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_COMPLEX.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:支持上传楼盘封面图和相册图片(格式jpg/png/gif,单文件≤20MB);上传成功后图片在楼盘详情页展示;支持删除图片;楼盘封面图可手动设置
|
||||||
|
|
||||||
|
##### US-COMPLEX-011 管理员维护楼盘价格走势
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/房源管理/楼盘管理模块PRD.md` - 楼盘价格走势
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_COMPLEX.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:楼盘详情页可查看历史价格走势折线图;价格走势数据按月维度展示;支持手动录入或批量导入历史均价数据
|
||||||
|
|
||||||
|
##### US-COMPLEX-012 管理员维护周边配套学校管理
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/房源管理/楼盘管理模块PRD.md` - 周边配套(学校管理)
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_COMPLEX.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:可为楼盘关联周边学校(从学校库选择);学校库支持新增/编辑/删除;楼盘详情页展示关联学校列表;学校数据可在客源意向学校字段中搜索引用
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 房源管理
|
||||||
|
|
||||||
|
##### US-PROPERTY-010 经纪人查看房源维护完成度诊断面板
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/房源管理/房源管理模块PRD.md` - 房源维护完成度(诊断面板)
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_PROPERTY.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:房源详情页展示数据完整度百分比及未填字段提示列表;点击未填字段提示可直接跳转对应编辑区域;完整度≥80%时展示绿色状态,<60%时展示红色警告
|
||||||
|
|
||||||
|
##### US-PROPERTY-011 经纪人管理敏感信息跟进权限控制
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/房源管理/房源管理模块PRD.md` - 敏感信息跟进(查看权限控制)
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_PROPERTY.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:敏感信息跟进Tab仅对有权限的角色可见;查看敏感信息自动写入审计日志(不可删除);无权限用户看到Tab时显示"无权限查看"提示而非隐藏Tab
|
||||||
|
|
||||||
|
##### US-PROPERTY-012 经纪人管理房源附件
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/房源管理/房源管理模块PRD.md` - 附件管理
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_PROPERTY.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:支持上传PDF/Word/Excel等文档类附件(单文件≤50MB);附件按上传时间倒序展示;支持下载和删除附件;附件上传通过Celery异步处理,不阻塞主线程
|
||||||
|
|
||||||
|
##### US-PROPERTY-013 经纪人查看房源市场报盘
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/房源管理/房源管理模块PRD.md` - 市场报盘
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_PROPERTY.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:房源详情页可查看同楼盘其他在售房源的报价分布;展示该楼盘近期成交均价和当前挂牌均价;数据按成交日期倒序展示
|
||||||
|
|
||||||
|
##### US-PROPERTY-014 经纪人查看房源价格解读
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/房源管理/房源管理模块PRD.md` - 价格解读
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_PROPERTY.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:房源详情页展示基于同楼盘/同商圈数据的价格合理性分析;展示当前报价与参考价的偏差百分比;无足够数据时展示"暂无参考数据"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 客源管理
|
||||||
|
|
||||||
|
##### US-CLIENT-020 经纪人使用二手配房功能查看匹配房源
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/客源管理/客源管理模块PRD.md` - Story 11:经纪人使用二手配房功能推荐房源
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md`
|
||||||
|
- 参考UI_Design文档:`Project/fonrey/UI_DESIGN/客源管理/客源详情_UI.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:智能配房Tab分"录客配房"和"系统配房"两个子Tab;录客配房按优质户型/降价/热门/新上四个分组展示房源卡片;每套房源卡片展示封面图/小区名/户型/面积/售价/标签;点击「分享房源」触发房源分享流程;支持「批量分享」多套房源
|
||||||
|
|
||||||
|
##### US-CLIENT-021 经纪人查看客源解读AI行为分析
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/客源管理/客源管理模块PRD.md` - Story 10:经纪人查看客源解读
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md`
|
||||||
|
- 参考UI_Design文档:`Project/fonrey/UI_DESIGN/客源管理/客源详情_UI.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:客源解读Tab展示活跃行为/活跃时间/购房偏好三个模块;购房偏好支持近7日/近30日/近90日三个时间维度切换,切换后数据联动刷新;价格/户型/面积偏好以圆环图+图例形式展示;无数据时展示"暂无数据"而非报错
|
||||||
|
|
||||||
|
##### US-CLIENT-022 经纪人将重点客源收藏至收藏夹
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/客源管理/客源管理模块PRD.md` - Story 16:经纪人收藏客源至私客收藏夹
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md`
|
||||||
|
- 参考UI_Design文档:`Project/fonrey/UI_DESIGN/客源管理/客源详情_UI.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:点击「☆收藏」触发"选择私客收藏夹"浮层,默认选中"默认收藏夹";支持在浮层内创建新收藏夹(名称最多10字,超出「创建」按钮置灰);收藏成功后图标变为实心★橙色;私客列表支持按收藏夹筛选展示
|
||||||
|
|
||||||
|
##### US-CLIENT-023 经纪人通过快捷入口编辑客源基础信息
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/客源管理/客源管理模块PRD.md` - Story 22:经纪人编辑客源基础信息(快捷入口)
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md`
|
||||||
|
- 参考UI_Design文档:`Project/fonrey/UI_DESIGN/客源管理/客源详情_UI.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:点击信息概览面板「编辑客源」入口触发"编辑基础信息"抽屉浮层;浮层包含需求类型/用途/来源(必填)及购房目的/付款方式/名下房产等选填字段;点击「确定」校验必填字段,保存成功后面板相关字段实时更新;点击「取消」或×关闭不保存
|
||||||
|
|
||||||
|
##### US-CLIENT-024 经纪人查看客源操作日志
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/客源管理/客源管理模块PRD.md` - Story 25:经纪人查看客源操作日志
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:点击「查看操作日志」跳转独立日志列表页(面包屑:客源/客源详情/客源操作日志);支持按日期范围/操作人/操作类型筛选;日志列表按操作时间倒序排列,展示操作时间/操作人/操作类型/操作内容;日志为只读,不支持编辑或删除;支持分页(默认20条/页)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 组织人事
|
||||||
|
|
||||||
|
##### US-ORG-010 管理员办理员工离职与调动
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/组织人事管理/组织人事管理模块PRD.md` - 员工离职/调动
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_ORG.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:员工离职后账号立即禁用无法登录;离职员工名下房源和客源可批量转移给其他员工;员工调动后所属部门/组织信息实时更新;调动/离职操作写入异动记录
|
||||||
|
|
||||||
|
##### US-ORG-011 管理员维护员工通讯录
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/组织人事管理/组织人事管理模块PRD.md` - 员工通讯录
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_ORG.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:通讯录支持按姓名/部门搜索;展示员工姓名/职位/手机号/所属门店;手机号默认打码,有权限才可查看完整号码;支持按部门分组展示
|
||||||
|
|
||||||
|
##### US-ORG-012 管理员管理员工职务
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/组织人事管理/组织人事管理模块PRD.md` - 职务管理
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_ORG.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:支持新增/编辑/删除职务(如经纪人/店长/区域经理);职务可关联权限角色;删除有在职员工绑定的职务时系统提示并阻止
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 权限管理
|
||||||
|
|
||||||
|
##### US-PERMISSION-010 管理员配置字段级权限敏感字段可见性
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/权限管理/权限管理模块PRD.md` - 字段级权限(敏感字段可见性)
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_PERMISSION.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:可为不同角色配置联系人手机号/证件号码等敏感字段的可见性;无查看权限的角色访问时号码始终打码,无法点击查看;查看敏感字段操作记录在审计日志中;字段级权限配置变更后Redis缓存立即失效
|
||||||
|
|
||||||
|
##### US-PERMISSION-011 管理员配置个人特定权限覆盖
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/权限管理/权限管理模块PRD.md` - 个人特定权限覆盖
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_PERMISSION.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:支持在角色权限基础上为特定员工单独开启或关闭特定权限点;个人覆盖权限优先级高于角色权限;个人权限覆盖配置记录可查看和删除
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 系统配置
|
||||||
|
|
||||||
|
##### US-SETTING-010 管理员配置首页展示内容
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/系统配置/系统配置.md` - 首页设置
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_PUBLIC.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:可配置首页展示的统计数据卡片(如今日新增房源/客源数量);配置变更后首页实时生效;不同角色可配置不同的首页视图
|
||||||
|
|
||||||
|
##### US-SETTING-011 管理员配置相关方规则
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/系统配置/系统配置.md` - 相关方设置
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_PUBLIC.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:可配置房源/客源的相关方角色(如协作人/跟进人)及其权限范围;相关方配置影响房源/客源详情页的相关员工区块展示
|
||||||
|
|
||||||
|
##### US-SETTING-012 管理员配置客源相关参数
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/系统配置/系统配置.md` - 客源设置(基本配置/参数配置)
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_PUBLIC.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:可配置私客自动转公客的天数阈值;可配置客源来源枚举值(lookup_items);可配置活跃度计算的各阈值天数;配置变更后Celery定时任务下次执行时使用新配置
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 系统管理(运营后台)
|
||||||
|
|
||||||
|
##### US-SYSTEM-010 平台管理员管理租户开通暂停配置
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/系统管理/系统管理模块PRD.md` - 租户管理(开通/暂停/配置)
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:可在运营后台新开通租户(自动创建独立PostgreSQL Schema);可暂停租户(暂停后租户用户无法登录);可为租户配置域名/子域名;租户操作记录写入平台操作日志
|
||||||
|
|
||||||
|
##### US-SYSTEM-011 平台管理员监控系统健康状态
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/系统管理/系统管理模块PRD.md` - 系统健康监控
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:运营后台展示系统核心指标(API响应时间/错误率/Celery队列积压);Sentry错误告警正常接收;Grafana面板可查看历史监控数据;关键指标超阈值时触发告警通知
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 客户端发布
|
||||||
|
|
||||||
|
##### US-RELEASE-010 系统发布Windows桌面客户端安装包
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/发布管理/客户端发布管理模块PRD.md` - Windows桌面客户端
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:electron-builder 输出 NSIS .exe 安装包和便携版 .zip;安装包经EV证书签名,安装时无SmartScreen警告;安装包上传至Cloudflare R2并通过CDN分发;后端 ClientRelease 表新增一条版本记录
|
||||||
|
|
||||||
|
##### US-RELEASE-011 客户端自动检测并更新至最新版本
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/发布管理/客户端发布管理模块PRD.md` - 自动更新机制
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:客户端启动时及每4小时自动检测 GET /api/client/updates/latest/ 接口;有新版本时后台静默下载,下载完成后提示用户重启;下载完成后校验SHA256与服务端返回一致才允许安装;强制更新标记时用户无法跳过更新
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 3 - 路线图功能(P2,已规划未排期)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 房源管理
|
||||||
|
|
||||||
|
##### US-PROPERTY-020 经纪人录入别墅商铺商住写字楼其他类型房源
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/房源管理/房源管理模块PRD.md` - 录入别墅/商铺/商住/写字楼/其他
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:(规划中,详细验收标准待PRD细化后补充)
|
||||||
|
|
||||||
|
##### US-PROPERTY-021 经纪人查看全部商铺写字楼列表
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/房源管理/房源管理模块PRD.md` - 全部商铺列表/全部写字楼列表
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:(规划中,详细验收标准待PRD细化后补充)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 楼盘管理
|
||||||
|
|
||||||
|
##### US-COMPLEX-020 管理员使用应用数据标准功能
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/房源管理/楼盘管理模块PRD.md` - 应用数据标准
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:(规划中,详细验收标准待PRD细化后补充)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 客源管理
|
||||||
|
|
||||||
|
##### US-CLIENT-030 经纪人查看与管理公客列表
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/客源管理/客源管理模块PRD.md` - Story 12:经纪人查看与筛选公客列表
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:(规划中,详细验收标准待PRD细化后补充)
|
||||||
|
|
||||||
|
##### US-CLIENT-031 经纪人查看与管理成交客列表
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/客源管理/客源管理模块PRD.md` - Story 13:经纪人查看成交客列表
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:(规划中,详细验收标准待PRD细化后补充)
|
||||||
|
|
||||||
|
##### US-CLIENT-032 经纪人管理暂缓私客
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/客源管理/客源管理模块PRD.md` - Story 5:经纪人管理暂缓私客
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:(规划中,详细验收标准待PRD细化后补充)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 组织人事
|
||||||
|
|
||||||
|
##### US-ORG-020 管理员查看员工异动记录
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/组织人事管理/组织人事管理模块PRD.md` - 异动记录
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_ORG.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:(规划中,详细验收标准待PRD细化后补充)
|
||||||
|
|
||||||
|
##### US-ORG-021 管理员管理员工奖惩记录
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/组织人事管理/组织人事管理模块PRD.md` - 奖惩记录
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_ORG.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:(规划中,详细验收标准待PRD细化后补充)
|
||||||
|
|
||||||
|
##### US-ORG-022 管理员查看门店分布地图
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/组织人事管理/组织人事管理模块PRD.md` - 门店分布地图
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_ORG.md`
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:(规划中,详细验收标准待PRD细化后补充)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 系统配置
|
||||||
|
|
||||||
|
##### US-SETTING-020 管理员配置人事OA相关参数
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/系统配置/系统配置.md` - 人事OA设置
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:(规划中,详细验收标准待PRD细化后补充)
|
||||||
|
|
||||||
|
##### US-SETTING-021 管理员配置交易规则
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/系统配置/系统配置.md` - 交易设置
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:(规划中,详细验收标准待PRD细化后补充)
|
||||||
|
|
||||||
|
##### US-SETTING-022 管理员配置财务规则
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/系统配置/系统配置.md` - 财务设置
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:(规划中,详细验收标准待PRD细化后补充)
|
||||||
|
|
||||||
|
##### US-SETTING-023 管理员配置合同模板
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/系统配置/系统配置.md` - 合同设置
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:(规划中,详细验收标准待PRD细化后补充)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 系统管理(运营后台)
|
||||||
|
|
||||||
|
##### US-SYSTEM-020 平台管理员查看操作审计日志
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/系统管理/系统管理模块PRD.md` - 操作审计日志
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:(规划中,详细验收标准待PRD细化后补充)
|
||||||
|
|
||||||
|
##### US-SYSTEM-021 平台管理员管理灰度发布滚动升级
|
||||||
|
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/系统管理/系统管理模块PRD.md` - 灰度发布/滚动升级
|
||||||
|
- 状态:[ ]
|
||||||
|
- 验收标准:(规划中,详细验收标准待PRD细化后补充)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 4 - 明确不做(Out of Scope)
|
||||||
|
|
||||||
|
> 以下功能在 MVP 阶段及近期版本路线图中明确不实现,仅作备忘。
|
||||||
|
|
||||||
|
<!-- OUT OF SCOPE: 移动端适配 - v2 规划 -->
|
||||||
|
<!-- OUT OF SCOPE: 新房模块(新房管理/新房设置)- 独立模块,后续版本 -->
|
||||||
|
<!-- OUT OF SCOPE: 合同管理模块 - 独立模块,后续版本 -->
|
||||||
|
<!-- OUT OF SCOPE: 财务管理/提成结算 - 独立模块,后续版本 -->
|
||||||
|
<!-- OUT OF SCOPE: 三网发布(安居客/链家/贝壳对接)- 独立模块,后续版本 -->
|
||||||
|
<!-- OUT OF SCOPE: 数据报表/行程量化 - 独立模块,后续版本 -->
|
||||||
|
<!-- OUT OF SCOPE: 在线充值/增值服务 - 独立模块,后续版本 -->
|
||||||
|
<!-- OUT OF SCOPE: 任务管理(OA任务/入职祝福)- 低优先 -->
|
||||||
|
<!-- OUT OF SCOPE: 考勤管理 - 独立 HR 模块 -->
|
||||||
|
<!-- OUT OF SCOPE: 审批流程 - 独立 OA 模块 -->
|
||||||
|
<!-- OUT OF SCOPE: 智慧大屏 / VR换装 - 增值产品 -->
|
||||||
|
<!-- OUT OF SCOPE: 房源广场(跨租户公共池)- 多租户复杂场景 -->
|
||||||
|
<!-- OUT OF SCOPE: 资料客详细功能 - 后续版本规划 -->
|
||||||
|
<!-- OUT OF SCOPE: 营销客详细功能(含端口发布/朋友圈分享)- 营销模块另行规划 -->
|
||||||
|
<!-- OUT OF SCOPE: AI 智能推荐引擎自研 - 基础版基于规则匹配实现 -->
|
||||||
|
<!-- OUT OF SCOPE: 客源数据对外 API 开放 - 接口规范另行设计 -->
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 已完成
|
||||||
|
|
||||||
|
(暂无)
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -54,15 +54,15 @@
|
|||||||
```
|
```
|
||||||
fonrey/
|
fonrey/
|
||||||
├── apps/
|
├── apps/
|
||||||
│ ├── tenants/ # django-tenants 配置(shared_apps)
|
│ ├── tenant/ # django-tenants 配置(shared_apps)
|
||||||
│ ├── accounts/ # 登录认证(详见 登录管理技术方案.md)
|
│ ├── account/ # 登录认证(详见 登录管理技术方案.md)
|
||||||
│ ├── permissions/ # 权限管理(详见 权限管理系统技术方案.md)
|
│ ├── permission/ # 权限管理(详见 权限管理系统技术方案.md)
|
||||||
│ ├── org/ # 组织人事(org_units, staff)
|
│ ├── org/ # 组织人事(org_units, staff)
|
||||||
│ ├── region/ # 区域管理(districts, business_areas, metro)
|
│ ├── region/ # 区域管理(districts, business_areas, metro)
|
||||||
│ ├── complex/ # 楼盘管理(complexes, buildings, schools)
|
│ ├── complex/ # 楼盘管理(complexes, buildings, schools)
|
||||||
│ ├── property/ # 房源核心(含 models/services/tasks 三层)
|
│ ├── property/ # 房源核心(含 models/services/tasks 三层)
|
||||||
│ ├── client/ # 客源管理
|
│ ├── client/ # 客源管理
|
||||||
│ ├── settings/ # 系统设置(lookup, tags)
|
│ ├── setting/ # 系统设置(lookup, tags)
|
||||||
│ └── release/ # 客户端发布管理(shared_apps)
|
│ └── release/ # 客户端发布管理(shared_apps)
|
||||||
├── shared/ # 公共 Schema App
|
├── shared/ # 公共 Schema App
|
||||||
└── core/
|
└── core/
|
||||||
@@ -144,10 +144,51 @@ apps/property/
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 9. 文档维护原则
|
## 9. 测试策略
|
||||||
|
|
||||||
|
> **完整测试规范**见:[`测试规范.md`](./测试规范.md)。本节仅列关键结论。
|
||||||
|
|
||||||
|
Fonrey 采用 AI vibe coding 模式开发,测试是保证每日迭代质量的唯一安全网。**每个 P0 User Story 完成后,对应测试必须同步产出,不允许欠测试债。**
|
||||||
|
|
||||||
|
### 测试分层
|
||||||
|
|
||||||
|
| 层级 | 工具 | 覆盖目标 | 运行频率 |
|
||||||
|
|------|------|---------|---------|
|
||||||
|
| **单元测试** | `pytest-django` + `factory_boy` | `core/`、`services/`、`tasks.py` | 每次 push |
|
||||||
|
| **集成测试** | `pytest-django` TenantClient | 所有 P0 User Story 的 HTTP 接口 | 每次 push |
|
||||||
|
| **E2E 测试** | `playwright` (Python) | 5 条核心用户旅程 | 每日定时 |
|
||||||
|
|
||||||
|
### 关键约定
|
||||||
|
|
||||||
|
- 所有集成测试必须使用 `django-tenants` 的 `TenantClient`,禁止使用 Django 原生 `Client()`
|
||||||
|
- HTMX 局部请求测试须携带 `HTTP_HX_REQUEST: true` header,并验证返回局部 HTML 而非完整页面
|
||||||
|
- Celery 任务测试使用 `CELERY_TASK_ALWAYS_EAGER = True` 同步执行
|
||||||
|
- 外部服务(R2、Redis、邮件)在测试中全部 Mock,禁止真实调用
|
||||||
|
- 每个受权限保护的 View,必须覆盖:有权限(200)、无权限(403)、未登录(302)三个场景
|
||||||
|
|
||||||
|
### 覆盖率基准
|
||||||
|
|
||||||
|
| 模块 | 最低目标 |
|
||||||
|
|------|---------|
|
||||||
|
| `core/` 核心基础模块 | ≥ 90% |
|
||||||
|
| `apps/*/services/` 业务逻辑层 | ≥ 80% |
|
||||||
|
| `apps/*/views.py` 视图层 | ≥ 70% |
|
||||||
|
| E2E 核心用户旅程(5 条) | 100% 通过 |
|
||||||
|
|
||||||
|
### CI 自动化
|
||||||
|
|
||||||
|
- 每次 push 到 `main` / `develop` 自动运行单元测试 + 集成测试
|
||||||
|
- 每日北京时间凌晨 2 点自动运行全量套件(含 E2E)
|
||||||
|
- 配置文件:`.github/workflows/daily-test.yml`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. 文档维护原则
|
||||||
|
|
||||||
- 本文档仅记录**跨模块共识**与**模块索引**,不展开模块细节
|
- 本文档仅记录**跨模块共识**与**模块索引**,不展开模块细节
|
||||||
- 模块技术方案在子文档中维护,并通过 §8 表格回链
|
- 模块技术方案在子文档中维护,并通过 §8 表格回链
|
||||||
- 任何技术栈变更(替换组件、升级主版本、新增外部服务)须同步更新本文档 §2、§5、§6
|
- 任何技术栈变更(替换组件、升级主版本、新增外部服务)须同步更新本文档 §2、§5、§6
|
||||||
- 新增模块时,先在 §4 目录结构补位,再在 §8 索引登记子文档
|
- 新增模块时,先在 §4 目录结构补位,再在 §8 索引登记子文档
|
||||||
|
- 测试规范变更须同步更新 §9 关键结论,完整细节在 [`测试规范.md`](./测试规范.md) 中维护
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
611
Project/fonrey/TECH_STACK/测试规范.md
Normal file
611
Project/fonrey/TECH_STACK/测试规范.md
Normal file
@@ -0,0 +1,611 @@
|
|||||||
|
# Fonrey 测试规范(TEST_SPEC)
|
||||||
|
|
||||||
|
> **For AI assistants**: Read this entire file before writing any test 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.
|
||||||
|
|
||||||
|
**版本**: 1.0 | **最后更新**: 2026-04-26
|
||||||
|
**定位**: 本文档定义 Fonrey 项目的完整测试策略,包含测试分层、工具选型、目录结构、多租户测试约定、HTMX 测试约定、CI 自动化配置及 AI 辅助编码时的测试要求。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 测试目标
|
||||||
|
|
||||||
|
Fonrey 采用 AI vibe coding 模式开发,AI 负责生成功能代码,**测试是保证每日迭代质量的唯一安全网**。测试体系须满足:
|
||||||
|
|
||||||
|
- 每个 P0 User Story 完成后,对应测试同步产出
|
||||||
|
- 每日自动运行全量测试套件,输出可读报告
|
||||||
|
- 测试失败时,AI 可根据报告自主定位并修复问题
|
||||||
|
- 测试环境与生产环境技术栈完全一致(同样使用 PostgreSQL + django-tenants)
|
||||||
|
|
||||||
|
**覆盖率基准目标**:
|
||||||
|
|
||||||
|
| 层级 | 最低目标 |
|
||||||
|
|------|---------|
|
||||||
|
| `core/` 核心基础模块 | ≥ 90% |
|
||||||
|
| `apps/*/services/` 业务逻辑层 | ≥ 80% |
|
||||||
|
| `apps/*/views.py` 视图层 | ≥ 70% |
|
||||||
|
| `apps/*/tasks.py` 异步任务 | ≥ 70% |
|
||||||
|
| E2E 核心用户旅程 | 5 条必须全部通过 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 测试分层架构
|
||||||
|
|
||||||
|
Fonrey 采用三层测试体系,从底层向上覆盖:
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────┐
|
||||||
|
│ E2E 测试(用户行为模拟) │ ← Playwright
|
||||||
|
│ 覆盖:5 条核心用户旅程 │
|
||||||
|
├─────────────────────────────────────────┤
|
||||||
|
│ 集成测试(API / View 层) │ ← pytest-django TenantClient
|
||||||
|
│ 覆盖:所有 P0 User Story 的 HTTP 接口 │
|
||||||
|
├─────────────────────────────────────────┤
|
||||||
|
│ 单元测试(逻辑单元) │ ← pytest-django + factory_boy
|
||||||
|
│ 覆盖:core/、services/、tasks.py │
|
||||||
|
└─────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
**三层分工原则**:
|
||||||
|
|
||||||
|
- **单元测试**:不启动 HTTP server,不依赖浏览器,速度最快;测试单一函数/类的逻辑正确性
|
||||||
|
- **集成测试**:使用 Django 测试客户端,验证完整请求-响应链路(View → Service → DB);不启动真实 HTTP server
|
||||||
|
- **E2E 测试**:启动真实 Django dev server,用浏览器驱动验证真实用户操作流程;速度最慢,只覆盖核心旅程
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 工具选型
|
||||||
|
|
||||||
|
### 3.1 工具清单
|
||||||
|
|
||||||
|
| 类型 | 工具 | 版本 | 用途 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| 测试框架 | `pytest` | ≥ 8.x | 统一测试运行器 |
|
||||||
|
| Django 集成 | `pytest-django` | ≥ 4.x | Django 数据库、Client、设置管理 |
|
||||||
|
| 测试数据工厂 | `factory_boy` | ≥ 3.x | 创建测试用 Model 实例,避免手写 fixture |
|
||||||
|
| 假数据生成 | `Faker` | ≥ 25.x | 生成中文姓名、手机号、地址等假数据 |
|
||||||
|
| Mock 工具 | `pytest-mock` | ≥ 3.x | Mock 外部依赖(R2、Redis、邮件服务) |
|
||||||
|
| HTTP Mock | `responses` | ≥ 0.25.x | Mock 第三方 HTTP 请求(Cloudflare API 等) |
|
||||||
|
| E2E 测试 | `playwright` (Python) | ≥ 1.44.x | 浏览器自动化 |
|
||||||
|
| E2E 集成 | `pytest-playwright` | ≥ 0.5.x | Playwright 的 pytest 插件 |
|
||||||
|
| 覆盖率 | `pytest-cov` | ≥ 5.x | 生成代码覆盖率报告 |
|
||||||
|
| 并行加速 | `pytest-xdist` | ≥ 3.x | 多进程并行运行单元/集成测试 |
|
||||||
|
|
||||||
|
### 3.2 安装依赖
|
||||||
|
|
||||||
|
所有测试依赖统一放在 `requirements/test.txt`:
|
||||||
|
|
||||||
|
```
|
||||||
|
pytest>=8.0
|
||||||
|
pytest-django>=4.8
|
||||||
|
pytest-mock>=3.12
|
||||||
|
pytest-cov>=5.0
|
||||||
|
pytest-xdist>=3.5
|
||||||
|
pytest-playwright>=0.5
|
||||||
|
factory_boy>=3.3
|
||||||
|
Faker>=25.0
|
||||||
|
responses>=0.25
|
||||||
|
```
|
||||||
|
|
||||||
|
安装命令:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install -r requirements/test.txt
|
||||||
|
playwright install chromium
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 目录结构
|
||||||
|
|
||||||
|
```
|
||||||
|
fonrey/
|
||||||
|
└── tests/
|
||||||
|
├── conftest.py # 全局 fixtures(租户、用户、客户端)
|
||||||
|
├── settings_test.py # 测试专用 Django settings
|
||||||
|
├── factories/ # factory_boy 工厂
|
||||||
|
│ ├── __init__.py
|
||||||
|
│ ├── tenant_factory.py # Tenant、域名
|
||||||
|
│ ├── account_factory.py # Staff、Account
|
||||||
|
│ ├── org_factory.py # OrgUnit
|
||||||
|
│ ├── permission_factory.py # Role、Permission
|
||||||
|
│ ├── complex_factory.py # Complex、Building
|
||||||
|
│ ├── property_factory.py # Property、FollowUpLog
|
||||||
|
│ └── client_factory.py # Client、ClientFollowUp
|
||||||
|
├── unit/ # 单元测试
|
||||||
|
│ ├── test_encryption.py # PII 加密/解密
|
||||||
|
│ ├── test_soft_delete.py # 软删除 Manager
|
||||||
|
│ ├── test_permission_service.py
|
||||||
|
│ ├── test_property_service.py
|
||||||
|
│ ├── test_client_service.py
|
||||||
|
│ └── test_celery_tasks.py # Celery 任务(同步模式)
|
||||||
|
├── integration/ # 集成测试(按 User Story 分文件)
|
||||||
|
│ ├── account/
|
||||||
|
│ │ └── test_us_account.py # US-ACCOUNT-001~003
|
||||||
|
│ ├── permission/
|
||||||
|
│ │ └── test_us_permission.py # US-PERMISSION-001~005
|
||||||
|
│ ├── complex/
|
||||||
|
│ │ └── test_us_complex.py
|
||||||
|
│ ├── property/
|
||||||
|
│ │ └── test_us_property.py # US-PROPERTY-001~008
|
||||||
|
│ ├── client/
|
||||||
|
│ │ └── test_us_client.py # US-CLIENT-001~017
|
||||||
|
│ ├── org/
|
||||||
|
│ │ └── test_us_org.py
|
||||||
|
│ └── setting/
|
||||||
|
│ └── test_us_setting.py
|
||||||
|
└── e2e/ # E2E 测试(核心用户旅程)
|
||||||
|
├── conftest.py # E2E 专用 fixtures(live_server、page)
|
||||||
|
├── test_journey_login.py
|
||||||
|
├── test_journey_property.py
|
||||||
|
├── test_journey_client.py
|
||||||
|
├── test_journey_permission.py
|
||||||
|
└── test_journey_onboarding.py
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 多租户测试约定
|
||||||
|
|
||||||
|
这是 Fonrey 测试中最重要的约定。`django-tenants` 的 Schema 隔离在测试中必须正确处理,否则测试结果不可信。
|
||||||
|
|
||||||
|
### 5.1 核心原则
|
||||||
|
|
||||||
|
- **所有集成测试和单元测试**(涉及数据库的)必须在租户 Schema 上下文中执行
|
||||||
|
- 严禁在 `public` Schema 下直接操作业务数据
|
||||||
|
- 每个测试函数执行后,数据库状态自动回滚(`pytest-django` 的 `db` fixture 保证事务隔离)
|
||||||
|
- 禁止测试之间共享可变状态(禁止 `module` 或 `session` 级别的数据库 fixtures,除非明确只读)
|
||||||
|
|
||||||
|
### 5.2 租户 Fixture 规范
|
||||||
|
|
||||||
|
全局 `conftest.py` 必须提供以下标准 fixtures:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# tests/conftest.py(规范示意,非最终代码)
|
||||||
|
|
||||||
|
@pytest.fixture(scope="session")
|
||||||
|
def tenant():
|
||||||
|
"""
|
||||||
|
创建一个测试租户(session 级别,全程复用同一个 Schema)。
|
||||||
|
使用 django_tenants.test.client.TenantClient 配套使用。
|
||||||
|
"""
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def tenant_client(tenant):
|
||||||
|
"""
|
||||||
|
返回绑定到测试租户的 TenantClient 实例。
|
||||||
|
等价于 Django 的 Client(),但自动切换到租户 Schema。
|
||||||
|
所有集成测试的 HTTP 请求必须通过此 client 发出。
|
||||||
|
"""
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def staff_user(tenant):
|
||||||
|
"""普通员工用户,已完成登录态(含 Cookie/Session)"""
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def admin_user(tenant):
|
||||||
|
"""系统管理员用户"""
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def authenticated_client(tenant_client, staff_user):
|
||||||
|
"""已登录状态的 TenantClient"""
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.3 禁止事项
|
||||||
|
|
||||||
|
- ❌ 禁止在测试中使用 Django 原生 `Client()`,必须使用 `TenantClient`
|
||||||
|
- ❌ 禁止在测试中手动 `SET search_path`,由 fixtures 统一管理
|
||||||
|
- ❌ 禁止跨租户数据访问断言(每个测试只能操作自己的租户数据)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 单元测试规范
|
||||||
|
|
||||||
|
### 6.1 适用范围
|
||||||
|
|
||||||
|
单元测试覆盖以下代码,**不依赖 HTTP 请求,速度要求 < 100ms/个**:
|
||||||
|
|
||||||
|
| 目标代码 | 测试文件位置 |
|
||||||
|
|---------|------------|
|
||||||
|
| `core/encryption.py` | `tests/unit/test_encryption.py` |
|
||||||
|
| `core/models/base.py`(软删除、ActiveManager) | `tests/unit/test_soft_delete.py` |
|
||||||
|
| `apps/*/services/` 所有 service 函数 | `tests/unit/test_*_service.py` |
|
||||||
|
| `apps/*/tasks.py` Celery 任务 | `tests/unit/test_celery_tasks.py` |
|
||||||
|
| `core/cache.py` Redis key 工具函数 | `tests/unit/test_cache.py` |
|
||||||
|
|
||||||
|
### 6.2 factory_boy 规范
|
||||||
|
|
||||||
|
每个 Django Model 必须有对应的 Factory,集中放在 `tests/factories/` 下:
|
||||||
|
|
||||||
|
- Factory 类名统一为 `{ModelName}Factory`
|
||||||
|
- 使用 `faker` 生成中文假数据(姓名、手机号、地址)
|
||||||
|
- 手机号字段必须使用未加密的明文值传入 factory(factory 内部触发 Model 的加密逻辑)
|
||||||
|
- Factory 之间通过 `SubFactory` 表达依赖关系,禁止在 Factory 内部硬编码 ID
|
||||||
|
|
||||||
|
### 6.3 Celery 任务测试规范
|
||||||
|
|
||||||
|
所有 Celery 任务测试必须在同步模式下运行,在 `settings_test.py` 中配置:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# tests/settings_test.py
|
||||||
|
CELERY_TASK_ALWAYS_EAGER = True # 任务同步执行
|
||||||
|
CELERY_TASK_EAGER_PROPAGATES = True # 同步模式下抛出真实异常
|
||||||
|
```
|
||||||
|
|
||||||
|
调用方式统一使用 `.apply()` 而非 `.delay()` 或 `.apply_async()`:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# 正确
|
||||||
|
result = my_task.apply(args=[...])
|
||||||
|
|
||||||
|
# 禁止在测试中使用
|
||||||
|
my_task.delay(...)
|
||||||
|
my_task.apply_async(...)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.4 PII 加密测试要求
|
||||||
|
|
||||||
|
`test_encryption.py` 必须覆盖以下场景:
|
||||||
|
|
||||||
|
- 加密后的密文与明文不同
|
||||||
|
- 相同明文每次加密产生不同密文(GCM nonce 随机性)
|
||||||
|
- 解密后的明文与原始明文完全一致
|
||||||
|
- 加密字段的 SHA-256 hash 索引值具有确定性(相同明文产生相同 hash)
|
||||||
|
- 解密错误(篡改密文)抛出可识别异常
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 集成测试规范
|
||||||
|
|
||||||
|
### 7.1 适用范围
|
||||||
|
|
||||||
|
集成测试覆盖完整的 HTTP 请求-响应链路,每个 P0 User Story 至少对应一个集成测试文件。
|
||||||
|
|
||||||
|
### 7.2 HTMX 请求约定
|
||||||
|
|
||||||
|
Fonrey 的 View 层分为两种响应模式,测试必须对应覆盖:
|
||||||
|
|
||||||
|
| 请求类型 | Header | 预期响应 |
|
||||||
|
|---------|--------|---------|
|
||||||
|
| 普通页面请求 | 无 | 完整 HTML(含 `<html>`, `<head>`, `<body>`) |
|
||||||
|
| HTMX 局部请求 | `HTTP_HX_REQUEST: true` | 局部 HTML 片段(不含完整页面结构) |
|
||||||
|
|
||||||
|
HTMX 请求在 `TenantClient` 中发送方式:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# HTMX 局部请求(规范示意)
|
||||||
|
response = authenticated_client.get(
|
||||||
|
'/properties/',
|
||||||
|
HTTP_HX_REQUEST='true'
|
||||||
|
)
|
||||||
|
|
||||||
|
# 验证返回局部 HTML(不含完整页面标签)
|
||||||
|
assert '<html' not in response.content.decode()
|
||||||
|
assert response.status_code == 200
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.3 权限验证覆盖要求
|
||||||
|
|
||||||
|
每个受权限保护的 View,集成测试必须覆盖以下场景(缺一不可):
|
||||||
|
|
||||||
|
1. **有权限用户**:返回 200,响应内容符合预期
|
||||||
|
2. **无权限用户**:返回 403
|
||||||
|
3. **未登录用户**:返回 302 重定向到登录页
|
||||||
|
4. **数据域隔离**(如适用):只能看到自己权限范围内的数据
|
||||||
|
|
||||||
|
### 7.4 P0 User Story 测试覆盖映射
|
||||||
|
|
||||||
|
每个 User Story 的集成测试须覆盖其 **验收标准(Acceptance Criteria)** 中的所有条目:
|
||||||
|
|
||||||
|
| User Story 文件 | 集成测试文件 |
|
||||||
|
|----------------|------------|
|
||||||
|
| US-ACCOUNT-001~003 | `tests/integration/account/test_us_account.py` |
|
||||||
|
| US-PERMISSION-001~005 | `tests/integration/permission/test_us_permission.py` |
|
||||||
|
| US-COMPLEX-001~003 | `tests/integration/complex/test_us_complex.py` |
|
||||||
|
| US-PROPERTY-001~008 | `tests/integration/property/test_us_property.py` |
|
||||||
|
| US-CLIENT-001~017 | `tests/integration/client/test_us_client.py` |
|
||||||
|
| US-ORG-001~003 | `tests/integration/org/test_us_org.py` |
|
||||||
|
| US-SETTING-001 | `tests/integration/setting/test_us_setting.py` |
|
||||||
|
|
||||||
|
### 7.5 外部服务 Mock 规范
|
||||||
|
|
||||||
|
集成测试中必须 Mock 所有外部 I/O,禁止真实调用:
|
||||||
|
|
||||||
|
| 外部依赖 | Mock 方式 |
|
||||||
|
|---------|---------|
|
||||||
|
| Cloudflare R2 文件上传 | `pytest-mock` mock `boto3.client` |
|
||||||
|
| Redis | 使用 `fakeredis` 替代真实 Redis |
|
||||||
|
| 邮件发送 | Django `django.test.utils.override_settings(EMAIL_BACKEND='django.core.mail.backends.locmem.EmailBackend')` |
|
||||||
|
| Celery 任务 | `CELERY_TASK_ALWAYS_EAGER=True`(见 §6.3) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. E2E 测试规范
|
||||||
|
|
||||||
|
### 8.1 适用范围与原则
|
||||||
|
|
||||||
|
E2E 测试成本高、速度慢,**只覆盖核心用户旅程,不追求全覆盖**。以下 5 条旅程为必须通过项,任意一条失败即视为阻塞级问题:
|
||||||
|
|
||||||
|
| # | 旅程名称 | 对应模块 |
|
||||||
|
|---|---------|---------|
|
||||||
|
| J-01 | 登录 → 进入首页 | 登录管理 |
|
||||||
|
| J-02 | 录入房源 → 上传照片 → 查看列表 | 房源管理 |
|
||||||
|
| J-03 | 录入客源 → 添加跟进记录 | 客源管理 |
|
||||||
|
| J-04 | 无权限员工访问受限页面 → 看到 403 提示 | 权限管理 |
|
||||||
|
| J-05 | 管理员创建员工 → 分配角色 → 新员工登录验证 | 组织人事 + 权限 |
|
||||||
|
|
||||||
|
### 8.2 Playwright 技术约定
|
||||||
|
|
||||||
|
- 浏览器:仅使用 Chromium(与 Electron 内核一致)
|
||||||
|
- 运行模式:CI 环境用 `headless=True`;本地调试可用 `headless=False`
|
||||||
|
- 等待策略:**禁止使用 `page.wait_for_timeout()`(固定等待)**,必须使用语义等待:
|
||||||
|
- `page.wait_for_url(pattern)` — 等待导航完成
|
||||||
|
- `expect(locator).to_be_visible()` — 等待元素出现
|
||||||
|
- `page.wait_for_load_state('networkidle')` — 等待 HTMX 请求完成
|
||||||
|
- 选择器优先级:`role` > `text` > `placeholder` > `data-testid` > CSS 选择器(可维护性从高到低)
|
||||||
|
- 断言使用 `expect()` 而非原生 `assert`,获得更清晰的错误输出
|
||||||
|
|
||||||
|
### 8.3 HTMX 页面的 E2E 注意事项
|
||||||
|
|
||||||
|
HTMX 局部更新后,DOM 发生变化但页面 URL 可能不变。等待策略:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# 触发 HTMX 请求后,等待网络空闲(HTMX 请求完成)
|
||||||
|
page.click('button:has-text("筛选")')
|
||||||
|
page.wait_for_load_state('networkidle')
|
||||||
|
# 再断言 DOM 内容
|
||||||
|
expect(page.locator('.property-list')).to_contain_text('...')
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8.4 E2E 测试数据管理
|
||||||
|
|
||||||
|
- E2E 测试使用独立的测试租户(在 `tests/e2e/conftest.py` 中创建)
|
||||||
|
- 每次 E2E 测试套件运行前,重置测试租户数据至初始种子状态
|
||||||
|
- 禁止 E2E 测试依赖其他 E2E 测试的产出数据(每条旅程测试自行准备数据)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. 测试配置文件
|
||||||
|
|
||||||
|
### 9.1 pytest.ini
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[pytest]
|
||||||
|
DJANGO_SETTINGS_MODULE = tests.settings_test
|
||||||
|
python_files = test_*.py
|
||||||
|
python_classes = Test*
|
||||||
|
python_functions = test_*
|
||||||
|
addopts =
|
||||||
|
--tb=short
|
||||||
|
--strict-markers
|
||||||
|
-q
|
||||||
|
markers =
|
||||||
|
unit: 单元测试(不访问数据库)
|
||||||
|
integration: 集成测试(访问数据库,使用 TenantClient)
|
||||||
|
e2e: E2E 测试(启动真实服务,需要浏览器)
|
||||||
|
slow: 耗时超过 5 秒的测试
|
||||||
|
```
|
||||||
|
|
||||||
|
### 9.2 tests/settings_test.py 关键配置
|
||||||
|
|
||||||
|
```python
|
||||||
|
# 继承主 settings,覆盖以下配置
|
||||||
|
|
||||||
|
DATABASES = {
|
||||||
|
# 使用独立的测试数据库(CI 中由环境变量注入)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Celery 同步模式
|
||||||
|
CELERY_TASK_ALWAYS_EAGER = True
|
||||||
|
CELERY_TASK_EAGER_PROPAGATES = True
|
||||||
|
|
||||||
|
# 使用内存缓存(避免依赖真实 Redis)
|
||||||
|
CACHES = {
|
||||||
|
'default': {
|
||||||
|
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# 邮件使用内存后端
|
||||||
|
EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
|
||||||
|
|
||||||
|
# 文件存储使用本地临时目录(非 R2)
|
||||||
|
DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage'
|
||||||
|
MEDIA_ROOT = '/tmp/fonrey_test_media/'
|
||||||
|
|
||||||
|
# 关闭密码哈希加速(测试中不需要高强度 hash)
|
||||||
|
PASSWORD_HASHERS = ['django.contrib.auth.hashers.MD5PasswordHasher']
|
||||||
|
|
||||||
|
# 禁用 DEBUG(贴近生产环境)
|
||||||
|
DEBUG = False
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. CI 自动化运行
|
||||||
|
|
||||||
|
### 10.1 GitHub Actions 配置
|
||||||
|
|
||||||
|
每日凌晨 2 点自动运行全量测试套件,并在每次 push 到 `main` / `develop` 分支时触发:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# .github/workflows/daily-test.yml
|
||||||
|
name: Daily Test Suite
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 18 * * *' # UTC 18:00 = 北京时间次日 02:00
|
||||||
|
push:
|
||||||
|
branches: [main, develop]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
unit-and-integration:
|
||||||
|
name: Unit & Integration Tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres:16
|
||||||
|
env:
|
||||||
|
POSTGRES_DB: fonrey_test
|
||||||
|
POSTGRES_USER: fonrey
|
||||||
|
POSTGRES_PASSWORD: test_password
|
||||||
|
options: >-
|
||||||
|
--health-cmd pg_isready
|
||||||
|
--health-interval 10s
|
||||||
|
--health-timeout 5s
|
||||||
|
--health-retries 5
|
||||||
|
redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
options: >-
|
||||||
|
--health-cmd "redis-cli ping"
|
||||||
|
--health-interval 10s
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: '3.12'
|
||||||
|
cache: pip
|
||||||
|
- run: pip install -r requirements/test.txt
|
||||||
|
- name: Run unit tests
|
||||||
|
run: pytest tests/unit -m unit --cov=core --cov=apps -q
|
||||||
|
- name: Run integration tests
|
||||||
|
run: pytest tests/integration -m integration -q
|
||||||
|
- name: Upload coverage report
|
||||||
|
uses: codecov/codecov-action@v4
|
||||||
|
|
||||||
|
e2e:
|
||||||
|
name: E2E Tests (Core Journeys)
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: unit-and-integration
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: '3.12'
|
||||||
|
cache: pip
|
||||||
|
- run: pip install -r requirements/test.txt
|
||||||
|
- run: playwright install chromium --with-deps
|
||||||
|
- name: Run E2E tests
|
||||||
|
run: pytest tests/e2e -m e2e -q
|
||||||
|
- name: Upload E2E screenshots on failure
|
||||||
|
if: failure()
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: e2e-screenshots
|
||||||
|
path: tests/e2e/screenshots/
|
||||||
|
```
|
||||||
|
|
||||||
|
### 10.2 本地每日运行
|
||||||
|
|
||||||
|
开发机本地运行全量测试:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# scripts/daily_test.sh
|
||||||
|
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=============================="
|
||||||
|
echo " Fonrey Daily Test Runner"
|
||||||
|
echo "=============================="
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "[1/3] 单元测试..."
|
||||||
|
pytest tests/unit -m unit -q --tb=short
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "[2/3] 集成测试..."
|
||||||
|
pytest tests/integration -m integration -q --tb=short
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "[3/3] E2E 核心旅程测试..."
|
||||||
|
pytest tests/e2e -m e2e -q --tb=short
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "[覆盖率报告]"
|
||||||
|
pytest tests/unit tests/integration \
|
||||||
|
--cov=core --cov=apps \
|
||||||
|
--cov-report=term-missing \
|
||||||
|
--cov-fail-under=70 \
|
||||||
|
-q --tb=no
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=============================="
|
||||||
|
echo " All tests passed."
|
||||||
|
echo "=============================="
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. AI 辅助编码时的测试要求
|
||||||
|
|
||||||
|
在 Fonrey vibe coding 流程中,每次 AI 完成一个 User Story 的功能代码后,**必须同步产出对应测试**,不允许欠测试债。
|
||||||
|
|
||||||
|
### 11.1 每个 User Story 的测试产出清单
|
||||||
|
|
||||||
|
AI 完成功能代码后,须产出以下内容(缺一不可):
|
||||||
|
|
||||||
|
- [ ] 相关 Model 的 `factory_boy` Factory(若尚未存在)
|
||||||
|
- [ ] Service 层的单元测试(正常路径 + 至少 2 个边界/异常场景)
|
||||||
|
- [ ] View 层的集成测试(覆盖 PRD 验收标准中所有 AC 条目)
|
||||||
|
- [ ] 权限场景覆盖(有权限 / 无权限 / 未登录,见 §7.3)
|
||||||
|
- [ ] HTMX 局部请求与完整页面请求分别测试(见 §7.2)
|
||||||
|
|
||||||
|
### 11.2 触发 AI 生成测试的标准 Prompt 模板
|
||||||
|
|
||||||
|
```
|
||||||
|
基于刚才实现的 [US-XXX-NNN],请为其生成完整测试:
|
||||||
|
|
||||||
|
1. factory_boy 工厂(如尚未存在)
|
||||||
|
- 文件位置:tests/factories/{app}_factory.py
|
||||||
|
- 使用 Faker 生成中文假数据
|
||||||
|
|
||||||
|
2. Service 层单元测试
|
||||||
|
- 文件位置:tests/unit/test_{app}_service.py
|
||||||
|
- 覆盖正常路径 + 至少 2 个边界/异常场景
|
||||||
|
- 使用 pytest-mock mock 外部依赖
|
||||||
|
|
||||||
|
3. View 层集成测试
|
||||||
|
- 文件位置:tests/integration/{app}/test_us_{module}.py
|
||||||
|
- 覆盖 PRD 中该 US 的所有 AC 条目
|
||||||
|
- 使用 TenantClient 发送请求
|
||||||
|
- HTMX 请求和普通请求分别覆盖
|
||||||
|
- 权限场景:有权限 / 无权限(403) / 未登录(302)
|
||||||
|
|
||||||
|
所有测试须遵循 TECH_STACK/测试规范.md 中的约定。
|
||||||
|
租户 fixtures 从 tests/conftest.py 导入,不要重复定义。
|
||||||
|
```
|
||||||
|
|
||||||
|
### 11.3 测试失败时的修复流程
|
||||||
|
|
||||||
|
CI 测试失败后,AI 修复流程:
|
||||||
|
|
||||||
|
1. 读取失败的测试输出(`--tb=short` 格式)
|
||||||
|
2. 定位失败原因(逻辑错误 / 数据错误 / 环境依赖问题)
|
||||||
|
3. **优先修复功能代码**(测试是需求的正式表达,不轻易修改测试)
|
||||||
|
4. 仅当测试本身有误(如 AC 理解错误)时才修改测试,并注明修改原因
|
||||||
|
5. 修复后本地重跑对应测试套件确认通过,再提交
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12. 禁止项(Do NOT)
|
||||||
|
|
||||||
|
- ❌ 禁止使用 Django 原生 `Client()`,必须使用 `TenantClient`
|
||||||
|
- ❌ 禁止使用固定等待 `time.sleep()` 或 `page.wait_for_timeout()`
|
||||||
|
- ❌ 禁止测试直接调用真实外部服务(R2、邮件、第三方 API)
|
||||||
|
- ❌ 禁止测试之间共享可变数据(避免测试顺序依赖)
|
||||||
|
- ❌ 禁止在测试中硬编码 Tenant ID、UUID、时间戳
|
||||||
|
- ❌ 禁止 E2E 测试依赖其他 E2E 测试产出的数据
|
||||||
|
- ❌ 禁止跳过权限验证场景(无权限 / 未登录场景必须覆盖)
|
||||||
|
- ❌ 禁止在功能代码未完成时先写空测试(`pass` 占位)后忘记补全
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 13. 文档索引
|
||||||
|
|
||||||
|
| 文档 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| [`TECH_STACK.md`](./TECH_STACK.md) | 技术栈总纲 |
|
||||||
|
| [`登录管理技术方案.md`](./登录管理技术方案.md) | 登录模块技术细节 |
|
||||||
|
| [`权限管理系统技术方案.md`](./权限管理系统技术方案.md) | 权限模块技术细节 |
|
||||||
|
| [`../PRD/TASK.md`](../PRD/TASK.md) | P0 User Story 清单(测试覆盖基准) |
|
||||||
|
| [`../DATA_MODEL/DATA_MODEL.md`](../DATA_MODEL/DATA_MODEL.md) | 数据模型总览(factory 设计参考) |
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -873,17 +873,17 @@
|
|||||||
</td>
|
</td>
|
||||||
|
|
||||||
<!-- 姓名 + 等级 + 活跃度 -->
|
<!-- 姓名 + 等级 + 活跃度 -->
|
||||||
<td class="px-4 py-2 align-middle min-w-[160px] max-w-[200px]">
|
<td class="px-4 py-2 align-middle min-w-[160px] max-w-[220px]">
|
||||||
<div class="flex flex-col gap-0.5">
|
<div class="flex flex-col gap-1">
|
||||||
|
<!-- 第一行:置顶标记 + 姓名 + 等级 -->
|
||||||
<div class="flex items-center gap-1.5">
|
<div class="flex items-center gap-1.5">
|
||||||
<!-- 置顶标记 -->
|
|
||||||
<svg x-show="client.pinned" class="w-3 h-3 text-warning-600 shrink-0" fill="currentColor" viewBox="0 0 20 20"><path d="M10 2a.75.75 0 0 1 .75.75v1.5a.75.75 0 0 1-1.5 0v-1.5A.75.75 0 0 1 10 2ZM10 15a.75.75 0 0 1 .75.75v1.5a.75.75 0 0 1-1.5 0v-1.5A.75.75 0 0 1 10 15Z"/></svg>
|
<svg x-show="client.pinned" class="w-3 h-3 text-warning-600 shrink-0" fill="currentColor" viewBox="0 0 20 20"><path d="M10 2a.75.75 0 0 1 .75.75v1.5a.75.75 0 0 1-1.5 0v-1.5A.75.75 0 0 1 10 2ZM10 15a.75.75 0 0 1 .75.75v1.5a.75.75 0 0 1-1.5 0v-1.5A.75.75 0 0 1 10 15Z"/></svg>
|
||||||
<a href="#"
|
<a href="#"
|
||||||
class="text-info-600 hover:underline font-medium text-sm truncate max-w-[160px]"
|
class="text-primary-600 hover:underline font-semibold text-base truncate max-w-[140px]"
|
||||||
x-text="client.name"></a>
|
x-text="client.name"></a>
|
||||||
<span class="text-[11px] text-neutral-400 font-medium shrink-0" x-text="client.gradeLabel"></span>
|
<span class="text-[11px] text-neutral-400 font-medium shrink-0" x-text="client.gradeLabel"></span>
|
||||||
</div>
|
</div>
|
||||||
<!-- 活跃度标签行 -->
|
<!-- 第二行:活跃度标签(强制独占一行) -->
|
||||||
<div class="flex items-center gap-1 flex-wrap">
|
<div class="flex items-center gap-1 flex-wrap">
|
||||||
<template x-for="tag in client.activityTags" :key="tag.key">
|
<template x-for="tag in client.activityTags" :key="tag.key">
|
||||||
<span class="text-[11px] px-1.5 py-0.5 rounded-full font-medium"
|
<span class="text-[11px] px-1.5 py-0.5 rounded-full font-medium"
|
||||||
|
|||||||
@@ -1,981 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="zh-CN">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>客源列表 · 私客 · Fonrey 房睿</title>
|
|
||||||
<meta name="viewport" content="width=1280">
|
|
||||||
<script src="https://cdn.tailwindcss.com"></script>
|
|
||||||
<script src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js" defer></script>
|
|
||||||
<script>
|
|
||||||
tailwind.config = {
|
|
||||||
theme: {
|
|
||||||
extend: {
|
|
||||||
colors: {
|
|
||||||
primary: {
|
|
||||||
50:'#F0FDFA',100:'#CCFBF1',200:'#99F6E4',
|
|
||||||
500:'#14B8A6',600:'#0F766E',700:'#115E59',800:'#134E4A',
|
|
||||||
},
|
|
||||||
neutral: {
|
|
||||||
50:'#F8FAFC',100:'#F1F5F9',200:'#E2E8F0',300:'#CBD5E1',
|
|
||||||
400:'#94A3B8',500:'#64748B',600:'#475569',700:'#334155',
|
|
||||||
800:'#1E293B',900:'#0F172A',
|
|
||||||
},
|
|
||||||
success:{50:'#F0FDF4',600:'#16A34A'},
|
|
||||||
warning:{50:'#FFFBEB',600:'#D97706'},
|
|
||||||
danger: {50:'#FEF2F2',600:'#DC2626'},
|
|
||||||
info: {50:'#EFF6FF',600:'#2563EB'},
|
|
||||||
},
|
|
||||||
fontFamily: {
|
|
||||||
sans:['Inter','PingFang SC','Microsoft YaHei','sans-serif'],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
body { font-family: 'Inter','PingFang SC','Microsoft YaHei',sans-serif; }
|
|
||||||
.tabular-nums { font-variant-numeric: tabular-nums; }
|
|
||||||
[x-cloak] { display: none !important; }
|
|
||||||
::-webkit-scrollbar{width:6px;height:6px}
|
|
||||||
::-webkit-scrollbar-thumb{background:#CBD5E1;border-radius:4px}
|
|
||||||
::-webkit-scrollbar-thumb:hover{background:#94A3B8}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body class="bg-neutral-50 text-neutral-700 text-sm antialiased">
|
|
||||||
|
|
||||||
<!-- ============ 顶部导航 ============ -->
|
|
||||||
<header class="fixed top-0 left-0 right-0 h-14 z-30 bg-primary-800 flex items-center justify-between">
|
|
||||||
<!-- 左区:Logo -->
|
|
||||||
<div class="flex items-center gap-2 px-4 w-60 shrink-0">
|
|
||||||
<div class="w-7 h-7 rounded-md bg-primary-500 flex items-center justify-center text-white font-semibold text-sm">F</div>
|
|
||||||
<span class="font-semibold text-white text-base">Fonrey · 房睿</span>
|
|
||||||
</div>
|
|
||||||
<!-- 中区:主导航 + 搜索 -->
|
|
||||||
<div class="flex items-center gap-4 flex-1 px-2">
|
|
||||||
<nav class="flex items-center gap-1 text-sm">
|
|
||||||
<a href="#" class="px-3 py-1.5 rounded-md text-primary-100 hover:bg-primary-700 hover:text-white transition-colors">工作台</a>
|
|
||||||
<a href="#" class="px-3 py-1.5 rounded-md text-primary-100 hover:bg-primary-700 hover:text-white transition-colors">房源</a>
|
|
||||||
<a href="#" class="px-3 py-1.5 rounded-md bg-primary-600 text-white font-medium">客源</a>
|
|
||||||
<a href="#" class="px-3 py-1.5 rounded-md text-primary-100 hover:bg-primary-700 hover:text-white transition-colors">营销</a>
|
|
||||||
<a href="#" class="px-3 py-1.5 rounded-md text-primary-100 hover:bg-primary-700 hover:text-white transition-colors">交易</a>
|
|
||||||
<a href="#" class="px-3 py-1.5 rounded-md text-primary-100 hover:bg-primary-700 hover:text-white transition-colors">数据</a>
|
|
||||||
<a href="#" class="px-3 py-1.5 rounded-md text-primary-100 hover:bg-primary-700 hover:text-white transition-colors">人事</a>
|
|
||||||
<a href="#" class="px-3 py-1.5 rounded-md text-primary-100 hover:bg-primary-700 hover:text-white transition-colors">系统</a>
|
|
||||||
</nav>
|
|
||||||
<!-- 全局搜索 -->
|
|
||||||
<div class="max-w-xs w-full relative">
|
|
||||||
<svg class="w-4 h-4 absolute left-3 top-1/2 -translate-y-1/2 text-primary-300" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="m21 21-4.3-4.3M11 19a8 8 0 1 1 0-16 8 8 0 0 1 0 16Z"/></svg>
|
|
||||||
<input type="text" placeholder="搜索房源 / 客户 / 楼盘 ⌘K"
|
|
||||||
class="w-full pl-9 pr-3 py-1.5 text-sm rounded-md bg-primary-700/60 border border-transparent text-white placeholder:text-primary-300 hover:bg-primary-700 focus:bg-white focus:text-neutral-700 focus:border-primary-600 focus:ring-2 focus:ring-primary-600/20 focus:outline-none focus:placeholder:text-neutral-400 transition-all">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- 右区:工具 -->
|
|
||||||
<div class="flex items-center gap-1 px-4 shrink-0">
|
|
||||||
<button class="relative p-1.5 text-primary-200 hover:bg-primary-700 hover:text-white rounded-md transition-colors">
|
|
||||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="1.8" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M14.857 17.082a23.848 23.848 0 0 0 5.454-1.31A8.967 8.967 0 0 1 18 9.75V9A6 6 0 0 0 6 9v.75a8.967 8.967 0 0 1-2.312 6.022 23.848 23.848 0 0 0 5.454 1.31m5.714 0a24.255 24.255 0 0 1-5.714 0m5.714 0a3 3 0 1 1-5.714 0"/></svg>
|
|
||||||
<span class="absolute top-1 right-1 w-1.5 h-1.5 rounded-full bg-danger-600"></span>
|
|
||||||
</button>
|
|
||||||
<button class="p-1.5 text-primary-200 hover:bg-primary-700 hover:text-white rounded-md transition-colors">
|
|
||||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="1.8" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 0 1 1.37.49l1.296 2.247a1.125 1.125 0 0 1-.26 1.431l-1.003.827c-.293.241-.438.613-.43.992a7.723 7.723 0 0 1 0 .255c-.008.378.137.75.43.991l1.004.827c.424.35.534.955.26 1.43l-1.298 2.247a1.125 1.125 0 0 1-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.47 6.47 0 0 1-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55 0-1.019-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 0 1-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 0 1-1.369-.49l-1.297-2.247a1.125 1.125 0 0 1 .26-1.431l1.004-.827c.292-.24.437-.613.43-.991a6.932 6.932 0 0 1 0-.255c.007-.38-.138-.751-.43-.992l-1.004-.827a1.125 1.125 0 0 1-.26-1.43l1.297-2.247a1.125 1.125 0 0 1 1.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.086.22-.128.332-.183.582-.495.644-.869l.214-1.28Z"/><path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"/></svg>
|
|
||||||
</button>
|
|
||||||
<div class="flex items-center gap-2 pl-3 ml-1 border-l border-primary-700">
|
|
||||||
<div class="w-7 h-7 rounded-full bg-primary-600 text-white flex items-center justify-center text-xs font-semibold">WS</div>
|
|
||||||
<span class="text-sm font-medium text-primary-100">魏深</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<!-- ============ 左侧导航栏 ============ -->
|
|
||||||
<aside class="fixed left-0 top-14 h-[calc(100vh-56px)] w-60 z-20 border-r border-neutral-200 bg-white">
|
|
||||||
<nav class="p-3 space-y-0.5">
|
|
||||||
<div class="px-2 pt-2 pb-1 text-xs font-medium text-neutral-500 uppercase tracking-wide">客源管理</div>
|
|
||||||
<a href="#" class="flex items-center gap-2 px-2 py-1.5 rounded-md bg-primary-50 text-primary-700 font-medium">
|
|
||||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="1.8" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5"/></svg>
|
|
||||||
私客列表
|
|
||||||
</a>
|
|
||||||
<a href="#" class="flex items-center gap-2 px-2 py-1.5 rounded-md text-neutral-700 hover:bg-neutral-100">公客池</a>
|
|
||||||
<a href="#" class="flex items-center gap-2 px-2 py-1.5 rounded-md text-neutral-700 hover:bg-neutral-100">成交客</a>
|
|
||||||
<a href="#" class="flex items-center gap-2 px-2 py-1.5 rounded-md text-neutral-700 hover:bg-neutral-100">已删客源</a>
|
|
||||||
</nav>
|
|
||||||
</aside>
|
|
||||||
|
|
||||||
<!-- ============ 主内容区 ============ -->
|
|
||||||
<main x-data="clientListApp()" class="ml-60 pt-[72px] min-h-screen bg-neutral-50">
|
|
||||||
<div class="px-6 py-4">
|
|
||||||
|
|
||||||
<!-- ======== 一级 Tab 导航 ======== -->
|
|
||||||
<div class="flex items-center justify-between border-b border-neutral-200 bg-neutral-50 sticky top-14 z-20 -mx-6 px-6 pt-1">
|
|
||||||
<div class="flex items-center gap-0">
|
|
||||||
<a href="#" class="px-4 py-3 text-sm border-b-2 border-primary-600 text-primary-600 font-medium whitespace-nowrap">私客</a>
|
|
||||||
<a href="#" class="px-4 py-3 text-sm border-b-2 border-transparent text-neutral-500 hover:text-neutral-700 whitespace-nowrap transition-colors">资料客</a>
|
|
||||||
<a href="#" class="px-4 py-3 text-sm border-b-2 border-transparent text-neutral-500 hover:text-neutral-700 whitespace-nowrap transition-colors">营销客</a>
|
|
||||||
<a href="#" class="px-4 py-3 text-sm border-b-2 border-transparent text-neutral-500 hover:text-neutral-700 whitespace-nowrap transition-colors">成交客</a>
|
|
||||||
<a href="#" class="px-4 py-3 text-sm border-b-2 border-transparent text-neutral-500 hover:text-neutral-700 whitespace-nowrap transition-colors">公客</a>
|
|
||||||
</div>
|
|
||||||
<!-- 右侧操作区 -->
|
|
||||||
<div class="flex items-center gap-4 text-sm pb-1">
|
|
||||||
<span class="text-neutral-500">
|
|
||||||
私客与成交客重复:
|
|
||||||
<a href="#" class="text-info-600 hover:underline font-medium">3</a>
|
|
||||||
</span>
|
|
||||||
<span class="text-neutral-500">
|
|
||||||
私客与公客重复:
|
|
||||||
<a href="#" class="text-info-600 hover:underline font-medium">7</a>
|
|
||||||
</span>
|
|
||||||
<a href="#" class="text-neutral-500 hover:text-neutral-700 transition-colors">已删客源</a>
|
|
||||||
<a href="/clients/private/create/"
|
|
||||||
class="inline-flex items-center gap-1.5 px-3 py-1.5 bg-primary-600 hover:bg-primary-700 text-white text-sm font-medium rounded-lg transition-colors">
|
|
||||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15"/></svg>
|
|
||||||
新增私客
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- ======== 二级 Tab 导航 ======== -->
|
|
||||||
<div class="mt-3 flex items-center gap-1 p-1 bg-neutral-100 rounded-lg w-fit">
|
|
||||||
<template x-for="tab in tabs" :key="tab.key">
|
|
||||||
<button
|
|
||||||
:class="activeTab === tab.key
|
|
||||||
? 'bg-white text-primary-700 shadow-sm font-semibold'
|
|
||||||
: 'text-neutral-600 hover:bg-white/60'"
|
|
||||||
class="px-4 py-1.5 text-sm rounded-md transition-all flex items-center gap-1"
|
|
||||||
@click="activeTab = tab.key">
|
|
||||||
<span x-text="tab.label"></span>
|
|
||||||
<span x-show="tab.count !== null"
|
|
||||||
class="bg-neutral-200 text-neutral-600 text-xs px-1.5 py-0.5 rounded-full tabular-nums"
|
|
||||||
x-text="tab.count"></span>
|
|
||||||
</button>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- ======== 搜索 + 筛选区 ======== -->
|
|
||||||
<div class="bg-white rounded-lg border border-neutral-200 px-4 py-3 mt-3">
|
|
||||||
|
|
||||||
<!-- 搜索行 -->
|
|
||||||
<div class="flex items-center gap-3">
|
|
||||||
<!-- 范围选择器 -->
|
|
||||||
<select class="text-sm text-neutral-600 border border-neutral-300 rounded-lg px-3 py-2 bg-white focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-600/40 shrink-0">
|
|
||||||
<option>客户信息</option>
|
|
||||||
<option>客源编号</option>
|
|
||||||
<option>小区名称</option>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<!-- 搜索框 -->
|
|
||||||
<div class="relative flex-1 max-w-lg">
|
|
||||||
<svg class="w-4 h-4 absolute left-3 top-1/2 -translate-y-1/2 text-neutral-400" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="m21 21-4.3-4.3M11 19a8 8 0 1 1 0-16 8 8 0 0 1 0 16Z"/></svg>
|
|
||||||
<input type="search"
|
|
||||||
placeholder="输入客源姓名 / 号码 / 号码后4位 / 客源编号 / 备注信息"
|
|
||||||
class="w-full pl-9 pr-10 py-2 border border-neutral-300 rounded-lg text-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-600/40">
|
|
||||||
<button class="absolute right-1 top-1/2 -translate-y-1/2 bg-primary-600 hover:bg-primary-700 text-white w-8 h-8 rounded-md flex items-center justify-center transition-colors">
|
|
||||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="m21 21-4.3-4.3M11 19a8 8 0 1 1 0-16 8 8 0 0 1 0 16Z"/></svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 已存搜索 -->
|
|
||||||
<div x-data="{ open: false }" class="relative shrink-0">
|
|
||||||
<button @click="open = !open"
|
|
||||||
class="text-sm text-neutral-500 hover:text-neutral-700 flex items-center gap-1 transition-colors">
|
|
||||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="1.8" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M17.593 3.322c1.1.128 1.907 1.077 1.907 2.185V21L12 17.25 4.5 21V5.507c0-1.108.806-2.057 1.907-2.185a48.507 48.507 0 0 1 11.186 0Z"/></svg>
|
|
||||||
<span>3条已存搜索</span>
|
|
||||||
<svg class="w-3 h-3" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5"/></svg>
|
|
||||||
</button>
|
|
||||||
<div x-show="open" x-cloak @click.outside="open = false"
|
|
||||||
class="absolute left-0 top-full mt-1 w-64 bg-white shadow-lg border border-neutral-200 rounded-lg z-50 py-1">
|
|
||||||
<div class="px-3 py-2 text-xs text-neutral-400 border-b border-neutral-100">已存搜索条件</div>
|
|
||||||
<a href="#" class="flex items-center justify-between px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-50">
|
|
||||||
<span>求购·A级·宝山</span>
|
|
||||||
<button class="text-neutral-400 hover:text-danger-600 ml-2">
|
|
||||||
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12"/></svg>
|
|
||||||
</button>
|
|
||||||
</a>
|
|
||||||
<a href="#" class="flex items-center justify-between px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-50">
|
|
||||||
<span>7日活跃·与我相关</span>
|
|
||||||
<button class="text-neutral-400 hover:text-danger-600 ml-2">
|
|
||||||
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12"/></svg>
|
|
||||||
</button>
|
|
||||||
</a>
|
|
||||||
<a href="#" class="flex items-center justify-between px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-50">
|
|
||||||
<span>即将掉公·近30天录入</span>
|
|
||||||
<button class="text-neutral-400 hover:text-danger-600 ml-2">
|
|
||||||
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12"/></svg>
|
|
||||||
</button>
|
|
||||||
</a>
|
|
||||||
<div class="px-3 py-2 border-t border-neutral-100">
|
|
||||||
<button class="text-xs text-primary-600 hover:underline">保存当前筛选条件</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 收起/展开筛选 -->
|
|
||||||
<button @click="showFilters = !showFilters"
|
|
||||||
class="ml-auto text-sm text-neutral-500 hover:text-primary-600 flex items-center gap-1 shrink-0 transition-colors">
|
|
||||||
<span x-text="showFilters ? '收起筛选' : '展开筛选'"></span>
|
|
||||||
<svg class="w-4 h-4 transition-transform" :class="showFilters ? 'rotate-180' : ''" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5"/></svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 筛选区(可折叠) -->
|
|
||||||
<div x-show="showFilters"
|
|
||||||
x-transition:enter="transition ease-out duration-150"
|
|
||||||
x-transition:enter-start="opacity-0 -translate-y-1"
|
|
||||||
x-transition:enter-end="opacity-100 translate-y-0"
|
|
||||||
x-transition:leave="transition ease-in duration-100"
|
|
||||||
x-transition:leave-start="opacity-100 translate-y-0"
|
|
||||||
x-transition:leave-end="opacity-0 -translate-y-1"
|
|
||||||
class="mt-3 space-y-2.5 border-t border-neutral-100 pt-3">
|
|
||||||
|
|
||||||
<!-- 快捷筛选行 -->
|
|
||||||
<div class="flex items-center gap-5 text-sm">
|
|
||||||
<span class="text-neutral-400 text-xs w-6 shrink-0">常用</span>
|
|
||||||
<label class="flex items-center gap-1.5 cursor-pointer text-neutral-600 hover:text-primary-600 transition-colors">
|
|
||||||
<input type="checkbox" class="w-4 h-4 rounded accent-primary-600"> 即将掉公
|
|
||||||
</label>
|
|
||||||
<div class="flex items-center gap-1.5">
|
|
||||||
<span class="text-neutral-600">录入时间</span>
|
|
||||||
<select class="text-sm border-0 text-neutral-600 bg-transparent cursor-pointer focus:outline-none hover:text-primary-600 pr-4">
|
|
||||||
<option value="">不限</option>
|
|
||||||
<option>今天</option>
|
|
||||||
<option>最近7天</option>
|
|
||||||
<option>最近30天</option>
|
|
||||||
<option>自定义</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<label class="flex items-center gap-1.5 cursor-pointer text-neutral-600 hover:text-primary-600 transition-colors">
|
|
||||||
<input type="checkbox" class="w-4 h-4 rounded accent-primary-600"> 与我相关
|
|
||||||
<svg class="w-3.5 h-3.5 text-neutral-400" fill="none" stroke="currentColor" stroke-width="1.8" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z"/></svg>
|
|
||||||
</label>
|
|
||||||
<label class="flex items-center gap-1.5 cursor-pointer text-neutral-600 hover:text-primary-600 transition-colors">
|
|
||||||
<input type="checkbox" class="w-4 h-4 rounded accent-primary-600"> 我部门相关
|
|
||||||
<svg class="w-3.5 h-3.5 text-neutral-400" fill="none" stroke="currentColor" stroke-width="1.8" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z"/></svg>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 状态筛选行 -->
|
|
||||||
<div class="flex items-center flex-wrap gap-x-2 gap-y-1.5 text-sm">
|
|
||||||
<span class="text-neutral-400 text-xs w-6 shrink-0">状态</span>
|
|
||||||
<template x-for="opt in statusOptions" :key="opt.value">
|
|
||||||
<button
|
|
||||||
:class="activeStatus === opt.value
|
|
||||||
? 'bg-primary-600 text-white border-primary-600'
|
|
||||||
: 'border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600'"
|
|
||||||
class="px-3 py-1 text-xs border rounded-md transition-colors"
|
|
||||||
@click="activeStatus = opt.value"
|
|
||||||
x-text="opt.label">
|
|
||||||
</button>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 需求类型筛选行 -->
|
|
||||||
<div class="flex items-center flex-wrap gap-x-2 gap-y-1.5 text-sm">
|
|
||||||
<span class="text-neutral-400 text-xs w-6 shrink-0">需求</span>
|
|
||||||
<button class="px-3 py-1 text-xs bg-primary-600 text-white border border-primary-600 rounded-md">不限</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">二手</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">新房</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 等级筛选行 -->
|
|
||||||
<div class="flex items-center flex-wrap gap-x-2 gap-y-1.5 text-sm">
|
|
||||||
<span class="text-neutral-400 text-xs w-6 shrink-0">等级</span>
|
|
||||||
<button class="px-3 py-1 text-xs bg-primary-600 text-white border border-primary-600 rounded-md">不限</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">A(急迫)</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">B(较强)</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">C(一般)</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">D(较弱)</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">E(暂不)</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">未填写</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 位置筛选行 -->
|
|
||||||
<div class="flex items-center flex-wrap gap-x-2 gap-y-1.5 text-sm">
|
|
||||||
<span class="text-neutral-400 text-xs w-6 shrink-0">位置</span>
|
|
||||||
<button class="px-3 py-1 text-xs bg-primary-600 text-white border border-primary-600 rounded-md">不限</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">宝山</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">崇明</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">奉贤</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">虹口</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">黄浦</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">嘉定</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">金山</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">静安</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">闵行</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">浦东</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">普陀</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">青浦</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">松江</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">徐汇</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">杨浦</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">长宁</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 购价筛选行 -->
|
|
||||||
<div class="flex items-center flex-wrap gap-x-2 gap-y-1.5 text-sm">
|
|
||||||
<span class="text-neutral-400 text-xs w-6 shrink-0">购价</span>
|
|
||||||
<button class="px-3 py-1 text-xs bg-primary-600 text-white border border-primary-600 rounded-md">不限</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">200万以下</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">200-300万</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">300-500万</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">500-800万</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">800-1000万</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">1000万以上</button>
|
|
||||||
<div class="flex items-center gap-1.5 ml-1">
|
|
||||||
<input type="number" placeholder="最小值" class="w-20 px-2 py-1 text-xs border border-neutral-300 rounded-md focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-600/40">
|
|
||||||
<span class="text-neutral-400 text-xs">~</span>
|
|
||||||
<input type="number" placeholder="最大值" class="w-20 px-2 py-1 text-xs border border-neutral-300 rounded-md focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-600/40">
|
|
||||||
<span class="text-xs text-neutral-500">万</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 居室筛选行 -->
|
|
||||||
<div class="flex items-center flex-wrap gap-x-2 gap-y-1.5 text-sm">
|
|
||||||
<span class="text-neutral-400 text-xs w-6 shrink-0">居室</span>
|
|
||||||
<button class="px-3 py-1 text-xs bg-primary-600 text-white border border-primary-600 rounded-md">不限</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">1居</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">2居</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">3居</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">4居</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">5居及以上</button>
|
|
||||||
<label class="flex items-center gap-1.5 cursor-pointer text-neutral-600 hover:text-primary-600 transition-colors ml-2">
|
|
||||||
<input type="checkbox" class="w-4 h-4 rounded accent-primary-600"> 是大价值
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 更多筛选(展开/收起) -->
|
|
||||||
<div x-data="{ showMore: false }">
|
|
||||||
<button @click="showMore = !showMore"
|
|
||||||
class="flex items-center gap-1 text-xs text-neutral-500 hover:text-primary-600 transition-colors py-0.5">
|
|
||||||
<svg class="w-3.5 h-3.5 transition-transform" :class="showMore ? 'rotate-180' : ''" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5"/></svg>
|
|
||||||
<span x-text="showMore ? '收起筛选' : '展开更多筛选'"></span>
|
|
||||||
</button>
|
|
||||||
<div x-show="showMore" x-cloak class="mt-2.5 space-y-2.5">
|
|
||||||
<!-- 相关方 -->
|
|
||||||
<div class="flex items-center flex-wrap gap-x-3 gap-y-1.5 text-sm">
|
|
||||||
<span class="text-neutral-400 text-xs w-10 shrink-0">相关方</span>
|
|
||||||
<select class="text-sm border border-neutral-300 rounded-md px-2 py-1 bg-white focus:outline-none text-neutral-600">
|
|
||||||
<option>不限</option>
|
|
||||||
<option>首录人:我</option>
|
|
||||||
<option>归属人:我</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<!-- 委托日期 -->
|
|
||||||
<div class="flex items-center flex-wrap gap-x-3 gap-y-1.5 text-sm">
|
|
||||||
<span class="text-neutral-400 text-xs w-10 shrink-0">委托日期</span>
|
|
||||||
<input type="date" class="text-sm border border-neutral-300 rounded-md px-2 py-1 bg-white focus:outline-none text-neutral-600">
|
|
||||||
<span class="text-neutral-400 text-xs">~</span>
|
|
||||||
<input type="date" class="text-sm border border-neutral-300 rounded-md px-2 py-1 bg-white focus:outline-none text-neutral-600">
|
|
||||||
</div>
|
|
||||||
<!-- 来源 -->
|
|
||||||
<div class="flex items-center flex-wrap gap-x-3 gap-y-1.5 text-sm">
|
|
||||||
<span class="text-neutral-400 text-xs w-10 shrink-0">来源</span>
|
|
||||||
<select class="text-sm border border-neutral-300 rounded-md px-2 py-1 bg-white focus:outline-none text-neutral-600">
|
|
||||||
<option>不限</option>
|
|
||||||
<option>自然到访</option>
|
|
||||||
<option>网络推广</option>
|
|
||||||
<option>老客介绍</option>
|
|
||||||
<option>巧客力</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<!-- 活跃情况 -->
|
|
||||||
<div class="flex items-center flex-wrap gap-x-2 gap-y-1.5 text-sm">
|
|
||||||
<span class="text-neutral-400 text-xs w-10 shrink-0">活跃</span>
|
|
||||||
<button class="px-3 py-1 text-xs bg-primary-600 text-white border border-primary-600 rounded-md">不限</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">新配房</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">7日活跃</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">30日活跃</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">即将过期</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">已暂缓</button>
|
|
||||||
</div>
|
|
||||||
<!-- 带看进度 -->
|
|
||||||
<div class="flex items-center flex-wrap gap-x-2 gap-y-1.5 text-sm">
|
|
||||||
<span class="text-neutral-400 text-xs w-10 shrink-0">带看</span>
|
|
||||||
<button class="px-3 py-1 text-xs bg-primary-600 text-white border border-primary-600 rounded-md">不限</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">未带看</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">一看</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">二看</button>
|
|
||||||
<button class="px-3 py-1 text-xs border border-neutral-200 text-neutral-600 hover:border-primary-400 hover:text-primary-600 rounded-md transition-colors">复看</button>
|
|
||||||
</div>
|
|
||||||
<!-- 保护客 -->
|
|
||||||
<div class="flex items-center flex-wrap gap-x-5 gap-y-1.5 text-sm">
|
|
||||||
<span class="text-neutral-400 text-xs w-10 shrink-0">其他</span>
|
|
||||||
<label class="flex items-center gap-1.5 cursor-pointer text-neutral-600 hover:text-primary-600 transition-colors">
|
|
||||||
<input type="checkbox" class="w-4 h-4 rounded accent-primary-600"> 保护客
|
|
||||||
</label>
|
|
||||||
<label class="flex items-center gap-1.5 cursor-pointer text-neutral-600 hover:text-primary-600 transition-colors">
|
|
||||||
<input type="checkbox" class="w-4 h-4 rounded accent-primary-600"> 偏好新房
|
|
||||||
</label>
|
|
||||||
<label class="flex items-center gap-1.5 cursor-pointer text-neutral-600 hover:text-primary-600 transition-colors">
|
|
||||||
<input type="checkbox" class="w-4 h-4 rounded accent-primary-600"> 收藏客源
|
|
||||||
</label>
|
|
||||||
<label class="flex items-center gap-1.5 cursor-pointer text-neutral-600 hover:text-primary-600 transition-colors">
|
|
||||||
<input type="checkbox" class="w-4 h-4 rounded accent-primary-600"> 置顶客源
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- ======== 工具栏 ======== -->
|
|
||||||
<div class="flex items-center justify-between px-4 py-2.5 bg-white border border-neutral-200 rounded-lg mt-3">
|
|
||||||
<!-- 左侧:批量操作 + 计数 -->
|
|
||||||
<div class="flex items-center gap-2">
|
|
||||||
<button :disabled="selected.length === 0"
|
|
||||||
:class="selected.length > 0
|
|
||||||
? 'text-neutral-700 hover:bg-neutral-100 border-neutral-300 cursor-pointer'
|
|
||||||
: 'text-neutral-300 border-neutral-200 cursor-not-allowed'"
|
|
||||||
class="px-3 py-1.5 text-sm border rounded-md transition-colors">
|
|
||||||
修改相关方
|
|
||||||
</button>
|
|
||||||
<button :disabled="selected.length === 0"
|
|
||||||
:class="selected.length > 0
|
|
||||||
? 'text-neutral-700 hover:bg-neutral-100 border-neutral-300 cursor-pointer'
|
|
||||||
: 'text-neutral-300 border-neutral-200 cursor-not-allowed'"
|
|
||||||
class="px-3 py-1.5 text-sm border rounded-md transition-colors">
|
|
||||||
修改来源
|
|
||||||
</button>
|
|
||||||
<button :disabled="selected.length === 0"
|
|
||||||
:class="selected.length > 0
|
|
||||||
? 'text-danger-600 hover:bg-danger-50 border-danger-200 cursor-pointer'
|
|
||||||
: 'text-neutral-300 border-neutral-200 cursor-not-allowed'"
|
|
||||||
class="px-3 py-1.5 text-sm border rounded-md transition-colors">
|
|
||||||
删除客源
|
|
||||||
</button>
|
|
||||||
<button :disabled="selected.length === 0"
|
|
||||||
:class="selected.length > 0
|
|
||||||
? 'text-neutral-700 hover:bg-neutral-100 border-neutral-300 cursor-pointer'
|
|
||||||
: 'text-neutral-300 border-neutral-200 cursor-not-allowed'"
|
|
||||||
class="px-3 py-1.5 text-sm border rounded-md transition-colors">
|
|
||||||
合并客源
|
|
||||||
</button>
|
|
||||||
<span class="text-sm text-neutral-500 ml-2">
|
|
||||||
共 <strong class="text-neutral-800 tabular-nums">1,248</strong> 条
|
|
||||||
</span>
|
|
||||||
<span x-show="selected.length > 0" class="text-sm text-primary-600">
|
|
||||||
已选 <span x-text="selected.length" class="tabular-nums"></span> 条
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<!-- 右侧:导出 + 自定义列 -->
|
|
||||||
<div class="flex items-center gap-2">
|
|
||||||
<button class="flex items-center gap-1.5 px-3 py-1.5 text-sm text-neutral-600 border border-neutral-300 rounded-md hover:bg-neutral-50 transition-colors">
|
|
||||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="1.8" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12m4.5 4.5V3"/></svg>
|
|
||||||
导出
|
|
||||||
</button>
|
|
||||||
<button @click="showColumnModal = true"
|
|
||||||
class="flex items-center gap-1.5 px-3 py-1.5 text-sm text-neutral-600 border border-neutral-300 rounded-md hover:bg-neutral-50 transition-colors">
|
|
||||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="1.8" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M10.5 6h9.75M10.5 6a1.5 1.5 0 1 1-3 0m3 0a1.5 1.5 0 1 0-3 0M3.75 6H7.5m3 12h9.75m-9.75 0a1.5 1.5 0 0 1-3 0m3 0a1.5 1.5 0 0 0-3 0m-3.75 0H7.5m9-6h3.75m-3.75 0a1.5 1.5 0 0 1-3 0m3 0a1.5 1.5 0 0 0-3 0m-9.75 0h9.75"/></svg>
|
|
||||||
自定义列表
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- ======== 数据表格 ======== -->
|
|
||||||
<div id="client-list-container" class="rounded-lg border border-neutral-200 overflow-hidden bg-white mt-3">
|
|
||||||
<div class="overflow-x-auto">
|
|
||||||
<table class="min-w-full divide-y divide-neutral-200">
|
|
||||||
<thead class="bg-neutral-50">
|
|
||||||
<tr>
|
|
||||||
<th class="w-10 px-4 py-3">
|
|
||||||
<input type="checkbox" id="select-all"
|
|
||||||
class="w-4 h-4 rounded accent-primary-600"
|
|
||||||
@change="toggleAll($event)">
|
|
||||||
</th>
|
|
||||||
<th class="px-4 py-3 text-left text-xs font-semibold text-neutral-500 uppercase tracking-wide whitespace-nowrap min-w-[160px]">姓名</th>
|
|
||||||
<th class="px-4 py-3 text-left text-xs font-semibold text-neutral-500 uppercase tracking-wide whitespace-nowrap w-20">状态</th>
|
|
||||||
<th class="px-4 py-3 text-left text-xs font-semibold text-neutral-500 uppercase tracking-wide whitespace-nowrap w-20">需求类型</th>
|
|
||||||
<th class="px-4 py-3 text-left text-xs font-semibold text-neutral-500 uppercase tracking-wide whitespace-nowrap min-w-[180px]">需求/解读</th>
|
|
||||||
<th class="px-4 py-3 text-left text-xs font-semibold text-neutral-500 uppercase tracking-wide whitespace-nowrap w-24">智能配房</th>
|
|
||||||
<th class="px-4 py-3 text-left text-xs font-semibold text-neutral-500 uppercase tracking-wide whitespace-nowrap min-w-[120px]">意向商圈/小区</th>
|
|
||||||
<th class="px-4 py-3 text-left text-xs font-semibold text-neutral-500 uppercase tracking-wide whitespace-nowrap min-w-[140px]">归属人</th>
|
|
||||||
<th class="px-4 py-3 text-left text-xs font-semibold text-neutral-500 uppercase tracking-wide whitespace-nowrap w-20">带看进度</th>
|
|
||||||
<th class="px-4 py-3 text-left text-xs font-semibold text-neutral-500 uppercase tracking-wide whitespace-nowrap w-[72px] cursor-pointer hover:bg-neutral-100 select-none">
|
|
||||||
带看次数
|
|
||||||
<svg class="inline w-3.5 h-3.5 text-neutral-300 ml-0.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M8.25 15 12 18.75 15.75 15m-7.5-6L12 5.25 15.75 9"/></svg>
|
|
||||||
</th>
|
|
||||||
<th class="px-4 py-3 text-left text-xs font-semibold text-neutral-500 uppercase tracking-wide whitespace-nowrap w-24 cursor-pointer hover:bg-neutral-100 select-none">
|
|
||||||
委托日期
|
|
||||||
<svg class="inline w-3.5 h-3.5 text-neutral-300 ml-0.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M8.25 15 12 18.75 15.75 15m-7.5-6L12 5.25 15.75 9"/></svg>
|
|
||||||
</th>
|
|
||||||
<th class="px-4 py-3 text-left text-xs font-semibold text-neutral-500 uppercase tracking-wide whitespace-nowrap w-24 cursor-pointer hover:bg-neutral-100 select-none text-primary-600">
|
|
||||||
最近时间
|
|
||||||
<svg class="inline w-3.5 h-3.5 text-primary-400 ml-0.5" fill="none" stroke="currentColor" stroke-width="2.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M19.5 8.25 12 15.75 4.5 8.25"/></svg>
|
|
||||||
</th>
|
|
||||||
<th class="px-4 py-3 text-center text-xs font-semibold text-neutral-500 uppercase tracking-wide whitespace-nowrap w-16">操作</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody id="client-table-body" class="divide-y divide-neutral-100 bg-white">
|
|
||||||
|
|
||||||
<!-- 数据行 1 -->
|
|
||||||
<tr class="hover:bg-neutral-50 transition-colors"
|
|
||||||
:class="selected.includes('c001') ? 'bg-primary-50 hover:bg-primary-100' : ''">
|
|
||||||
<td class="w-10 px-4 py-2">
|
|
||||||
<input type="checkbox" value="c001" class="w-4 h-4 rounded accent-primary-600" x-model="selected">
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2 min-w-[160px]">
|
|
||||||
<div class="flex flex-col gap-0.5">
|
|
||||||
<a href="/clients/private/c001/" class="text-info-600 hover:underline font-medium text-sm truncate max-w-[160px]">王建国</a>
|
|
||||||
<div class="flex items-center gap-1 flex-wrap">
|
|
||||||
<span class="text-[11px] text-neutral-500">A(急迫)</span>
|
|
||||||
<span class="text-[11px] px-1.5 py-0.5 rounded-full font-medium bg-success-50 text-success-600">7日活跃</span>
|
|
||||||
<span class="text-[11px] px-1.5 py-0.5 rounded-full font-medium bg-info-50 text-info-600">新配房</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<span class="bg-primary-50 text-primary-700 text-xs px-2 py-0.5 rounded-full">求购</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2 text-sm text-neutral-700">二手</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<span class="text-sm text-neutral-700 truncate block max-w-[200px]" title="550-600万,100㎡-110㎡,3居,宝山">550-600万,100㎡-110㎡,3居,宝山</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<div class="flex items-center gap-1">
|
|
||||||
<span class="text-sm text-neutral-700 font-medium">8套</span>
|
|
||||||
<button class="text-neutral-400 hover:text-info-600 transition-colors" title="查看配房详情">
|
|
||||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="1.8" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z"/></svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<span class="text-sm text-neutral-700 truncate block max-w-[160px]" title="宝山·顾村,大华锦绣华城">宝山·顾村,大华锦绣华城</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<span class="text-sm text-neutral-700">张伟-都市港湾店一组</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<span class="bg-warning-50 text-warning-600 px-2 py-0.5 rounded-full text-xs">一看</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2 text-sm text-neutral-700 tabular-nums">3次</td>
|
|
||||||
<td class="px-4 py-2 text-sm text-neutral-600 tabular-nums">2026-03-15</td>
|
|
||||||
<td class="px-4 py-2 text-sm text-neutral-700 tabular-nums">今天</td>
|
|
||||||
<td class="px-3 py-2 text-center">
|
|
||||||
<button class="inline-flex items-center justify-center w-8 h-8 rounded-md text-primary-600 hover:bg-primary-50 hover:text-primary-700 transition-colors" title="拨号">
|
|
||||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="1.8" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M2.25 6.75c0 8.284 6.716 15 15 15h2.25a2.25 2.25 0 0 0 2.25-2.25v-1.372c0-.516-.351-.966-.852-1.091l-4.423-1.106c-.44-.11-.902.055-1.173.417l-.97 1.293c-.282.376-.769.542-1.21.38a12.035 12.035 0 0 1-7.143-7.143c-.162-.441.004-.928.38-1.21l1.293-.97c.363-.271.527-.734.417-1.173L6.963 3.102a1.125 1.125 0 0 0-1.091-.852H4.5A2.25 2.25 0 0 0 2.25 4.5v2.25Z"/></svg>
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<!-- 数据行 2 -->
|
|
||||||
<tr class="hover:bg-neutral-50 transition-colors"
|
|
||||||
:class="selected.includes('c002') ? 'bg-primary-50 hover:bg-primary-100' : ''">
|
|
||||||
<td class="w-10 px-4 py-2">
|
|
||||||
<input type="checkbox" value="c002" class="w-4 h-4 rounded accent-primary-600" x-model="selected">
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2 min-w-[160px]">
|
|
||||||
<div class="flex flex-col gap-0.5">
|
|
||||||
<a href="/clients/private/c002/" class="text-info-600 hover:underline font-medium text-sm truncate max-w-[160px]">李晓敏</a>
|
|
||||||
<div class="flex items-center gap-1 flex-wrap">
|
|
||||||
<span class="text-[11px] text-neutral-500">B(较强)</span>
|
|
||||||
<span class="text-[11px] px-1.5 py-0.5 rounded-full font-medium bg-purple-50 text-purple-600">营销客</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<span class="bg-info-50 text-info-600 text-xs px-2 py-0.5 rounded-full">求租</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2 text-sm text-neutral-700">租房</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<span class="text-sm text-neutral-700 truncate block max-w-[200px]" title="4000-6000元/月,60㎡-80㎡,2居,静安">4000-6000元/月,60㎡-80㎡,2居,静安</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<div class="flex items-center gap-1">
|
|
||||||
<span class="text-sm text-neutral-700 font-medium">12套</span>
|
|
||||||
<button class="text-neutral-400 hover:text-info-600 transition-colors">
|
|
||||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="1.8" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z"/></svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<span class="text-sm text-neutral-700 truncate block max-w-[160px]">静安·南京西路</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<span class="text-sm text-neutral-700">陈丽-静安旗舰店二组</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<span class="text-sm text-neutral-500">未带看</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2 text-sm text-neutral-700 tabular-nums">0次</td>
|
|
||||||
<td class="px-4 py-2 text-sm text-neutral-600 tabular-nums">2026-04-10</td>
|
|
||||||
<td class="px-4 py-2 text-sm text-neutral-700 tabular-nums">3天前</td>
|
|
||||||
<td class="px-3 py-2 text-center">
|
|
||||||
<button class="inline-flex items-center justify-center w-8 h-8 rounded-md text-primary-600 hover:bg-primary-50 hover:text-primary-700 transition-colors" title="拨号">
|
|
||||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="1.8" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M2.25 6.75c0 8.284 6.716 15 15 15h2.25a2.25 2.25 0 0 0 2.25-2.25v-1.372c0-.516-.351-.966-.852-1.091l-4.423-1.106c-.44-.11-.902.055-1.173.417l-.97 1.293c-.282.376-.769.542-1.21.38a12.035 12.035 0 0 1-7.143-7.143c-.162-.441.004-.928.38-1.21l1.293-.97c.363-.271.527-.734.417-1.173L6.963 3.102a1.125 1.125 0 0 0-1.091-.852H4.5A2.25 2.25 0 0 0 2.25 4.5v2.25Z"/></svg>
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<!-- 数据行 3 -->
|
|
||||||
<tr class="hover:bg-neutral-50 transition-colors"
|
|
||||||
:class="selected.includes('c003') ? 'bg-primary-50 hover:bg-primary-100' : ''">
|
|
||||||
<td class="w-10 px-4 py-2">
|
|
||||||
<input type="checkbox" value="c003" class="w-4 h-4 rounded accent-primary-600" x-model="selected">
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2 min-w-[160px]">
|
|
||||||
<div class="flex flex-col gap-0.5">
|
|
||||||
<a href="/clients/private/c003/" class="text-info-600 hover:underline font-medium text-sm truncate max-w-[160px]">赵志远</a>
|
|
||||||
<div class="flex items-center gap-1 flex-wrap">
|
|
||||||
<span class="text-[11px] text-neutral-500">A(急迫)</span>
|
|
||||||
<span class="text-[11px] px-1.5 py-0.5 rounded-full font-medium bg-warning-50 text-warning-600">即将过期</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<span class="bg-warning-50 text-warning-600 text-xs px-2 py-0.5 rounded-full">租购</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2 text-sm text-neutral-700">二手</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<span class="text-sm text-neutral-700 truncate block max-w-[200px]" title="800-1000万,120㎡以上,4居,浦东">800-1000万,120㎡以上,4居,浦东</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<div class="flex items-center gap-1">
|
|
||||||
<span class="text-sm text-neutral-700 font-medium">5套</span>
|
|
||||||
<button class="text-neutral-400 hover:text-info-600 transition-colors">
|
|
||||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="1.8" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z"/></svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<span class="text-sm text-neutral-700 truncate block max-w-[160px]">浦东·陆家嘴,世纪公园</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<span class="text-sm text-neutral-700">刘洋-浦东总店三组</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<span class="bg-info-50 text-info-600 px-2 py-0.5 rounded-full text-xs">二看</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2 text-sm text-neutral-700 tabular-nums">5次</td>
|
|
||||||
<td class="px-4 py-2 text-sm text-neutral-600 tabular-nums">2026-01-20</td>
|
|
||||||
<td class="px-4 py-2 text-sm text-neutral-700 tabular-nums">8天前</td>
|
|
||||||
<td class="px-3 py-2 text-center">
|
|
||||||
<button class="inline-flex items-center justify-center w-8 h-8 rounded-md text-primary-600 hover:bg-primary-50 hover:text-primary-700 transition-colors" title="拨号">
|
|
||||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="1.8" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M2.25 6.75c0 8.284 6.716 15 15 15h2.25a2.25 2.25 0 0 0 2.25-2.25v-1.372c0-.516-.351-.966-.852-1.091l-4.423-1.106c-.44-.11-.902.055-1.173.417l-.97 1.293c-.282.376-.769.542-1.21.38a12.035 12.035 0 0 1-7.143-7.143c-.162-.441.004-.928.38-1.21l1.293-.97c.363-.271.527-.734.417-1.173L6.963 3.102a1.125 1.125 0 0 0-1.091-.852H4.5A2.25 2.25 0 0 0 2.25 4.5v2.25Z"/></svg>
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<!-- 数据行 4 -->
|
|
||||||
<tr class="hover:bg-neutral-50 transition-colors"
|
|
||||||
:class="selected.includes('c004') ? 'bg-primary-50 hover:bg-primary-100' : ''">
|
|
||||||
<td class="w-10 px-4 py-2">
|
|
||||||
<input type="checkbox" value="c004" class="w-4 h-4 rounded accent-primary-600" x-model="selected">
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2 min-w-[160px]">
|
|
||||||
<div class="flex flex-col gap-0.5">
|
|
||||||
<a href="/clients/private/c004/" class="text-info-600 hover:underline font-medium text-sm truncate max-w-[160px]">孙美玲</a>
|
|
||||||
<div class="flex items-center gap-1 flex-wrap">
|
|
||||||
<span class="text-[11px] text-neutral-500">C(一般)</span>
|
|
||||||
<span class="text-[11px] px-1.5 py-0.5 rounded-full font-medium bg-neutral-100 text-neutral-500">暂缓</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<span class="bg-neutral-100 text-neutral-500 text-xs px-2 py-0.5 rounded-full">暂缓</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2 text-sm text-neutral-700">二手</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<span class="text-sm text-neutral-500 truncate block max-w-[200px]">-</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<div class="flex items-center gap-1">
|
|
||||||
<span class="text-sm text-neutral-500">0套</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<span class="text-sm text-neutral-500">-</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<span class="text-sm text-neutral-700">魏深-都市港湾店一组</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<span class="text-sm text-neutral-500">未带看</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2 text-sm text-neutral-700 tabular-nums">0次</td>
|
|
||||||
<td class="px-4 py-2 text-sm text-neutral-600 tabular-nums">2026-04-01</td>
|
|
||||||
<td class="px-4 py-2 text-sm text-danger-600 tabular-nums">32天前</td>
|
|
||||||
<td class="px-3 py-2 text-center">
|
|
||||||
<button class="inline-flex items-center justify-center w-8 h-8 rounded-md text-primary-600 hover:bg-primary-50 hover:text-primary-700 transition-colors" title="拨号">
|
|
||||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="1.8" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M2.25 6.75c0 8.284 6.716 15 15 15h2.25a2.25 2.25 0 0 0 2.25-2.25v-1.372c0-.516-.351-.966-.852-1.091l-4.423-1.106c-.44-.11-.902.055-1.173.417l-.97 1.293c-.282.376-.769.542-1.21.38a12.035 12.035 0 0 1-7.143-7.143c-.162-.441.004-.928.38-1.21l1.293-.97c.363-.271.527-.734.417-1.173L6.963 3.102a1.125 1.125 0 0 0-1.091-.852H4.5A2.25 2.25 0 0 0 2.25 4.5v2.25Z"/></svg>
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<!-- 数据行 5 -->
|
|
||||||
<tr class="hover:bg-neutral-50 transition-colors"
|
|
||||||
:class="selected.includes('c005') ? 'bg-primary-50 hover:bg-primary-100' : ''">
|
|
||||||
<td class="w-10 px-4 py-2">
|
|
||||||
<input type="checkbox" value="c005" class="w-4 h-4 rounded accent-primary-600" x-model="selected">
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2 min-w-[160px]">
|
|
||||||
<div class="flex flex-col gap-0.5">
|
|
||||||
<a href="/clients/private/c005/" class="text-info-600 hover:underline font-medium text-sm truncate max-w-[160px]">陈建华</a>
|
|
||||||
<div class="flex items-center gap-1 flex-wrap">
|
|
||||||
<span class="text-[11px] text-neutral-500">B(较强)</span>
|
|
||||||
<span class="text-[11px] px-1.5 py-0.5 rounded-full font-medium bg-orange-50 text-orange-600">销售客</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<span class="bg-primary-50 text-primary-700 text-xs px-2 py-0.5 rounded-full">求购</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2 text-sm text-neutral-700">新房</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<span class="text-sm text-neutral-700 truncate block max-w-[200px]" title="300-400万,90㎡-110㎡,3居,嘉定/青浦">300-400万,90㎡-110㎡,3居,嘉定/青浦</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<div class="flex items-center gap-1">
|
|
||||||
<span class="text-sm text-neutral-700 font-medium">23套</span>
|
|
||||||
<button class="text-neutral-400 hover:text-info-600 transition-colors">
|
|
||||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="1.8" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z"/></svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<span class="text-sm text-neutral-700 truncate block max-w-[160px]">嘉定·新城,远香湖</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<span class="text-sm text-neutral-700">魏深-都市港湾店一组</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<span class="bg-success-50 text-success-600 px-2 py-0.5 rounded-full text-xs">复看</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2 text-sm text-neutral-700 tabular-nums">7次</td>
|
|
||||||
<td class="px-4 py-2 text-sm text-neutral-600 tabular-nums">2026-02-28</td>
|
|
||||||
<td class="px-4 py-2 text-sm text-neutral-700 tabular-nums">1天前</td>
|
|
||||||
<td class="px-3 py-2 text-center">
|
|
||||||
<button class="inline-flex items-center justify-center w-8 h-8 rounded-md text-primary-600 hover:bg-primary-50 hover:text-primary-700 transition-colors" title="拨号">
|
|
||||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="1.8" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M2.25 6.75c0 8.284 6.716 15 15 15h2.25a2.25 2.25 0 0 0 2.25-2.25v-1.372c0-.516-.351-.966-.852-1.091l-4.423-1.106c-.44-.11-.902.055-1.173.417l-.97 1.293c-.282.376-.769.542-1.21.38a12.035 12.035 0 0 1-7.143-7.143c-.162-.441.004-.928.38-1.21l1.293-.97c.363-.271.527-.734.417-1.173L6.963 3.102a1.125 1.125 0 0 0-1.091-.852H4.5A2.25 2.25 0 0 0 2.25 4.5v2.25Z"/></svg>
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<!-- 数据行 6 -->
|
|
||||||
<tr class="hover:bg-neutral-50 transition-colors"
|
|
||||||
:class="selected.includes('c006') ? 'bg-primary-50 hover:bg-primary-100' : ''">
|
|
||||||
<td class="w-10 px-4 py-2">
|
|
||||||
<input type="checkbox" value="c006" class="w-4 h-4 rounded accent-primary-600" x-model="selected">
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2 min-w-[160px]">
|
|
||||||
<div class="flex flex-col gap-0.5">
|
|
||||||
<a href="/clients/private/c006/" class="text-info-600 hover:underline font-medium text-sm truncate max-w-[160px]">周小燕</a>
|
|
||||||
<div class="flex items-center gap-1 flex-wrap">
|
|
||||||
<span class="text-[11px] text-neutral-500">D(较弱)</span>
|
|
||||||
<span class="text-[11px] px-1.5 py-0.5 rounded-full font-medium bg-danger-50 text-danger-600">无效</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<span class="bg-primary-50 text-primary-700 text-xs px-2 py-0.5 rounded-full">求购</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2 text-sm text-neutral-700">二手</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<span class="text-sm text-neutral-700 truncate block max-w-[200px]" title="200-300万,80㎡-100㎡,2居,普陀/长宁">200-300万,80㎡-100㎡,2居,普陀/长宁</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<div class="flex items-center gap-1">
|
|
||||||
<span class="text-sm text-neutral-700 font-medium">2套</span>
|
|
||||||
<button class="text-neutral-400 hover:text-info-600 transition-colors">
|
|
||||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="1.8" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z"/></svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<span class="text-sm text-neutral-700 truncate block max-w-[160px]">普陀·长风</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<span class="text-sm text-neutral-700">王芳-普陀新村店</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
<span class="text-sm text-neutral-500">未带看</span>
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2 text-sm text-neutral-700 tabular-nums">1次</td>
|
|
||||||
<td class="px-4 py-2 text-sm text-neutral-600 tabular-nums">2025-12-01</td>
|
|
||||||
<td class="px-4 py-2 text-sm text-danger-600 tabular-nums">45天前</td>
|
|
||||||
<td class="px-3 py-2 text-center">
|
|
||||||
<button class="inline-flex items-center justify-center w-8 h-8 rounded-md text-primary-600 hover:bg-primary-50 hover:text-primary-700 transition-colors" title="拨号">
|
|
||||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="1.8" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M2.25 6.75c0 8.284 6.716 15 15 15h2.25a2.25 2.25 0 0 0 2.25-2.25v-1.372c0-.516-.351-.966-.852-1.091l-4.423-1.106c-.44-.11-.902.055-1.173.417l-.97 1.293c-.282.376-.769.542-1.21.38a12.035 12.035 0 0 1-7.143-7.143c-.162-.441.004-.928.38-1.21l1.293-.97c.363-.271.527-.734.417-1.173L6.963 3.102a1.125 1.125 0 0 0-1.091-.852H4.5A2.25 2.25 0 0 0 2.25 4.5v2.25Z"/></svg>
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- ======== 分页栏 ======== -->
|
|
||||||
<div class="mt-4 flex items-center justify-between px-1">
|
|
||||||
<!-- 左侧:总条数 -->
|
|
||||||
<div class="text-sm text-neutral-500">
|
|
||||||
共 <span class="font-medium text-neutral-800 tabular-nums">1,248</span> 条
|
|
||||||
</div>
|
|
||||||
<!-- 中间:页码 -->
|
|
||||||
<div class="flex items-center gap-1">
|
|
||||||
<button class="flex items-center gap-1 px-2.5 py-1.5 text-sm text-neutral-600 hover:bg-neutral-100 rounded-md transition-colors disabled:opacity-40 disabled:cursor-not-allowed">
|
|
||||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 19.5 8.25 12l7.5-7.5"/></svg>
|
|
||||||
上一页
|
|
||||||
</button>
|
|
||||||
<button class="w-8 h-8 flex items-center justify-center text-sm bg-primary-600 text-white rounded-md font-medium tabular-nums">1</button>
|
|
||||||
<button class="w-8 h-8 flex items-center justify-center text-sm text-neutral-600 hover:bg-neutral-100 rounded-md transition-colors tabular-nums">2</button>
|
|
||||||
<button class="w-8 h-8 flex items-center justify-center text-sm text-neutral-600 hover:bg-neutral-100 rounded-md transition-colors tabular-nums">3</button>
|
|
||||||
<button class="w-8 h-8 flex items-center justify-center text-sm text-neutral-600 hover:bg-neutral-100 rounded-md transition-colors tabular-nums">4</button>
|
|
||||||
<button class="w-8 h-8 flex items-center justify-center text-sm text-neutral-600 hover:bg-neutral-100 rounded-md transition-colors tabular-nums">5</button>
|
|
||||||
<span class="w-8 h-8 flex items-center justify-center text-sm text-neutral-400">…</span>
|
|
||||||
<button class="w-8 h-8 flex items-center justify-center text-sm text-neutral-600 hover:bg-neutral-100 rounded-md transition-colors tabular-nums">63</button>
|
|
||||||
<button class="flex items-center gap-1 px-2.5 py-1.5 text-sm text-neutral-600 hover:bg-neutral-100 rounded-md transition-colors">
|
|
||||||
下一页
|
|
||||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="m8.25 4.5 7.5 7.5-7.5 7.5"/></svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<!-- 右侧:每页条数 + 跳页 -->
|
|
||||||
<div class="flex items-center gap-3 text-sm">
|
|
||||||
<select class="border border-neutral-300 rounded-md px-2 py-1.5 text-sm text-neutral-600 bg-white focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-600/40">
|
|
||||||
<option>20条/页</option>
|
|
||||||
<option>50条/页</option>
|
|
||||||
<option>100条/页</option>
|
|
||||||
</select>
|
|
||||||
<div class="flex items-center gap-1.5 text-neutral-500">
|
|
||||||
跳至
|
|
||||||
<input type="number" min="1" max="63"
|
|
||||||
class="w-14 px-2 py-1.5 border border-neutral-300 rounded-md text-center text-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-600/40 tabular-nums">
|
|
||||||
页
|
|
||||||
<button class="px-2.5 py-1.5 text-sm border border-neutral-300 rounded-md text-neutral-600 hover:bg-neutral-50 transition-colors">确定</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div><!-- /px-6 py-4 -->
|
|
||||||
|
|
||||||
|
|
||||||
<!-- ======== 自定义列弹窗 ======== -->
|
|
||||||
<div x-show="showColumnModal" x-cloak
|
|
||||||
class="fixed inset-0 z-50 flex items-center justify-center p-4"
|
|
||||||
x-transition:enter="ease-out duration-200"
|
|
||||||
x-transition:enter-start="opacity-0"
|
|
||||||
x-transition:enter-end="opacity-100"
|
|
||||||
x-transition:leave="ease-in duration-150"
|
|
||||||
x-transition:leave-start="opacity-100"
|
|
||||||
x-transition:leave-end="opacity-0">
|
|
||||||
<!-- Overlay -->
|
|
||||||
<div class="absolute inset-0 bg-neutral-900/40 backdrop-blur-sm" @click="showColumnModal = false"></div>
|
|
||||||
<!-- Modal -->
|
|
||||||
<div class="relative bg-white rounded-xl shadow-xl w-full max-w-2xl flex flex-col max-h-[80vh]"
|
|
||||||
x-transition:enter="ease-out duration-200"
|
|
||||||
x-transition:enter-start="opacity-0 scale-95 translate-y-2"
|
|
||||||
x-transition:enter-end="opacity-100 scale-100 translate-y-0">
|
|
||||||
<!-- Header -->
|
|
||||||
<div class="flex items-center justify-between px-6 py-4 border-b border-neutral-200">
|
|
||||||
<h2 class="text-base font-semibold text-neutral-800">自定义信息</h2>
|
|
||||||
<button @click="showColumnModal = false" class="text-neutral-400 hover:text-neutral-600 transition-colors">
|
|
||||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12"/></svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<!-- Body -->
|
|
||||||
<div class="flex flex-1 overflow-hidden">
|
|
||||||
<!-- 左栏:未选信息 -->
|
|
||||||
<div class="w-1/2 border-r border-neutral-200 overflow-y-auto">
|
|
||||||
<div class="px-4 py-3 text-xs font-semibold text-neutral-500 uppercase tracking-wide border-b border-neutral-100">未选信息</div>
|
|
||||||
<div class="p-3 space-y-1">
|
|
||||||
<label class="flex items-center gap-2.5 px-2 py-2 rounded-md hover:bg-neutral-50 cursor-pointer">
|
|
||||||
<input type="checkbox" class="w-4 h-4 rounded accent-primary-600"> <span class="text-sm text-neutral-700">录入日期</span>
|
|
||||||
</label>
|
|
||||||
<label class="flex items-center gap-2.5 px-2 py-2 rounded-md hover:bg-neutral-50 cursor-pointer">
|
|
||||||
<input type="checkbox" class="w-4 h-4 rounded accent-primary-600"> <span class="text-sm text-neutral-700">最近通话日期</span>
|
|
||||||
</label>
|
|
||||||
<label class="flex items-center gap-2.5 px-2 py-2 rounded-md hover:bg-neutral-50 cursor-pointer">
|
|
||||||
<input type="checkbox" class="w-4 h-4 rounded accent-primary-600"> <span class="text-sm text-neutral-700">用途</span>
|
|
||||||
</label>
|
|
||||||
<label class="flex items-center gap-2.5 px-2 py-2 rounded-md hover:bg-neutral-50 cursor-pointer">
|
|
||||||
<input type="checkbox" class="w-4 h-4 rounded accent-primary-600"> <span class="text-sm text-neutral-700">来源</span>
|
|
||||||
</label>
|
|
||||||
<label class="flex items-center gap-2.5 px-2 py-2 rounded-md hover:bg-neutral-50 cursor-pointer">
|
|
||||||
<input type="checkbox" class="w-4 h-4 rounded accent-primary-600"> <span class="text-sm text-neutral-700">客源编号</span>
|
|
||||||
</label>
|
|
||||||
<label class="flex items-center gap-2.5 px-2 py-2 rounded-md hover:bg-neutral-50 cursor-pointer">
|
|
||||||
<input type="checkbox" class="w-4 h-4 rounded accent-primary-600"> <span class="text-sm text-neutral-700">首录人</span>
|
|
||||||
</label>
|
|
||||||
<label class="flex items-center gap-2.5 px-2 py-2 rounded-md hover:bg-neutral-50 cursor-pointer">
|
|
||||||
<input type="checkbox" class="w-4 h-4 rounded accent-primary-600"> <span class="text-sm text-neutral-700">成交人</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- 右栏:已选信息 -->
|
|
||||||
<div class="w-1/2 overflow-y-auto">
|
|
||||||
<div class="px-4 py-3 text-xs font-semibold text-neutral-500 uppercase tracking-wide border-b border-neutral-100">已选信息</div>
|
|
||||||
<div class="p-3 space-y-1">
|
|
||||||
<!-- 固定字段(不可删) -->
|
|
||||||
<div class="flex items-center gap-2 px-2 py-2 rounded-md bg-neutral-50">
|
|
||||||
<svg class="w-4 h-4 text-neutral-300 cursor-grab" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M3.75 5.25h16.5m-16.5 4.5h16.5m-16.5 4.5h16.5m-16.5 4.5h16.5"/></svg>
|
|
||||||
<span class="text-sm text-neutral-700 flex-1">姓名</span>
|
|
||||||
<svg class="w-3.5 h-3.5 text-neutral-300" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M16.5 10.5V6.75a4.5 4.5 0 1 0-9 0v3.75m-.75 11.25h10.5a2.25 2.25 0 0 0 2.25-2.25v-6.75a2.25 2.25 0 0 0-2.25-2.25H6.75a2.25 2.25 0 0 0-2.25 2.25v6.75a2.25 2.25 0 0 0 2.25 2.25Z"/></svg>
|
|
||||||
</div>
|
|
||||||
<!-- 可删字段 -->
|
|
||||||
<template x-for="(col, idx) in selectedColumns" :key="col">
|
|
||||||
<div class="flex items-center gap-2 px-2 py-2 rounded-md hover:bg-neutral-50 group">
|
|
||||||
<svg class="w-4 h-4 text-neutral-300 cursor-grab group-hover:text-neutral-400" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M3.75 5.25h16.5m-16.5 4.5h16.5m-16.5 4.5h16.5m-16.5 4.5h16.5"/></svg>
|
|
||||||
<span class="text-sm text-neutral-700 flex-1" x-text="col"></span>
|
|
||||||
<button @click="selectedColumns.splice(idx, 1)" class="text-neutral-400 hover:text-danger-600 transition-colors opacity-0 group-hover:opacity-100">
|
|
||||||
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12"/></svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
<p class="px-5 pb-3 text-xs text-neutral-400">提示:拖拽可调整展示顺序</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- Footer -->
|
|
||||||
<div class="flex items-center justify-between px-6 py-4 border-t border-neutral-200">
|
|
||||||
<button class="text-sm text-neutral-500 hover:text-neutral-700 transition-colors">恢复默认</button>
|
|
||||||
<div class="flex items-center gap-3">
|
|
||||||
<button @click="showColumnModal = false" class="px-4 py-2 text-sm text-neutral-600 border border-neutral-300 rounded-lg hover:bg-neutral-50 transition-colors">取消</button>
|
|
||||||
<button @click="showColumnModal = false" class="px-4 py-2 text-sm font-medium bg-primary-600 hover:bg-primary-700 text-white rounded-lg transition-colors">确定</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div><!-- /modal -->
|
|
||||||
|
|
||||||
</main><!-- /clientListApp -->
|
|
||||||
|
|
||||||
|
|
||||||
<script>
|
|
||||||
function clientListApp() {
|
|
||||||
return {
|
|
||||||
// 二级 Tab
|
|
||||||
activeTab: 'all',
|
|
||||||
tabs: [
|
|
||||||
{ key: 'buying', label: '求购', count: 913 },
|
|
||||||
{ key: 'renting', label: '求租', count: 187 },
|
|
||||||
{ key: 'suspended', label: '暂缓', count: null },
|
|
||||||
{ key: 'all', label: '全部私客', count: null },
|
|
||||||
],
|
|
||||||
|
|
||||||
// 筛选区展开
|
|
||||||
showFilters: true,
|
|
||||||
|
|
||||||
// 状态筛选选项
|
|
||||||
activeStatus: '',
|
|
||||||
statusOptions: [
|
|
||||||
{ value: '', label: '不限' },
|
|
||||||
{ value: 'buying', label: '求购' },
|
|
||||||
{ value: 'buy_or_rent', label: '租购' },
|
|
||||||
],
|
|
||||||
|
|
||||||
// 表格勾选
|
|
||||||
selected: [],
|
|
||||||
|
|
||||||
toggleAll(event) {
|
|
||||||
if (event.target.checked) {
|
|
||||||
this.selected = ['c001', 'c002', 'c003', 'c004', 'c005', 'c006'];
|
|
||||||
} else {
|
|
||||||
this.selected = [];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// 自定义列弹窗
|
|
||||||
showColumnModal: false,
|
|
||||||
selectedColumns: ['状态', '需求类型', '需求/解读', '智能配房', '意向商圈/小区', '归属人', '带看进度', '带看次数', '委托日期', '最近时间'],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -737,21 +737,21 @@ HTMX loading 触发:在 `<div id="client-list-container">` 添加 `hx-indicato
|
|||||||
表头行:`<thead class="bg-neutral-50">`,列头单元格统一样式:`px-4 py-3 text-left text-xs font-semibold text-neutral-500 uppercase tracking-wide whitespace-nowrap`
|
表头行:`<thead class="bg-neutral-50">`,列头单元格统一样式:`px-4 py-3 text-left text-xs font-semibold text-neutral-500 uppercase tracking-wide whitespace-nowrap`
|
||||||
数据行:`<tr class="hover:bg-neutral-50 transition-colors" style="height:56px">`
|
数据行:`<tr class="hover:bg-neutral-50 transition-colors" style="height:56px">`
|
||||||
|
|
||||||
| # | 列名 | 数据字段 | 列宽 | 对齐 | 可排序 | 特殊渲染说明 |
|
| # | 列名 | 数据字段 | 列宽 | 对齐 | 可排序 | 特殊渲染说明 |
|
||||||
|---|---|---|---|---|---|---|
|
| --- | ------- | ---------------------------------------------- | ----------------------------- | --- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| 1 | (复选框) | — | `w-10`(40px)`px-4` | 居中 | 否 | 全选:表头 `<input type="checkbox" id="select-all">`;单选:行内 `<input type="checkbox" x-model="selected" :value="client.id">` |
|
| 1 | (复选框) | — | `w-10`(40px)`px-4` | 居中 | 否 | 全选:表头 `<input type="checkbox" id="select-all">`;单选:行内 `<input type="checkbox" x-model="selected" :value="client.id">` |
|
||||||
| 2 | 姓名 | `contact_name` + `grade_display` + 活跃度标签 | `min-w-[160px] max-w-[200px]` | 左对齐 | 否 | 蓝色链接 `text-info-600 hover:underline`;下方渲染 Grade Badge + 活跃度 Tag(见 §3.2) |
|
| 2 | 姓名 | `contact_name` + `grade_display` + 活跃度标签 | `min-w-[160px] max-w-[200px]` | 左对齐 | 否 | 蓝色链接 `text-primary-600 hover:underline`;下方渲染 Grade Badge + 活跃度 Tag(见 §3.2) |
|
||||||
| 3 | 状态 | `status_display` | `w-20`(80px) | 左对齐 | 否 | Status Badge(见 §3.2) |
|
| 3 | 状态 | `status_display` | `w-20`(80px) | 左对齐 | 否 | Status Badge(见 §3.2) |
|
||||||
| 4 | 需求类型 | `requirement_type_display` | `w-20`(80px) | 左对齐 | 否 | 纯文字:二手 / 新房 / 租房 |
|
| 4 | 需求类型 | `requirement_type_display` | `w-20`(80px) | 左对齐 | 否 | 纯文字:二手 / 新房 / 租房 |
|
||||||
| 5 | 需求/解读 | `budget_area_display` | `min-w-[180px]` | 左对齐 | 否 | 截断 `truncate`;Tooltip 展示完整内容(`title` 属性) |
|
| 5 | 需求/解读 | `budget_area_display` | `min-w-[180px]` | 左对齐 | 否 | 截断 `truncate`;Tooltip 展示完整内容(`title` 属性) |
|
||||||
| 6 | 智能配房 | `match_count` | `w-24`(96px) | 左对齐 | 否 | `N套` + Heroicon `information-circle`(`w-4 h-4 text-neutral-400 ml-1 cursor-pointer`);点击弹出配房预览 Popover |
|
| 6 | 智能配房 | `match_count` | `w-24`(96px) | 左对齐 | 否 | `N套` + Heroicon `information-circle`(`w-4 h-4 text-neutral-400 ml-1 cursor-pointer`);点击弹出配房预览 Popover |
|
||||||
| 7 | 意向商圈/小区 | `intent_location_display` | `min-w-[120px]` | 左对齐 | 否 | 多值逗号分隔;`-` 表示未填;截断 `truncate max-w-[160px]` |
|
| 7 | 意向商圈/小区 | `intent_location_display` | `min-w-[120px]` | 左对齐 | 否 | 多值逗号分隔;`-` 表示未填;截断 `truncate max-w-[160px]` |
|
||||||
| 8 | 归属人 | `owner_display` | `min-w-[140px]` | 左对齐 | 否 | 格式:`姓名-门店组`;`text-sm text-neutral-700` |
|
| 8 | 归属人 | `owner_display` | `min-w-[140px]` | 左对齐 | 否 | 格式:`姓名-门店组`;`text-sm text-neutral-700` |
|
||||||
| 9 | 带看进度 | `viewing_progress_display` | `w-20`(80px) | 左对齐 | 否 | 「未带看」灰色文字;「一看」`bg-warning-50 text-warning-600 px-2 py-0.5 rounded-full text-xs`;「二看」`bg-info-50 text-info-600`;「复看」`bg-success-50 text-success-600` |
|
| 9 | 带看进度 | `viewing_progress_display` | `w-20`(80px) | 左对齐 | 否 | 「未带看」灰色文字;「一看」`bg-warning-50 text-warning-600 px-2 py-0.5 rounded-full text-xs`;「二看」`bg-info-50 text-info-600`;「复看」`bg-success-50 text-success-600` |
|
||||||
| 10 | 带看次数 | `viewing_count` | `w-[72px]` | 左对齐 | 是 | `N次`;点击列头触发 HTMX 排序 |
|
| 10 | 带看次数 | `viewing_count` | `w-[72px]` | 左对齐 | 是 | `N次`;点击列头触发 HTMX 排序 |
|
||||||
| 11 | 委托日期 | `commission_date` | `w-24`(96px) | 左对齐 | 是 | `YYYY-MM-DD`;未填显示 `-` |
|
| 11 | 委托日期 | `commission_date` | `w-24`(96px) | 左对齐 | 是 | `YYYY-MM-DD`;未填显示 `-` |
|
||||||
| 12 | 最近时间 | `last_follow_display` / `last_contact_display` | `w-24`(96px) | 左对齐 | 是(默认降序) | `N天前` / `今天`;超过 30 天字色 `text-danger-600` |
|
| 12 | 最近时间 | `last_follow_display` / `last_contact_display` | `w-24`(96px) | 左对齐 | 是(默认降序) | `N天前` / `今天`;超过 30 天字色 `text-danger-600` |
|
||||||
| 13 | 操作 | — | `w-16`(64px) | 居中 | 否 | 见 §3.3 |
|
| 13 | 操作 | — | `w-16`(64px) | 居中 | 否 | 见 §3.3 |
|
||||||
|
|
||||||
> **自定义列**(P1 🟡):用户通过「自定义列表」弹窗(§4.1)选择显示字段后,后端将用户配置存入 `UserColumnPreference`,Django 模板根据配置动态渲染列头和列单元格。可选字段见截图 `客源列表-自定义字段.png`:录入日期、最近通话日期、用途、来源、客源编号、首录人、成交人等。
|
> **自定义列**(P1 🟡):用户通过「自定义列表」弹窗(§4.1)选择显示字段后,后端将用户配置存入 `UserColumnPreference`,Django 模板根据配置动态渲染列头和列单元格。可选字段见截图 `客源列表-自定义字段.png`:录入日期、最近通话日期、用途、来源、客源编号、首录人、成交人等。
|
||||||
|
|
||||||
|
|||||||
1115
Project/fonrey/UI_DESIGN/房源列表_UI.html
Normal file
1115
Project/fonrey/UI_DESIGN/房源列表_UI.html
Normal file
File diff suppressed because it is too large
Load Diff
1379
Project/fonrey/UI_DESIGN/房源管理/房源列表_UI.md
Normal file
1379
Project/fonrey/UI_DESIGN/房源管理/房源列表_UI.md
Normal file
File diff suppressed because it is too large
Load Diff
@@ -622,6 +622,22 @@ Fonrey 的核心场景,规范必须严格执行。
|
|||||||
| 逾期 / 紧急 / 冻结 | danger | `bg-danger-50 text-danger-600` |
|
| 逾期 / 紧急 / 冻结 | danger | `bg-danger-50 text-danger-600` |
|
||||||
| 暂缓 | 浅灰 + 斜体 | `bg-neutral-100 text-neutral-600 italic` |
|
| 暂缓 | 浅灰 + 斜体 | `bg-neutral-100 text-neutral-600 italic` |
|
||||||
|
|
||||||
|
#### 3.7.2 交易类型标签色板
|
||||||
|
|
||||||
|
交易类型标签(买卖 / 租赁 / 租售)属于**分类标签**,不表达状态语义,禁止使用语义色(danger / info solid)。
|
||||||
|
|
||||||
|
**视觉层级要求**:交易类型标签须比同行副标签(满五、独家等)**更大、更醒目**:
|
||||||
|
- 交易类型标签:`text-xs`(12px)+ `px-2 py-0.5` + `font-semibold` + 较深底色
|
||||||
|
- 副标签(房源属性 Tag):`text-[10px]` + `px-1.5 py-0.5` + `font-medium` + 极淡底色
|
||||||
|
|
||||||
|
| 交易类型 | 色系 | Tailwind 类 | 设计理由 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 买卖 | primary(Teal) | `bg-primary-200 text-primary-800` | 核心出售业务,用品牌主色强调 |
|
||||||
|
| 租赁 | warning(Amber) | `bg-warning-200 text-warning-800` | 与买卖形成色相区分,暖色低调 |
|
||||||
|
| 租售 | neutral | `bg-neutral-300 text-neutral-800` | 兼含两种类型,中性色避免歧义 |
|
||||||
|
|
||||||
|
> **禁止**对交易类型标签使用 Solid 样式(`bg-{color}-600 text-white`),该样式仅用于极少数强调性状态(如"紧急")。
|
||||||
|
|
||||||
#### 3.7.2 标准片段
|
#### 3.7.2 标准片段
|
||||||
|
|
||||||
```html
|
```html
|
||||||
|
|||||||
@@ -42,6 +42,7 @@
|
|||||||
- TECH_STACK:`Project/fonrey/TECH_STACK/TECH_STACK.md`
|
- TECH_STACK:`Project/fonrey/TECH_STACK/TECH_STACK.md`
|
||||||
- 登录管理技术方案:`Project/fonrey/TECH_STACK/登录管理技术方案.md`
|
- 登录管理技术方案:`Project/fonrey/TECH_STACK/登录管理技术方案.md`
|
||||||
- 权限管理技术方案:`Project/fonrey/TECH_STACK/登录管理技术方案.md`
|
- 权限管理技术方案:`Project/fonrey/TECH_STACK/登录管理技术方案.md`
|
||||||
|
- 测试规范:`Project/fonrey/TECH_STACK/测试规范`
|
||||||
|
|
||||||
**数据模型**
|
**数据模型**
|
||||||
- DATA_MODEL:`Project/fonrey/DATA_MODEL/DATA_MODEL.md`
|
- DATA_MODEL:`Project/fonrey/DATA_MODEL/DATA_MODEL.md`
|
||||||
@@ -58,11 +59,21 @@
|
|||||||
- 模块UI Design:
|
- 模块UI Design:
|
||||||
- `Project/fonrey/UI_DESIGN/客源列表_UI.md`
|
- `Project/fonrey/UI_DESIGN/客源列表_UI.md`
|
||||||
- `Project/fonrey/UI_DESIGN/客源详情_UI.md`
|
- `Project/fonrey/UI_DESIGN/客源详情_UI.md`
|
||||||
|
- `Project/fonrey/UI_DESIGN/客源管理/新增客源_UI`
|
||||||
|
- `Project/fonrey/UI_DESIGN/客源管理/编辑客源_UI`
|
||||||
|
- `Project/fonrey/UI_DESIGN/房源管理/房源列表_UI`
|
||||||
|
|
||||||
**UI 原型页面**:
|
**UI 原型页面**:
|
||||||
- UI SYSTEM: `Project/fonrey/UI_SYSTEM/preview`
|
- UI SYSTEM: `Project/fonrey/UI_DESIGN/preview.html`
|
||||||
- 客源列表:`Project/fonrey/UI_DESIGN/客源列表_UI.html`
|
- 客源列表:`Project/fonrey/UI_DESIGN/客源列表_UI.html`
|
||||||
- 客源详情:`Project/fonrey/UI_DESIGN/客源详情_UI.html`
|
- 客源详情:`Project/fonrey/UI_DESIGN/客源详情_UI.html`
|
||||||
|
- 编辑客源:`Project/fonrey/UI_DESIGN/编辑客源_UI.html`
|
||||||
|
- 新增客源:`Project/fonrey/UI_DESIGN/新增客源_UI.html`
|
||||||
|
- 房源列表:`Project/fonrey/UI_DESIGN/房源列表_UI.html`
|
||||||
|
|
||||||
|
**任务汇总**
|
||||||
|
- TASK:`Project/fonrey/PRD/TASK.md`
|
||||||
|
|
||||||
|
|
||||||
**其他参考文档**:
|
**其他参考文档**:
|
||||||
|
|
||||||
115
Project/fonrey/prompt/TASK - 模块实现TASK项目任务生成提示词.md
Normal file
115
Project/fonrey/prompt/TASK - 模块实现TASK项目任务生成提示词.md
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
|
||||||
|
你是一个 B2B SaaS 项目的产品/技术项目经理。你的任务是根据下方的 PRD.md及PRD_MPV.md 内容,生成一份完整的 TASK.md 项目任务看板文件。
|
||||||
|
|
||||||
|
## 任务说明:
|
||||||
|
根据客源的PRD文档,生成具体能落地的项目实现TASK列表
|
||||||
|
|
||||||
|
## 输入材料
|
||||||
|
|
||||||
|
- 模块PRD文档:`Project/fonrey/PRD/客源管理/客源管理模块PRD.md`
|
||||||
|
- 模块DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_CLIENT.md`
|
||||||
|
- TECH_STACK文档:`Project/fonrey/TECH_STACK/TECH_STACK.md`
|
||||||
|
- UI_SYSTEM文档:`Project/fonrey/UI_SYSTEM/UI_SYSTEM.md`
|
||||||
|
- `Project/fonrey/UI_DESIGN/客源管理/新增客源_UI.md`
|
||||||
|
- `Project/fonrey/UI_DESIGN/客源管理/客源列表_UI.md`
|
||||||
|
- `Project/fonrey/UI_DESIGN/客源管理/编辑客源_UI.md`
|
||||||
|
- `Project/fonrey/UI_DESIGN/客源管理/客源详情_UI.md`
|
||||||
|
- - 模块PRD)MPV文档:`Project/fonrey/PRD/PRD_MVP.md`
|
||||||
|
|
||||||
|
## 输出要求
|
||||||
|
|
||||||
|
**输出文档**:`Project/fonrey/PRD/TASK.md`
|
||||||
|
|
||||||
|
### 文件结构规则
|
||||||
|
按以下 Phase 划分,严格对应 PRD 优先级:
|
||||||
|
- **Phase 1 - MVP(P0,上线前必须完成)** → PRD 中标注 P0 的功能
|
||||||
|
- **Phase 2 - 增强功能(P1,MVP 后第一迭代)** → PRD 中标注 P1 的功能
|
||||||
|
- **Phase 3 - 路线图功能(P2,已规划未排期)** → PRD 中标注 P2 的功能
|
||||||
|
- **Phase 4 - 明确不做(Out of Scope)** → PRD 第 3 节"非目标"中的功能,仅列出条目作为备忘,不写 task 详情
|
||||||
|
|
||||||
|
### 模块顺序(按 PRD 顺序)
|
||||||
|
1. 用户登录
|
||||||
|
2. 楼盘管理
|
||||||
|
3. 房源管理
|
||||||
|
4. 客源管理
|
||||||
|
5. 组织人事
|
||||||
|
6. 权限管理
|
||||||
|
7. 系统配置
|
||||||
|
8. 系统管理(运营后台)
|
||||||
|
9. 客户端发布
|
||||||
|
|
||||||
|
**请在项目目录里寻找匹配的文档填入下面具体的任务列表**
|
||||||
|
### 每条 Task 格式(严格遵守)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### [模块中文名]
|
||||||
|
|
||||||
|
- [ ] US-XXX [动词开头的功能描述,主语为"经纪人/店长/管理员/系统"]
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/[模块名]/[模块名]模块PRD.md` - [对应 Story 或功能点名称]
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_[模块英文名].md`
|
||||||
|
- 参考UI_Design文档:`Project/fonrey/UI_DESIGN/[模块名]/[功能名]_UI.md`
|
||||||
|
- 参考UI静态原型页面:`Project/fonrey/UI_DESIGN/[模块名]/[功能名]_UI.html`
|
||||||
|
- 验收标准:[从 PRD 功能描述提炼 2-4 条可测试的验收标准,用分号分隔]
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### US 编号规则
|
||||||
|
- US 编号全局唯一,按模块分段:
|
||||||
|
- 用户登录:US-ACCOUNT-001 ~ US-ACCOUNT-100
|
||||||
|
- 楼盘管理:US-COMPLEX-001 ~ US-COMPLEX-100
|
||||||
|
- 房源管理:US-PROPERTY-001 ~ US-PROPERTY-100
|
||||||
|
- 客源管理:US-CLIENT-001 ~ US-CLIENT-100
|
||||||
|
- 组织人事:US-ORG-001 ~ US-ORG-100
|
||||||
|
- 权限管理:US-PERMISSION-001 ~ US-PERMISSION-100
|
||||||
|
- 系统配置:US-SETTING-001 ~ US-SETTING-100
|
||||||
|
- 系统管理:US-SYSTEM-001 ~ US-SYSTEM-100
|
||||||
|
- 客户端发布:US-RELEASE-001 ~ US-RELEASE-100
|
||||||
|
|
||||||
|
### 文件头部格式
|
||||||
|
```
|
||||||
|
|
||||||
|
## Project Task Board
|
||||||
|
|
||||||
|
### 项目状态总览
|
||||||
|
|
||||||
|
- 产品名称:Fonrey 房睿
|
||||||
|
- 当前阶段:MVP Phase 1
|
||||||
|
- 技术栈:[待填写]
|
||||||
|
- 最后更新:2026-04-24
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### 文件尾部格式
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 已完成
|
||||||
|
|
||||||
|
(暂无)
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## 生成规则与约束
|
||||||
|
|
||||||
|
1. **PRD 里每一行功能条目都必须生成至少一条 Task**,不得遗漏
|
||||||
|
2. **Phase 4(Out of Scope)** 只用注释格式列出,不写 US 编号和子项:
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- OUT OF SCOPE: 移动端适配 - v2 规划 -->
|
||||||
|
|
||||||
|
```
|
||||||
|
3. **验收标准**必须是可测试的具体行为,禁止写"功能正常"等模糊描述
|
||||||
|
4. 文档路径中的模块英文名对照:
|
||||||
|
- 房源管理 → PROPERTY
|
||||||
|
- 客源管理 → CLIENT
|
||||||
|
- 楼盘管理 → COMPLEX
|
||||||
|
- 组织人事 → ORG
|
||||||
|
- 权限管理 → PERMISSION
|
||||||
|
- 用户登录 → ACCOUNT
|
||||||
|
- 系统配置 → SETTING
|
||||||
|
- 系统管理 → SYSTEM
|
||||||
|
3. 一个 PRD 功能条目如果包含多个子操作(如"新增/编辑/查看"),可以拆成多条 Task,也可以合并为一条,根据复杂度判断
|
||||||
|
4. 输出纯 Markdown 格式,不加任何解释说明,直接输出文件内容
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
# Project Task Board
|
|
||||||
|
|
||||||
## 项目状态总览
|
|
||||||
- 当前阶段:MVP Phase 1
|
|
||||||
- 技术栈:[你的 tech stack 简述]
|
|
||||||
- 最后更新:YYYY-MM-DD
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Phase 1 - MVP(P0,必须完成)
|
|
||||||
|
|
||||||
### [模块名,如:用户认证]
|
|
||||||
- [ ] US-001 用户可以用邮箱注册账号
|
|
||||||
- 涉及文件:`/auth/register.tsx`, `userModel`
|
|
||||||
- 验收标准:表单校验通过 → 写入 DB → 跳转登录页
|
|
||||||
- [ ] US-002 用户可以登录并保持会话
|
|
||||||
- 涉及文件:`/auth/login.tsx`, `sessionModel`
|
|
||||||
- 验收标准:JWT 生成 → localStorage 存储 → 保护路由生效
|
|
||||||
|
|
||||||
### [模块名,如:仪表盘]
|
|
||||||
- [ ] US-005 用户可以看到核心数据概览
|
|
||||||
- 涉及文件:`/dashboard/index.tsx`
|
|
||||||
- 验收标准:数据从 API 读取,与 UI 原型视觉一致
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Phase 2 - 增强功能(P1,MVP 后实现)
|
|
||||||
|
|
||||||
- [ ] US-010 用户可以导出数据为 CSV
|
|
||||||
- [ ] US-011 支持第三方登录(Google OAuth)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Phase 3 - 锦上添花(P2,有时间再做)
|
|
||||||
|
|
||||||
- [ ] US-020 动画和过渡效果优化
|
|
||||||
- [ ] US-021 深色模式支持
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 已完成
|
|
||||||
- [x] US-XXX xxxxxxx(完成日期)
|
|
||||||
340
Project/fonrey/prompt/UI - 为 房源列表生成模块 UI 设计文档.md
Normal file
340
Project/fonrey/prompt/UI - 为 房源列表生成模块 UI 设计文档.md
Normal file
@@ -0,0 +1,340 @@
|
|||||||
|
# 任务:为房源列表 生成模块 UI 设计文档
|
||||||
|
|
||||||
|
## 你的角色
|
||||||
|
|
||||||
|
你是 Fonrey 房产经纪管理系统的 **UI/UX 架构师**,负责根据竞品截图和 PRD 功能描述,产出一份标准化的模块级 UI 设计文档。该文档将直接交给 AI Engineer 用于编码实现,必须包含足够的细节,Engineer 无需再问任何问题。
|
||||||
|
|
||||||
|
**注意**
|
||||||
|
以下所有的文档或图片是基于文档库的相对路径。
|
||||||
|
文档库的根路径为:`/mnt/d/Workspace/nexus`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 全局设计约束(必须严格遵守)
|
||||||
|
|
||||||
|
> 所有设计决策必须符合 `Project/fonrey/UI_SYSTEM/UI_SYSTEM.md` 中的设计规范。核心约束如下:
|
||||||
|
|
||||||
|
- **技术栈**:Tailwind CSS + HTMX + Alpine.js + Django HTML 模板(非 React/Vue/JSX)
|
||||||
|
- **图标库**:Heroicons v2(Outline 24px 默认,Solid 20px 强调,Mini 16px 极密场景)
|
||||||
|
- **主色**:Teal `#0F766E`(`primary-600`),所有颜色引用 Token,禁止硬编码 Hex
|
||||||
|
- **圆角**:`rounded-lg`(8px)为默认,表格行/小组件用 `rounded-md`(6px)
|
||||||
|
- **表格行高**:56px(`h-14`)
|
||||||
|
- **字体**:Inter + PingFang SC,正文 `text-sm`(14px)
|
||||||
|
- **焦点环**:`focus-visible:ring-2 focus-visible:ring-primary-600/40`
|
||||||
|
- **桌面优先**:≥1280px,不做移动端适配
|
||||||
|
- **禁止独立 CSS 文件或 CSS-in-JS**:所有样式用 Tailwind utility class(少量例外如 Flatpickr 覆盖样式)
|
||||||
|
- **组件实现参考**:`Project/fonrey/UI_SYSTEM/组件规范设计.md`(含 20 个特殊组件的完整 HTML + Alpine.js 实现)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 本次任务输入
|
||||||
|
|
||||||
|
### 1. 目标模块
|
||||||
|
|
||||||
|
**模块名称**:房源列表
|
||||||
|
**模块描述**:房源列表
|
||||||
|
|
||||||
|
### 2. PRD 功能文档路径
|
||||||
|
|
||||||
|
```
|
||||||
|
{{PRD文件路径,如:Project/fonrey/PRD/房源管理/房源管理模块PRD.md}}
|
||||||
|
```
|
||||||
|
|
||||||
|
请读取该文件,理解每个功能点的业务逻辑和验收标准。
|
||||||
|
|
||||||
|
### 3. DATA_MODEL 数据模型文档路径
|
||||||
|
|
||||||
|
```
|
||||||
|
{{DATA_MODEL文件路径,如:Project/fonrey/DATA_MODEL/DATA_MODEL_PROPERTY.md}}
|
||||||
|
```
|
||||||
|
|
||||||
|
请读取该文件,理解该模块的数据模型以及字段命名。
|
||||||
|
|
||||||
|
### 4. 竞品参考截图
|
||||||
|
|
||||||
|
请读取以下截图文件作为视觉参考(所有截图均在 `Project/fonrey/screenshots/` 目录下):
|
||||||
|
- 房源列表:
|
||||||
|
- `Project/fonrey/screenshots/房源/房源列表.png`
|
||||||
|
- `Project/fonrey/screenshots/房源/全部房源.png`
|
||||||
|
|
||||||
|
### 5. 参考已完成类似页面设计
|
||||||
|
请读取以下已完成和当前模块页面设计类似的文档和页面:
|
||||||
|
- 客源列表UI文档设计:`Project/fonrey/UI_DESIGN/客源管理/客源列表_UI.md`
|
||||||
|
- 客源泪飙UI静态原型:`Project/fonrey/UI_DESIGN/客源管理/客源列表_UI.html`
|
||||||
|
|
||||||
|
### 6. MVP 优先级参考
|
||||||
|
|
||||||
|
请参考 `Project/fonrey/PRD/PRD_MVP.md`,在设计文档中标注每个页面/功能的优先级(P0/P1/P2)。
|
||||||
|
|
||||||
|
---
|
||||||
|
## 输出格式要求
|
||||||
|
|
||||||
|
输出一份完整的 Markdown 文档,`Project/fonrey/UI_DESIGN/房源列表_UI.md`,结构如下:
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# {{模块名称}} UI 设计文档
|
||||||
|
|
||||||
|
> **版本**:v1.0 · **日期**:{今日日期}
|
||||||
|
> **依赖规范**:UI_SYSTEM.md v1.1 · 组件规范设计.md v1.0
|
||||||
|
> **PRD 来源**:{PRD文件路径}
|
||||||
|
> **优先级**:P0 功能在本文档中用 🔴 标注,P1 用 🟡,P2 用 ⚫
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 目录
|
||||||
|
|
||||||
|
(列出本文档所有章节)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 模块概述
|
||||||
|
|
||||||
|
### 1.1 功能范围
|
||||||
|
(从 PRD 提取本模块包含的所有功能,按优先级分组列表)
|
||||||
|
|
||||||
|
### 1.2 页面清单
|
||||||
|
(列出本模块所有页面/视图,每行包含:页面名称 | URL 模式建议 | 优先级 | 对应 PRD 章节)
|
||||||
|
|
||||||
|
### 1.3 用户角色与权限差异
|
||||||
|
(说明不同角色(经纪人/店长/管理员)在本模块的视图差异,如哪些字段/按钮对特定角色隐藏)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 页面设计规范
|
||||||
|
|
||||||
|
> 每个页面单独一节,按以下子结构输出。
|
||||||
|
|
||||||
|
### 2.N {页面名称}({优先级} 🔴/🟡/⚫)
|
||||||
|
|
||||||
|
#### 2.N.1 页面概述
|
||||||
|
- **URL**:`/模块/页面/`
|
||||||
|
- **访问入口**:(从哪里进入此页面)
|
||||||
|
- **页面职责**:(一句话)
|
||||||
|
- **竞品参考截图**:`{截图路径}`
|
||||||
|
|
||||||
|
#### 2.N.2 布局结构
|
||||||
|
(用文字描述页面整体布局,如:三栏布局、左侧边栏+右侧主内容区、全宽列表等)
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
┌──────────────────────────────────────────────────────────┐
|
||||||
|
│ 顶部区域(Breadcrumb / 页面标题 / 主操作按钮) │
|
||||||
|
├──────────────────────────────────────────────────────────┤
|
||||||
|
│ 筛选区域(可折叠) │
|
||||||
|
├──────────────────────────────────────────────────────────┤
|
||||||
|
│ 工具栏(批量操作 / 排序切换 / 列设置 / 导出) │
|
||||||
|
├──────────────────────────────────────────────────────────┤
|
||||||
|
│ 主内容区(表格 / 详情卡片 / 表单) │
|
||||||
|
├──────────────────────────────────────────────────────────┤
|
||||||
|
│ 分页栏 │
|
||||||
|
└──────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
```
|
||||||
|
(根据实际页面调整此 ASCII 图)
|
||||||
|
|
||||||
|
#### 2.N.3 区域详细规范
|
||||||
|
|
||||||
|
> 每个区域独立描述,包含:组件类型、字段/按钮清单、交互逻辑
|
||||||
|
|
||||||
|
**[区域名称,如:搜索筛选区]**
|
||||||
|
|
||||||
|
| 属性 | 说明 |
|
||||||
|
|---|---|
|
||||||
|
| 组件 | (引用组件规范设计.md 中的组件名,如:Date Range Picker) |
|
||||||
|
| 展开/收起 | (是否支持折叠,默认状态) |
|
||||||
|
| 筛选字段 | (列出所有筛选字段及输入类型) |
|
||||||
|
| 联动逻辑 | (字段间的联动关系) |
|
||||||
|
| HTMX 行为 | (如:`hx-get="/api/xxx/" hx-trigger="change" hx-target="#table-body"`) |
|
||||||
|
|
||||||
|
**[区域名称,如:数据表格]**
|
||||||
|
|
||||||
|
| 列名 | 数据类型 | 宽度 | 排序 | 特殊渲染 |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| (列名) | (string/number/date/badge/...) | (fixed px 或 auto) | (是/否) | (如:Tag、趋势箭头、行内按钮) |
|
||||||
|
|
||||||
|
(补充表格交互说明:行点击跳转、批量选择、列固定等)
|
||||||
|
|
||||||
|
#### 2.N.4 使用的特殊组件
|
||||||
|
|
||||||
|
| 组件名 | 来源(组件规范设计.md 章节) | 用途 | 自定义说明 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| (组件名) | (如:§1 Data Table) | (用于展示xxx列表) | (如果有与标准实现不同的地方,详细说明) |
|
||||||
|
|
||||||
|
#### 2.N.5 空状态设计
|
||||||
|
(描述列表/表格无数据时的展示方式,参考 UI_SYSTEM.md §6.3 空状态设计)
|
||||||
|
|
||||||
|
#### 2.N.6 Loading 状态
|
||||||
|
(描述数据加载中的骨架屏或加载指示方案)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 弹窗/抽屉设计规范
|
||||||
|
|
||||||
|
> 每个弹窗/抽屉独立一节,按以下结构输出。
|
||||||
|
|
||||||
|
### 3.N {弹窗/抽屉名称}({触发入口})
|
||||||
|
|
||||||
|
#### 3.N.1 触发方式
|
||||||
|
- **触发位置**:(如:房源详情页-调价链接)
|
||||||
|
- **组件类型**:Modal Dialog / Drawer(选一个,说明选择理由)
|
||||||
|
- **尺寸**:(Modal: max-w-sm/md/lg/xl/2xl;Drawer: w-[480px]/w-[640px])
|
||||||
|
- **竞品截图**:`{截图路径}`
|
||||||
|
|
||||||
|
#### 3.N.2 表单字段规范
|
||||||
|
|
||||||
|
| 字段名 | 组件类型 | 必填 | 校验规则 | 默认值/预填值 |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| (字段名) | (Input/Select/Textarea/DatePicker/Toggle/TreeSelect/MultiTag/...) | (是/否) | (规则描述) | (如有) |
|
||||||
|
|
||||||
|
#### 3.N.3 提交行为
|
||||||
|
- **提交方式**:HTMX `hx-post` / `hx-put` / `hx-patch`
|
||||||
|
- **成功响应**:(如:关闭弹窗 + Toast "保存成功" + 刷新目标区域)
|
||||||
|
- **失败响应(422)**:(字段级错误提示)
|
||||||
|
- **HTMX 属性**:(完整写出 hx-post/hx-target/hx-swap/hx-on 等)
|
||||||
|
|
||||||
|
#### 3.N.4 使用的特殊组件
|
||||||
|
|
||||||
|
| 组件名 | 来源 | 用途 |
|
||||||
|
|---|---|---|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 交互状态规范
|
||||||
|
|
||||||
|
### 4.1 全局状态机(如有)
|
||||||
|
(如房源状态机:在售 → 暂缓 → 成交 → 下架,用状态流转图描述)
|
||||||
|
|
||||||
|
### 4.2 权限控制矩阵
|
||||||
|
(描述不同角色对本模块各操作的权限,如:删除只有管理员可见)
|
||||||
|
|
||||||
|
| 操作 | 经纪人 | 店长 | 管理员 |
|
||||||
|
|---|---|---|---|
|
||||||
|
|
||||||
|
### 4.3 HTMX 请求规范
|
||||||
|
(列出本模块所有 HTMX 请求,包含:触发事件、URL、target、swap 方式、Loading 行为)
|
||||||
|
|
||||||
|
| 操作 | hx-trigger | hx-get/post/... | hx-target | hx-swap | Loading |
|
||||||
|
|---|---|---|---|---|---|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 关键数据字段说明
|
||||||
|
|
||||||
|
(列出本模块所有需要后端支持的数据字段,便于 Engineer 与后端联调)
|
||||||
|
|
||||||
|
| 字段名(英文) | 显示名 | 数据类型 | 说明 |
|
||||||
|
|---|---|---|---|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 竞品截图对应关系
|
||||||
|
|
||||||
|
(将本模块所有参考截图按功能分类整理,说明截图对应设计文档的哪个章节)
|
||||||
|
|
||||||
|
| 截图路径 | 对应功能 | 对应文档章节 | 采纳的设计要点 |
|
||||||
|
|---|---|---|---|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 实现优先级与工期估算
|
||||||
|
|
||||||
|
| 页面/功能 | 优先级 | 特殊组件复杂度 | 工期估算(前端) |
|
||||||
|
|---|---|---|---|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 开放问题(待决策)
|
||||||
|
|
||||||
|
(列出设计过程中发现的、需要产品/后端确认的问题)
|
||||||
|
|
||||||
|
| # | 问题 | 影响范围 | 待确认方 |
|
||||||
|
|---|---|---|---|
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 额外要求
|
||||||
|
|
||||||
|
1. **类似页面UI设计有限**: 如有已完成的类似页面设计,请作为主要参考,设计页面布局,内容布局等。
|
||||||
|
2. **PRD优先**:有截图的功能,以截图呈现的 UI 为补充说明,以PRD 文字为主要参考;截图和 PRD 有冲突时,以PRD为准,并在文档中注明差异。
|
||||||
|
3. **组件引用**:每次使用特殊组件(如 Data Table、Tree Select、Drawer 等),必须在"使用的特殊组件"表格中引用组件规范设计.md 的对应章节编号,并说明如有差异的自定义部分。
|
||||||
|
4. **HTMX 落地**:每个需要异步更新的交互(筛选、分页、弹窗提交)必须写出完整的 HTMX 属性,Engineer 可以直接复制使用。
|
||||||
|
5. **Alpine.js 分工**:说明哪些状态由 Alpine.js 管理(弹窗开关、选中状态、表单联动),哪些交互走 HTMX(数据加载、表单提交)。
|
||||||
|
6. **禁止设计移动端**:所有布局仅针对 ≥1280px 桌面端。
|
||||||
|
7. **优先级标注**:P0 功能用 🔴,P1 用 🟡,P2 用 ⚫,确保 Engineer 知道实现顺序。
|
||||||
|
8. **不要遗漏边界状态**:每个列表页必须包含空状态设计;每个表单必须包含校验失败状态;每个异步操作必须包含 Loading 状态。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# 任务:为房源列表生成模块 UI 静态原型
|
||||||
|
|
||||||
|
## 你的角色
|
||||||
|
|
||||||
|
你是 Fonrey 房产经纪管理系统的 **UI/UX 架构师**,负责根据竞品截图和 PRD 功能描述,产出一份标准化的模块级 UI 设计文档。该文档将直接交给 AI Engineer 用于编码实现,必须包含足够的细节,Engineer 无需再问任何问题。
|
||||||
|
|
||||||
|
**注意**
|
||||||
|
以下所有的文档或图片是基于文档库的相对路径。
|
||||||
|
文档库的根路径为:`/mnt/d/Workspace/nexus`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 全局设计约束(必须严格遵守)
|
||||||
|
|
||||||
|
> 所有设计决策必须符合 `Project/fonrey/UI_SYSTEM/UI_SYSTEM.md` 中的设计规范。核心约束如下:
|
||||||
|
|
||||||
|
- **技术栈**:Tailwind CSS + HTMX + Alpine.js + Django HTML 模板(非 React/Vue/JSX)
|
||||||
|
- **图标库**:Heroicons v2(Outline 24px 默认,Solid 20px 强调,Mini 16px 极密场景)
|
||||||
|
- **主色**:Teal `#0F766E`(`primary-600`),所有颜色引用 Token,禁止硬编码 Hex
|
||||||
|
- **圆角**:`rounded-lg`(8px)为默认,表格行/小组件用 `rounded-md`(6px)
|
||||||
|
- **表格行高**:56px(`h-14`)
|
||||||
|
- **字体**:Inter + PingFang SC,正文 `text-sm`(14px)
|
||||||
|
- **焦点环**:`focus-visible:ring-2 focus-visible:ring-primary-600/40`
|
||||||
|
- **桌面优先**:≥1280px,不做移动端适配
|
||||||
|
- **禁止独立 CSS 文件或 CSS-in-JS**:所有样式用 Tailwind utility class(少量例外如 Flatpickr 覆盖样式)
|
||||||
|
- **组件实现参考**:`Project/fonrey/UI_SYSTEM/组件规范设计.md`(含 20 个特殊组件的完整 HTML + Alpine.js 实现)
|
||||||
|
|
||||||
|
|
||||||
|
**输入文件**
|
||||||
|
1. 【UI_SYSTEM】全局UI设计规范文档 `Project/fonrey/UI_SYSTEM/UI_SYSTEM.md`
|
||||||
|
2. 【现有原型页面】已完成的HTML页面(作为视觉和代码参考基准)
|
||||||
|
- `Project/fonrey/UI_SYSTEM/preview.html`
|
||||||
|
- `Project/fonrey/UI_DESIGN/客源列表_UI.html`
|
||||||
|
3. 【本次模块UI设计文档】本次需要实现的模块设计说明
|
||||||
|
- `Project/fonrey/UI_DESIGN/房源列表_UI.md`
|
||||||
|
**输出文件**
|
||||||
|
- 【本次模块UI输出静态原型文件】
|
||||||
|
- `Project/fonrey/UI_DESIGN/房源列表_UI.html`
|
||||||
|
|
||||||
|
### 强制约束(不可违反)
|
||||||
|
|
||||||
|
#### 一致性约束
|
||||||
|
- 颜色、字体、字号、圆角、阴影、间距等视觉变量,必须与 UI_SYSTEM 保持完全一致,不得自行创造新的变量
|
||||||
|
- 公共组件(导航栏、侧边栏、顶部栏、按钮、表单、卡片、标签等)的样式和结构,必须与现有原型页面中的实现保持一致
|
||||||
|
- 如果现有页面使用了 CSS 变量或特定 class 命名规范,本次输出必须沿用相同的规范
|
||||||
|
|
||||||
|
#### 布局约束
|
||||||
|
- 整体页面框架(如侧边栏宽度、顶栏高度、内容区边距)必须与现有原型页面保持一致
|
||||||
|
- 响应式断点策略(如有)需与已有页面对齐
|
||||||
|
#### 代码约束
|
||||||
|
- 输出单一 HTML 文件,CSS 写在 `<style>` 标签内,JS 写在 `<script>` 标签内
|
||||||
|
- 不引入任何外部依赖,除非现有原型页面已经使用了该依赖
|
||||||
|
- 类名、变量名的命名风格与现有代码保持一致
|
||||||
|
|
||||||
|
#### 执行步骤(按顺序执行)
|
||||||
|
1. 通读所有输入材料,识别 UI_SYSTEM 中的核心设计 token
|
||||||
|
2. 分析现有原型页面,提取公共组件的 HTML 结构和 CSS 实现
|
||||||
|
3. 阅读本次模块设计文档,理解页面结构、交互状态和内容层级
|
||||||
|
4. 以现有页面为外壳,将本次模块内容填入正确的内容区域
|
||||||
|
5. 对照设计文档逐项检查还原度,确认无遗漏后输出
|
||||||
|
|
||||||
|
#### 输出要求
|
||||||
|
- 直接输出完整可运行的 HTML 文件内容
|
||||||
|
- 页面中需要数据的地方使用合理的占位内容(不要留空)
|
||||||
|
- 交互状态(hover、active、selected、disabled)需在 CSS 中体现
|
||||||
|
- 输出完成后,列出你在本次实现中做出的所有设计假设或补充决策
|
||||||
|
|
||||||
|
#### 注意事项
|
||||||
|
- 如果设计文档与 UI_SYSTEM 存在冲突,以 UI_SYSTEM 为准,并告知我冲突点
|
||||||
|
- 如果设计文档描述不清晰,不要自行猜测,先列出疑问再继续
|
||||||
@@ -40,6 +40,7 @@
|
|||||||
- 架构师方法论:`Project/fonrey/prompt/engineering-backend-architect.md`
|
- 架构师方法论:`Project/fonrey/prompt/engineering-backend-architect.md`
|
||||||
- 现有技术栈草案:`Project/fonrey/TECH_STACK/TECH_STACK.md`
|
- 现有技术栈草案:`Project/fonrey/TECH_STACK/TECH_STACK.md`
|
||||||
- 现有数据模型草案:`Project/fonrey/DATA_MODEL/DATA_MODEL.md`
|
- 现有数据模型草案:`Project/fonrey/DATA_MODEL/DATA_MODEL.md`
|
||||||
|
- 现有UI总体设计方案:`Project/fonrey/UI_SYSTEM/UI_SYSTEM.md`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
603
Project/fonrey/prompt/提示词模板/创建项目骨架提示词_v1.md
Normal file
603
Project/fonrey/prompt/提示词模板/创建项目骨架提示词_v1.md
Normal file
@@ -0,0 +1,603 @@
|
|||||||
|
# Fonrey 项目骨架搭建 — 工程执行提示词
|
||||||
|
## 你的角色与约束
|
||||||
|
你是一名资深 Django 后端工程师。你的任务是**严格按照规范**搭建 Fonrey 项目骨架,不得自行发明技术方案,不得引入文档未授权的第三方库。每一步操作后必须验证结果。
|
||||||
|
**项目工作目录**:`/mnt/c/Project/`(在此目录下创建 `fonrey/` 子目录)
|
||||||
|
**执行方式**:逐步创建,每创建一个文件/目录后立即验证,遇到冲突停下来询问而不是自行决策。
|
||||||
|
---
|
||||||
|
## 一、技术栈约束(必读,不得违反)
|
||||||
|
| 层级 | 技术 | 版本约束 |
|
||||||
|
|------|------|----------|
|
||||||
|
| Backend | Django | 4.2 LTS(ASGI 模式) |
|
||||||
|
| Multi-tenant | django-tenants | latest stable |
|
||||||
|
| Database | PostgreSQL | 16 |
|
||||||
|
| Cache | Redis | latest stable |
|
||||||
|
| Tasks | Celery + Celery Beat | latest stable |
|
||||||
|
| Storage | django-storages + boto3 | Cloudflare R2(S3 兼容) |
|
||||||
|
| Frontend | HTMX + Alpine.js + Tailwind CSS | HTMX 2.x, Alpine 3.x, Tailwind 3.x |
|
||||||
|
| Icons | Heroicons v2 | inline SVG via templatetag |
|
||||||
|
| Server | Gunicorn + Uvicorn workers | ASGI |
|
||||||
|
| Container | Docker + Docker Compose | — |
|
||||||
|
| Monitoring | Sentry SDK | — |
|
||||||
|
**绝对禁止**:React / Vue / Angular;任何 JS 框架;`nodeIntegration: true`;硬编码密钥/ID;跨租户 SQL 查询。
|
||||||
|
---
|
||||||
|
## 二、目录结构(严格按此创建,不得增减顶层结构)
|
||||||
|
```
|
||||||
|
fonrey/
|
||||||
|
├── apps/
|
||||||
|
│ ├── tenant/ # django-tenants 配置(in SHARED_APPS)
|
||||||
|
│ ├── account/ # 登录认证(in TENANT_APPS)
|
||||||
|
│ ├── permission/ # 权限管理(in TENANT_APPS)
|
||||||
|
│ ├── org/ # 组织人事(in TENANT_APPS)
|
||||||
|
│ ├── region/ # 区域管理(in TENANT_APPS)
|
||||||
|
│ ├── complex/ # 楼盘管理(in TENANT_APPS)
|
||||||
|
│ ├── property/ # 房源核心(in TENANT_APPS)
|
||||||
|
│ ├── client/ # 客源管理(in TENANT_APPS)
|
||||||
|
│ ├── setting/ # 系统设置(in TENANT_APPS)
|
||||||
|
│ └── release/ # 客户端发布管理(in SHARED_APPS)
|
||||||
|
├── core/
|
||||||
|
│ ├── __init__.py
|
||||||
|
│ ├── models/
|
||||||
|
│ │ ├── __init__.py
|
||||||
|
│ │ └── base.py # 抽象基类(见第四节规范)
|
||||||
|
│ ├── encryption.py # PII 加密(AES-256-GCM)
|
||||||
|
│ ├── cache.py # Redis 工具
|
||||||
|
│ ├── templatetags/
|
||||||
|
│ │ ├── __init__.py
|
||||||
|
│ │ └── heroicons.py # {% heroicon 'plus' %} templatetag
|
||||||
|
│ └── middleware/
|
||||||
|
│ ├── __init__.py
|
||||||
|
│ └── audit.py # 审计日志中间件骨架
|
||||||
|
├── shared/
|
||||||
|
│ ├── __init__.py
|
||||||
|
│ └── apps.py # 公共 Schema App 配置
|
||||||
|
├── config/
|
||||||
|
│ ├── __init__.py
|
||||||
|
│ ├── settings/
|
||||||
|
│ │ ├── __init__.py
|
||||||
|
│ │ ├── base.py # 基础配置
|
||||||
|
│ │ ├── development.py
|
||||||
|
│ │ └── production.py
|
||||||
|
│ ├── urls.py
|
||||||
|
│ ├── asgi.py # ASGI 入口
|
||||||
|
│ └── wsgi.py
|
||||||
|
├── templates/
|
||||||
|
│ ├── base.html # 全局基础模板
|
||||||
|
│ ├── layouts/
|
||||||
|
│ │ ├── auth.html # 认证页独立布局
|
||||||
|
│ │ └── app.html # 主应用布局(含 Topbar + Sidebar)
|
||||||
|
│ ├── components/ # 可复用组件片段
|
||||||
|
│ │ ├── topbar.html
|
||||||
|
│ │ ├── sidebar.html
|
||||||
|
│ │ ├── pagination.html
|
||||||
|
│ │ ├── toast.html
|
||||||
|
│ │ ├── modal.html
|
||||||
|
│ │ └── empty-state.html
|
||||||
|
│ └── errors/
|
||||||
|
│ ├── 403.html
|
||||||
|
│ ├── 404.html
|
||||||
|
│ └── 500.html
|
||||||
|
├── static/
|
||||||
|
│ ├── css/
|
||||||
|
│ │ └── main.css # Tailwind 入口(@tailwind directives)
|
||||||
|
│ ├── js/
|
||||||
|
│ │ └── main.js # Alpine.js 初始化 + 全局 HTMX 事件
|
||||||
|
│ └── vendor/ # 第三方 JS/CSS(htmx.min.js, alpine.min.js 等)
|
||||||
|
├── locale/ # 预留国际化(v2),当前仅中文
|
||||||
|
├── .env.example
|
||||||
|
├── .env # 不入 git
|
||||||
|
├── .gitignore
|
||||||
|
├── manage.py
|
||||||
|
├── requirements/
|
||||||
|
│ ├── base.txt
|
||||||
|
│ ├── development.txt
|
||||||
|
│ └── production.txt
|
||||||
|
├── docker-compose.yml
|
||||||
|
├── docker-compose.prod.yml
|
||||||
|
├── Dockerfile
|
||||||
|
├── Makefile # 常用命令快捷方式
|
||||||
|
├── tailwind.config.js
|
||||||
|
├── package.json # 仅用于 Tailwind 构建,不含业务 JS
|
||||||
|
└── pyproject.toml # ruff + black + isort 配置
|
||||||
|
```
|
||||||
|
每个 `apps/<name>/` 内部结构如下(以 `property` 为典型,其他 App 骨架相同):
|
||||||
|
```
|
||||||
|
apps/property/
|
||||||
|
├── __init__.py
|
||||||
|
├── apps.py
|
||||||
|
├── admin.py
|
||||||
|
├── models/
|
||||||
|
│ ├── __init__.py # 统一 re-export
|
||||||
|
│ └── .gitkeep # 骨架阶段留空,后续一表一文件
|
||||||
|
├── services/
|
||||||
|
│ ├── __init__.py
|
||||||
|
│ └── .gitkeep
|
||||||
|
├── tasks.py # Celery 任务骨架
|
||||||
|
├── views.py # HTMX/JSON 视图骨架
|
||||||
|
├── urls.py
|
||||||
|
├── templates/
|
||||||
|
│ └── property/ # App 级模板(可覆盖全局同名模板)
|
||||||
|
└── tests/
|
||||||
|
├── __init__.py
|
||||||
|
└── .gitkeep
|
||||||
|
```
|
||||||
|
---
|
||||||
|
## 三、Django 配置规范
|
||||||
|
### 3.1 INSTALLED_APPS 分区
|
||||||
|
```python
|
||||||
|
# config/settings/base.py
|
||||||
|
SHARED_APPS = [
|
||||||
|
"django_tenants", # 必须第一位
|
||||||
|
"apps.tenant", # Tenant / Domain 模型
|
||||||
|
"apps.release", # ClientRelease 模型
|
||||||
|
"shared", # 公共 Schema App
|
||||||
|
# Django 内置
|
||||||
|
"django.contrib.contenttypes",
|
||||||
|
"django.contrib.auth",
|
||||||
|
"django.contrib.sessions",
|
||||||
|
"django.contrib.messages",
|
||||||
|
"django.contrib.staticfiles",
|
||||||
|
# 第三方(shared)
|
||||||
|
"django_celery_beat",
|
||||||
|
"django_celery_results",
|
||||||
|
]
|
||||||
|
TENANT_APPS = [
|
||||||
|
"apps.account",
|
||||||
|
"apps.permission",
|
||||||
|
"apps.org",
|
||||||
|
"apps.region",
|
||||||
|
"apps.complex",
|
||||||
|
"apps.property",
|
||||||
|
"apps.client",
|
||||||
|
"apps.setting",
|
||||||
|
"core",
|
||||||
|
]
|
||||||
|
INSTALLED_APPS = list(SHARED_APPS) + list(TENANT_APPS)
|
||||||
|
```
|
||||||
|
### 3.2 核心配置项(base.py 必须包含以下所有项)
|
||||||
|
```python
|
||||||
|
# 多租户
|
||||||
|
TENANT_MODEL = "tenant.Tenant"
|
||||||
|
TENANT_DOMAIN_MODEL = "tenant.Domain"
|
||||||
|
DEFAULT_AUTO_FIELD = "django.db.models.UUIDField" # 全局 UUID PK
|
||||||
|
# 数据库(从环境变量读取)
|
||||||
|
DATABASES = {
|
||||||
|
"default": {
|
||||||
|
"ENGINE": "django_tenants.postgresql_backend",
|
||||||
|
"NAME": env("DB_NAME"),
|
||||||
|
"USER": env("DB_USER"),
|
||||||
|
"PASSWORD": env("DB_PASSWORD"),
|
||||||
|
"HOST": env("DB_HOST", default="localhost"),
|
||||||
|
"PORT": env("DB_PORT", default="5432"),
|
||||||
|
"CONN_MAX_AGE": 60,
|
||||||
|
"OPTIONS": {"pool_size": 10}, # PgBouncer 协同
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DATABASE_ROUTERS = ["django_tenants.routers.TenantSyncRouter"]
|
||||||
|
# Redis(Cache + Session + Celery Broker)
|
||||||
|
CACHES = {
|
||||||
|
"default": {
|
||||||
|
"BACKEND": "django_redis.cache.RedisCache",
|
||||||
|
"LOCATION": env("REDIS_URL", default="redis://127.0.0.1:6379/0"),
|
||||||
|
"OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient"},
|
||||||
|
"KEY_PREFIX": "fonrey",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
|
||||||
|
SESSION_CACHE_ALIAS = "default"
|
||||||
|
# Celery
|
||||||
|
CELERY_BROKER_URL = env("CELERY_BROKER_URL", default="redis://127.0.0.1:6379/1")
|
||||||
|
CELERY_RESULT_BACKEND = "django-db"
|
||||||
|
CELERY_TASK_ALWAYS_EAGER = False
|
||||||
|
CELERY_TASK_TIME_LIMIT = 300
|
||||||
|
CELERY_TASK_SOFT_TIME_LIMIT = 270
|
||||||
|
# 存储(Cloudflare R2)
|
||||||
|
DEFAULT_FILE_STORAGE = "storages.backends.s3boto3.S3Boto3Storage"
|
||||||
|
AWS_S3_ENDPOINT_URL = env("R2_ENDPOINT_URL")
|
||||||
|
AWS_ACCESS_KEY_ID = env("R2_ACCESS_KEY_ID")
|
||||||
|
AWS_SECRET_ACCESS_KEY = env("R2_SECRET_ACCESS_KEY")
|
||||||
|
AWS_STORAGE_BUCKET_NAME = env("R2_BUCKET_NAME", default="media")
|
||||||
|
AWS_S3_CUSTOM_DOMAIN = env("R2_CUSTOM_DOMAIN", default=None)
|
||||||
|
AWS_DEFAULT_ACL = "private"
|
||||||
|
# ASGI
|
||||||
|
ASGI_APPLICATION = "config.asgi.application"
|
||||||
|
# Sentry(production 环境激活)
|
||||||
|
# 见 production.py
|
||||||
|
# 安全
|
||||||
|
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
|
||||||
|
SESSION_COOKIE_HTTPONLY = True
|
||||||
|
SESSION_COOKIE_SAMESITE = "Lax"
|
||||||
|
CSRF_COOKIE_HTTPONLY = False # HTMX 需要读取
|
||||||
|
X_FRAME_OPTIONS = "DENY"
|
||||||
|
# 模板
|
||||||
|
TEMPLATES = [{
|
||||||
|
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
||||||
|
"DIRS": [BASE_DIR / "templates"],
|
||||||
|
"APP_DIRS": True,
|
||||||
|
"OPTIONS": {
|
||||||
|
"context_processors": [
|
||||||
|
"django.template.context_processors.debug",
|
||||||
|
"django.template.context_processors.request",
|
||||||
|
"django.contrib.auth.context_processors.auth",
|
||||||
|
"django.contrib.messages.context_processors.messages",
|
||||||
|
]
|
||||||
|
},
|
||||||
|
}]
|
||||||
|
# HTMX
|
||||||
|
HTMX_GLOBAL_CSRF = True # 全局 CSRF 注入
|
||||||
|
# 日志(骨架,production 扩展)
|
||||||
|
LOGGING = {
|
||||||
|
"version": 1,
|
||||||
|
"disable_existing_loggers": False,
|
||||||
|
"handlers": {"console": {"class": "logging.StreamHandler"}},
|
||||||
|
"root": {"handlers": ["console"], "level": "INFO"},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### 3.3 中间件顺序(严格按此,不得调整)
|
||||||
|
```python
|
||||||
|
MIDDLEWARE = [
|
||||||
|
"django_tenants.middleware.main.TenantMainMiddleware", # 必须第一位
|
||||||
|
"django.middleware.security.SecurityMiddleware",
|
||||||
|
"whitenoise.middleware.WhiteNoiseMiddleware", # 静态文件
|
||||||
|
"django.contrib.sessions.middleware.SessionMiddleware",
|
||||||
|
"django.middleware.common.CommonMiddleware",
|
||||||
|
"django.middleware.csrf.CsrfViewMiddleware",
|
||||||
|
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
||||||
|
"django.contrib.messages.middleware.MessageMiddleware",
|
||||||
|
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
||||||
|
"core.middleware.audit.AuditMiddleware", # 自定义审计(骨架)
|
||||||
|
]
|
||||||
|
```
|
||||||
|
---
|
||||||
|
## 四、核心抽象基类(core/models/base.py)
|
||||||
|
严格按以下规范实现,不得修改字段名、类型、顺序:
|
||||||
|
```python
|
||||||
|
import uuid
|
||||||
|
from django.db import models
|
||||||
|
from django.utils import timezone
|
||||||
|
class UUIDPrimaryKeyModel(models.Model):
|
||||||
|
"""所有业务模型的根基类:UUID v4 主键"""
|
||||||
|
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
||||||
|
class TimeStampedModel(UUIDPrimaryKeyModel):
|
||||||
|
"""追加创建/更新时间(TIMESTAMPTZ)"""
|
||||||
|
created_at = models.DateTimeField(auto_now_add=True, db_index=True)
|
||||||
|
updated_at = models.DateTimeField(auto_now=True)
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
||||||
|
ordering = ["-created_at"]
|
||||||
|
class SoftDeleteModel(TimeStampedModel):
|
||||||
|
"""软删除:deleted_at=NULL 表示未删除"""
|
||||||
|
deleted_at = models.DateTimeField(null=True, blank=True, db_index=True)
|
||||||
|
objects = ActiveManager() # 默认过滤已删除
|
||||||
|
all_objects = models.Manager() # 包含已删除记录
|
||||||
|
def delete(self, using=None, keep_parents=False):
|
||||||
|
self.deleted_at = timezone.now()
|
||||||
|
self.save(update_fields=["deleted_at"])
|
||||||
|
def hard_delete(self):
|
||||||
|
super().delete()
|
||||||
|
def restore(self):
|
||||||
|
self.deleted_at = None
|
||||||
|
self.save(update_fields=["deleted_at"])
|
||||||
|
@property
|
||||||
|
def is_deleted(self):
|
||||||
|
return self.deleted_at is not None
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
||||||
|
class AuditedModel(SoftDeleteModel):
|
||||||
|
"""审计字段:操作人(FK to Staff,允许 NULL 表示系统操作)"""
|
||||||
|
created_by = models.ForeignKey(
|
||||||
|
"org.Staff",
|
||||||
|
null=True, blank=True,
|
||||||
|
on_delete=models.SET_NULL,
|
||||||
|
related_name="%(app_label)s_%(class)s_created",
|
||||||
|
db_index=True,
|
||||||
|
)
|
||||||
|
updated_by = models.ForeignKey(
|
||||||
|
"org.Staff",
|
||||||
|
null=True, blank=True,
|
||||||
|
on_delete=models.SET_NULL,
|
||||||
|
related_name="%(app_label)s_%(class)s_updated",
|
||||||
|
)
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
||||||
|
class ActiveManager(models.Manager):
|
||||||
|
"""默认只返回未软删除的记录"""
|
||||||
|
def get_queryset(self):
|
||||||
|
return super().get_queryset().filter(deleted_at__isnull=True)
|
||||||
|
```
|
||||||
|
---
|
||||||
|
## 五、PII 加密(core/encryption.py)
|
||||||
|
骨架实现,接口固定(后续补充实现体),确保接口签名正确:
|
||||||
|
```python
|
||||||
|
from cryptography.fernet import Fernet
|
||||||
|
import hashlib
|
||||||
|
import base64
|
||||||
|
from django.conf import settings
|
||||||
|
class PhoneEncryption:
|
||||||
|
"""
|
||||||
|
手机号 AES-256-GCM 加密存储 + SHA-256 哈希索引
|
||||||
|
存储字段:phone_encrypted(加密密文)+ phone_hash(哈希,用于精确查询)
|
||||||
|
显示:脱敏格式 138****1234
|
||||||
|
"""
|
||||||
|
@staticmethod
|
||||||
|
def encrypt(phone: str) -> str:
|
||||||
|
"""加密手机号,返回 base64 密文"""
|
||||||
|
... # TODO: 实现
|
||||||
|
@staticmethod
|
||||||
|
def decrypt(ciphertext: str) -> str:
|
||||||
|
"""解密返回明文"""
|
||||||
|
... # TODO: 实现
|
||||||
|
@staticmethod
|
||||||
|
def hash(phone: str) -> str:
|
||||||
|
"""返回 SHA-256 哈希(用于 DB 索引查询)"""
|
||||||
|
... # TODO: 实现
|
||||||
|
@staticmethod
|
||||||
|
def mask(phone: str) -> str:
|
||||||
|
"""返回脱敏格式:138****1234"""
|
||||||
|
if not phone or len(phone) < 7:
|
||||||
|
return "***"
|
||||||
|
return phone[:3] + "****" + phone[-4:]
|
||||||
|
```
|
||||||
|
---
|
||||||
|
## 六、Heroicons Templatetag(core/templatetags/heroicons.py)
|
||||||
|
```python
|
||||||
|
from django import template
|
||||||
|
from django.utils.safestring import mark_safe
|
||||||
|
import os
|
||||||
|
register = template.Library()
|
||||||
|
ICONS_PATH = os.path.join(os.path.dirname(__file__), "..", "static", "icons")
|
||||||
|
@register.simple_tag
|
||||||
|
def heroicon(name: str, size: str = "24", style: str = "outline", css_class: str = "") -> str:
|
||||||
|
"""
|
||||||
|
用法: {% heroicon 'plus' %}
|
||||||
|
{% heroicon 'trash' size='20' style='solid' css_class='text-danger-600' %}
|
||||||
|
"""
|
||||||
|
# 骨架:实际从 heroicons vendor 文件读取 SVG
|
||||||
|
# size 可选: 12, 16, 20, 24
|
||||||
|
# style 可选: outline, solid, mini
|
||||||
|
css = f'class="w-{size//4 if isinstance(size, int) else size} h-{size//4 if isinstance(size, int) else size} {css_class}"'
|
||||||
|
return mark_safe(f'<!-- heroicon:{style}/{name} -->') # TODO: 替换为实际 SVG
|
||||||
|
```
|
||||||
|
---
|
||||||
|
## 七、模板体系
|
||||||
|
### 7.1 base.html(全局根模板)
|
||||||
|
包含以下 block 定义(骨架,后续填充):
|
||||||
|
- `{% block title %}` — 页面标题
|
||||||
|
- `{% block extra_head %}` — 额外 CSS/meta
|
||||||
|
- `{% block body_class %}` — body class 注入
|
||||||
|
- `{% block content %}` — 页面主内容
|
||||||
|
- `{% block extra_js %}` — 页面级 JS
|
||||||
|
引入资源顺序:
|
||||||
|
1. Tailwind CSS(编译后的 `main.css`)
|
||||||
|
2. Flatpickr CSS(条件加载)
|
||||||
|
3. HTMX `htmx.min.js`
|
||||||
|
4. Alpine.js `alpine.min.js`(defer,必须在 HTMX 之后)
|
||||||
|
5. 全局 `main.js`(初始化 Toast 监听、HTMX 事件、CSP nonce 等)
|
||||||
|
### 7.2 layouts/app.html(主应用布局)
|
||||||
|
继承 `base.html`,包含:
|
||||||
|
- Topbar(`bg-primary-800`,高 56px,sticky top-0 z-20)
|
||||||
|
- 左:Logo 150px 区
|
||||||
|
- 中:8 个主导航 Tab(主页/房源/客源/营销/交易/数据/人事/系统)+ 全局搜索
|
||||||
|
- 右:通知铃 + 设置齿轮 + 头像菜单
|
||||||
|
- Sidebar(固定,展开 240px / 收起 64px,Alpine `$persist` 记忆状态,z-20)
|
||||||
|
- 主内容区(`ml-60` 或 `ml-16`,`px-6 py-4`)
|
||||||
|
- Toast 容器(fixed bottom-right,z-70)
|
||||||
|
- 小屏拦截门(`window.innerWidth < 1280` 时显示全屏提示)
|
||||||
|
### 7.3 layouts/auth.html(认证页布局)
|
||||||
|
独立布局,无 Sidebar/Topbar,居中卡片 `max-w-md`。
|
||||||
|
### 7.4 HTMX Toast 约定
|
||||||
|
后端响应头触发 Toast(所有需要通知用户的操作必须返回此头):
|
||||||
|
```python
|
||||||
|
# 工具函数骨架(core/htmx.py)
|
||||||
|
from django.http import HttpResponse
|
||||||
|
def htmx_response(content="", status=200, toast=None, redirect=None):
|
||||||
|
"""
|
||||||
|
toast: {"type": "success|error|warning|info", "message": "..."}
|
||||||
|
"""
|
||||||
|
response = HttpResponse(content, status=status)
|
||||||
|
if toast:
|
||||||
|
import json
|
||||||
|
response["HX-Trigger"] = json.dumps({"fonrey:toast": toast})
|
||||||
|
if redirect:
|
||||||
|
response["HX-Redirect"] = redirect
|
||||||
|
return response
|
||||||
|
```
|
||||||
|
---
|
||||||
|
## 八、Docker Compose 规范
|
||||||
|
### docker-compose.yml(开发环境)
|
||||||
|
包含以下服务,网络统一使用 `fonrey_net`:
|
||||||
|
| 服务 | 镜像 | 端口 | 说明 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| `web` | 本地 Dockerfile | 8000:8000 | Django ASGI(Uvicorn) |
|
||||||
|
| `db` | postgres:16-alpine | 5432:5432 | PostgreSQL |
|
||||||
|
| `redis` | redis:7-alpine | 6379:6379 | Cache + Broker |
|
||||||
|
| `celery` | 同 web 镜像 | — | `celery -A config worker` |
|
||||||
|
| `celery-beat` | 同 web 镜像 | — | `celery -A config beat` |
|
||||||
|
| `tailwind` | node:20-alpine | — | `npm run watch`(开发热重载) |
|
||||||
|
所有服务通过环境变量从 `.env` 文件读取配置(`env_file: .env`)。
|
||||||
|
`db` 和 `redis` 必须配置 `volumes` 持久化数据。
|
||||||
|
### Dockerfile
|
||||||
|
```dockerfile
|
||||||
|
FROM python:3.12-slim
|
||||||
|
WORKDIR /app
|
||||||
|
# 系统依赖(PostgreSQL 客户端、构建工具)
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
libpq-dev gcc \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
COPY requirements/base.txt requirements/base.txt
|
||||||
|
RUN pip install --no-cache-dir -r requirements/base.txt
|
||||||
|
COPY . .
|
||||||
|
# 收集静态文件(production 阶段)
|
||||||
|
# RUN python manage.py collectstatic --noinput
|
||||||
|
EXPOSE 8000
|
||||||
|
CMD ["uvicorn", "config.asgi:application", "--host", "0.0.0.0", "--port", "8000"]
|
||||||
|
```
|
||||||
|
---
|
||||||
|
## 九、requirements 规范
|
||||||
|
### requirements/base.txt(精确版本锁定)
|
||||||
|
```
|
||||||
|
Django==4.2.16
|
||||||
|
django-tenants==3.7.0
|
||||||
|
psycopg2-binary==2.9.9
|
||||||
|
django-redis==5.4.0
|
||||||
|
celery==5.4.0
|
||||||
|
django-celery-beat==2.7.0
|
||||||
|
django-celery-results==2.5.1
|
||||||
|
django-storages[s3]==1.14.4
|
||||||
|
boto3==1.35.0
|
||||||
|
cryptography==43.0.0
|
||||||
|
whitenoise==6.8.2
|
||||||
|
gunicorn==23.0.0
|
||||||
|
uvicorn[standard]==0.32.0
|
||||||
|
sentry-sdk[django]==2.18.0
|
||||||
|
python-decouple==3.8 # .env 读取
|
||||||
|
Pillow==11.0.0 # 图片处理
|
||||||
|
```
|
||||||
|
### requirements/development.txt
|
||||||
|
```
|
||||||
|
-r base.txt
|
||||||
|
ruff==0.7.0
|
||||||
|
black==24.10.0
|
||||||
|
pytest-django==4.9.0
|
||||||
|
factory-boy==3.3.1
|
||||||
|
django-debug-toolbar==4.4.6
|
||||||
|
```
|
||||||
|
---
|
||||||
|
## 十、Makefile 快捷命令
|
||||||
|
```makefile
|
||||||
|
.PHONY: dev migrate shell createsuperuser test lint
|
||||||
|
dev:
|
||||||
|
docker compose up
|
||||||
|
migrate:
|
||||||
|
docker compose exec web python manage.py migrate_schemas --shared
|
||||||
|
docker compose exec web python manage.py migrate_schemas
|
||||||
|
shell:
|
||||||
|
docker compose exec web python manage.py shell_plus
|
||||||
|
test:
|
||||||
|
docker compose exec web pytest apps/ -v
|
||||||
|
lint:
|
||||||
|
ruff check . && black --check .
|
||||||
|
tailwind-build:
|
||||||
|
npm run build
|
||||||
|
createsuperuser:
|
||||||
|
docker compose exec web python manage.py create_tenant_superuser
|
||||||
|
```
|
||||||
|
---
|
||||||
|
## 十一、.env.example 模板
|
||||||
|
```bash
|
||||||
|
# Django
|
||||||
|
SECRET_KEY=your-secret-key-here
|
||||||
|
DEBUG=True
|
||||||
|
DJANGO_SETTINGS_MODULE=config.settings.development
|
||||||
|
ALLOWED_HOSTS=localhost,127.0.0.1
|
||||||
|
# Database
|
||||||
|
DB_NAME=fonrey
|
||||||
|
DB_USER=fonrey
|
||||||
|
DB_PASSWORD=fonrey
|
||||||
|
DB_HOST=db
|
||||||
|
DB_PORT=5432
|
||||||
|
# Redis
|
||||||
|
REDIS_URL=redis://redis:6379/0
|
||||||
|
CELERY_BROKER_URL=redis://redis:6379/1
|
||||||
|
# Cloudflare R2
|
||||||
|
R2_ENDPOINT_URL=https://<account_id>.r2.cloudflarestorage.com
|
||||||
|
R2_ACCESS_KEY_ID=
|
||||||
|
R2_SECRET_ACCESS_KEY=
|
||||||
|
R2_BUCKET_NAME=media
|
||||||
|
R2_CUSTOM_DOMAIN=
|
||||||
|
# Sentry(production 填写)
|
||||||
|
SENTRY_DSN=
|
||||||
|
# PII 加密密钥(AES-256,生产环境必须替换)
|
||||||
|
PHONE_ENCRYPTION_KEY=
|
||||||
|
```
|
||||||
|
---
|
||||||
|
## 十二、tailwind.config.js(完整规范)
|
||||||
|
严格按照 UI_SYSTEM.md §2.7 和 §10.1 的规范实现,包含:
|
||||||
|
1. **Primary 色(Teal)**:`primary-50` (#F0FDFA) 到 `primary-800` (#134E4A),`primary-600` (#0F766E) 为主色
|
||||||
|
2. **Neutral 色(Slate)**:`neutral-50` (#F8FAFC) 到 `neutral-900` (#0F172A)
|
||||||
|
3. **语义色**:`success-600` (#16A34A), `warning-600` (#D97706), `danger-600` (#DC2626), `info-600` (#2563EB)
|
||||||
|
4. **字体栈**:Inter, PingFang SC, Microsoft YaHei, sans-serif
|
||||||
|
5. **自定义 z-index**:z-60, z-70(Toast 层)
|
||||||
|
6. **自定义 boxShadow**:xs
|
||||||
|
7. **动画**:`slide-in-right`(Drawer 进场)
|
||||||
|
8. **content 扫描路径**:`./templates/**/*.html`, `./apps/**/templates/**/*.html`, `./static/js/**/*.js`
|
||||||
|
---
|
||||||
|
## 十三、package.json(仅 Tailwind 构建)
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "fonrey-frontend",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"build": "tailwindcss -i ./static/css/main.css -o ./static/css/output.css --minify",
|
||||||
|
"watch": "tailwindcss -i ./static/css/main.css -o ./static/css/output.css --watch"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"tailwindcss": "^3.4.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
---
|
||||||
|
## 十四、pyproject.toml(代码质量工具)
|
||||||
|
```toml
|
||||||
|
[tool.ruff]
|
||||||
|
line-length = 100
|
||||||
|
select = ["E", "F", "I", "N", "W", "UP"]
|
||||||
|
ignore = ["E501"]
|
||||||
|
target-version = "py312"
|
||||||
|
[tool.black]
|
||||||
|
line-length = 100
|
||||||
|
target-version = ["py312"]
|
||||||
|
[tool.isort]
|
||||||
|
profile = "black"
|
||||||
|
line_length = 100
|
||||||
|
[tool.pytest.ini_options]
|
||||||
|
DJANGO_SETTINGS_MODULE = "config.settings.development"
|
||||||
|
python_files = ["test_*.py", "*_test.py"]
|
||||||
|
addopts = "--reuse-db"
|
||||||
|
```
|
||||||
|
---
|
||||||
|
## 十五、执行顺序与验证清单
|
||||||
|
按以下顺序执行,每步完成后打 ✅:
|
||||||
|
```
|
||||||
|
[ ] 1. 创建根目录 fonrey/ 及上述完整目录树(含所有 __init__.py)
|
||||||
|
[ ] 2. 创建 pyproject.toml / .gitignore / .env.example / Makefile
|
||||||
|
[ ] 3. 创建 requirements/ 三个文件
|
||||||
|
[ ] 4. 创建 config/settings/base.py(完整配置)
|
||||||
|
[ ] 5. 创建 config/settings/development.py 和 production.py
|
||||||
|
[ ] 6. 创建 config/urls.py(骨架路由,含 django-tenants URL routing)
|
||||||
|
[ ] 7. 创建 config/asgi.py(ASGI 入口)
|
||||||
|
[ ] 8. 创建 core/models/base.py(四个抽象基类)
|
||||||
|
[ ] 9. 创建 core/encryption.py(PhoneEncryption 骨架)
|
||||||
|
[ ] 10. 创建 core/cache.py(Redis 工具骨架)
|
||||||
|
[ ] 11. 创建 core/htmx.py(htmx_response 工具)
|
||||||
|
[ ] 12. 创建 core/templatetags/heroicons.py
|
||||||
|
[ ] 13. 创建 core/middleware/audit.py(骨架)
|
||||||
|
[ ] 14. 为每个 App 创建目录结构(含 apps.py、models/__init__.py、services/__init__.py、tasks.py 骨架、views.py 骨架、urls.py 骨架)
|
||||||
|
[ ] 15. 创建 apps/tenant/models.py(Tenant、Domain 模型,django-tenants 规范)
|
||||||
|
[ ] 16. 创建 templates/ 完整目录树及 base.html、layouts/app.html、layouts/auth.html 骨架
|
||||||
|
[ ] 17. 创建 components/ 模板骨架(topbar, sidebar, pagination, toast, modal, empty-state)
|
||||||
|
[ ] 18. 创建 templates/errors/ 三个错误页骨架
|
||||||
|
[ ] 19. 创建 static/css/main.css(Tailwind 入口)
|
||||||
|
[ ] 20. 创建 static/js/main.js(Alpine 初始化 + HTMX 全局事件)
|
||||||
|
[ ] 21. 创建 tailwind.config.js(完整色彩/字体规范)
|
||||||
|
[ ] 22. 创建 package.json
|
||||||
|
[ ] 23. 创建 Dockerfile
|
||||||
|
[ ] 24. 创建 docker-compose.yml(5 个服务)
|
||||||
|
[ ] 25. 创建 manage.py
|
||||||
|
[ ] 26. 验证:python manage.py check --deploy 无致命错误
|
||||||
|
[ ] 27. 验证:项目目录树与第二节规范 100% 匹配
|
||||||
|
```
|
||||||
|
---
|
||||||
|
## 十六、关键注意事项
|
||||||
|
1. **django-tenants `apps/tenant/models.py`** 必须定义 `Tenant`(继承 `TenantMixin`)和 `Domain`(继承 `DomainMixin`),且 `Tenant` 的 `auto_create_schema = True`。
|
||||||
|
2. **`shared/` App** 的 `apps.py` 中 `name = "shared"`,用于公共 Schema 的跨租户共享数据(如 PermissionDef 等)。
|
||||||
|
3. **所有 App 的 `apps.py`** 必须包含正确的 `name`(含包路径,如 `apps.property`)和 `verbose_name`(中文)。
|
||||||
|
4. **`config/urls.py`** 使用 `django-tenants` 的 URL 路由模式,区分 public schema 路由和 tenant schema 路由。
|
||||||
|
5. **`apps/release/`** 放在 `SHARED_APPS`(所有租户共享一张版本表),其余业务 App 放 `TENANT_APPS`。
|
||||||
|
6. **`.gitignore`** 必须包含:`.env`、`*.pyc`、`__pycache__/`、`.DS_Store`、`node_modules/`、`static/css/output.css`、`media/`、`dist/`。
|
||||||
|
7. **模板中所有异步 HTMX 请求**在骨架阶段只需占位,但必须包含正确的 `hx-` 属性结构,不可省略 `hx-target` 和 `hx-swap`。
|
||||||
|
8. **Toast 系统**:前端监听 `htmx:afterRequest` 事件,检查响应头 `HX-Trigger` 中的 `fonrey:toast`,动态插入 Toast DOM,4 秒自动消失。
|
||||||
|
9. **小屏拦截**:`layouts/app.html` 中内嵌 JS,`window.innerWidth < 1280` 时显示全屏遮罩,文案:"Fonrey 当前仅支持桌面端(≥1280px),请在电脑上访问"。
|
||||||
|
10. **所有密码、密钥、Tenant ID** 禁止出现在任何 Python 文件中,统一从 `python-decouple` 的 `env()` 读取。
|
||||||
@@ -260,13 +260,14 @@
|
|||||||
|
|
||||||
## 额外要求
|
## 额外要求
|
||||||
|
|
||||||
1. **PRD优先**:有截图的功能,以截图呈现的 UI 为补充说明,以PRD 文字为主要参考;截图和 PRD 有冲突时,以PRD为准,并在文档中注明差异。
|
1. **类似页面UI设计有限**: 如有已完成的类似页面设计,请作为主要参考,设计页面布局,内容布局等。
|
||||||
2. **组件引用**:每次使用特殊组件(如 Data Table、Tree Select、Drawer 等),必须在"使用的特殊组件"表格中引用组件规范设计.md 的对应章节编号,并说明如有差异的自定义部分。
|
2. **PRD优先**:有截图的功能,以截图呈现的 UI 为补充说明,以PRD 文字为主要参考;截图和 PRD 有冲突时,以PRD为准,并在文档中注明差异。
|
||||||
3. **HTMX 落地**:每个需要异步更新的交互(筛选、分页、弹窗提交)必须写出完整的 HTMX 属性,Engineer 可以直接复制使用。
|
3. **组件引用**:每次使用特殊组件(如 Data Table、Tree Select、Drawer 等),必须在"使用的特殊组件"表格中引用组件规范设计.md 的对应章节编号,并说明如有差异的自定义部分。
|
||||||
4. **Alpine.js 分工**:说明哪些状态由 Alpine.js 管理(弹窗开关、选中状态、表单联动),哪些交互走 HTMX(数据加载、表单提交)。
|
4. **HTMX 落地**:每个需要异步更新的交互(筛选、分页、弹窗提交)必须写出完整的 HTMX 属性,Engineer 可以直接复制使用。
|
||||||
5. **禁止设计移动端**:所有布局仅针对 ≥1280px 桌面端。
|
5. **Alpine.js 分工**:说明哪些状态由 Alpine.js 管理(弹窗开关、选中状态、表单联动),哪些交互走 HTMX(数据加载、表单提交)。
|
||||||
6. **优先级标注**:P0 功能用 🔴,P1 用 🟡,P2 用 ⚫,确保 Engineer 知道实现顺序。
|
6. **禁止设计移动端**:所有布局仅针对 ≥1280px 桌面端。
|
||||||
7. **不要遗漏边界状态**:每个列表页必须包含空状态设计;每个表单必须包含校验失败状态;每个异步操作必须包含 Loading 状态。
|
7. **优先级标注**:P0 功能用 🔴,P1 用 🟡,P2 用 ⚫,确保 Engineer 知道实现顺序。
|
||||||
|
8. **不要遗漏边界状态**:每个列表页必须包含空状态设计;每个表单必须包含校验失败状态;每个异步操作必须包含 Loading 状态。
|
||||||
|
|
||||||
---PROMPT END---
|
---PROMPT END---
|
||||||
|
|
||||||
|
|||||||
108
Project/fonrey/prompt/提示词模板/模块实现TASK项目任务生成提示词_v1.md
Normal file
108
Project/fonrey/prompt/提示词模板/模块实现TASK项目任务生成提示词_v1.md
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
|
||||||
|
你是一个 B2B SaaS 项目的产品/技术项目经理。你的任务是根据下方的 PRD.md及PRD_MPV.md 内容,生成一份完整的 TASK.md 项目任务看板文件。
|
||||||
|
|
||||||
|
## 任务说明:
|
||||||
|
根据{{模块名称}}的PRD文档,生成具体能落地的项目实现TASK列表
|
||||||
|
|
||||||
|
## 输入材料
|
||||||
|
|
||||||
|
- 模块PRD文档:
|
||||||
|
- 模块DATA_MODEL文档:
|
||||||
|
- TECH_STACK文档:
|
||||||
|
- UI_SYSTEM文档:
|
||||||
|
|
||||||
|
## 输出要求
|
||||||
|
|
||||||
|
### 文件结构规则
|
||||||
|
按以下 Phase 划分,严格对应 PRD 优先级:
|
||||||
|
- **Phase 1 - MVP(P0,上线前必须完成)** → PRD 中标注 P0 的功能
|
||||||
|
- **Phase 2 - 增强功能(P1,MVP 后第一迭代)** → PRD 中标注 P1 的功能
|
||||||
|
- **Phase 3 - 路线图功能(P2,已规划未排期)** → PRD 中标注 P2 的功能
|
||||||
|
- **Phase 4 - 明确不做(Out of Scope)** → PRD 第 3 节"非目标"中的功能,仅列出条目作为备忘,不写 task 详情
|
||||||
|
|
||||||
|
### 模块顺序(按 PRD 顺序)
|
||||||
|
1. 用户登录
|
||||||
|
2. 楼盘管理
|
||||||
|
3. 房源管理
|
||||||
|
4. 客源管理
|
||||||
|
5. 组织人事
|
||||||
|
6. 权限管理
|
||||||
|
7. 系统配置
|
||||||
|
8. 系统管理(运营后台)
|
||||||
|
9. 客户端发布
|
||||||
|
|
||||||
|
**请在项目目录里寻找匹配的文档填入下面具体的任务列表**
|
||||||
|
### 每条 Task 格式(严格遵守)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### [模块中文名]
|
||||||
|
|
||||||
|
- [ ] US-XXX [动词开头的功能描述,主语为"经纪人/店长/管理员/系统"]
|
||||||
|
- 参考PRD文档:`Project/fonrey/PRD/[模块名]/[模块名]模块PRD.md` - [对应 Story 或功能点名称]
|
||||||
|
- 参考DATA_MODEL文档:`Project/fonrey/DATA_MODEL/DATA_MODEL_[模块英文名].md`
|
||||||
|
- 参考UI_Design文档:`Project/fonrey/UI_DESIGN/[模块名]/[功能名]_UI.md`
|
||||||
|
- 参考UI静态原型页面:`Project/fonrey/UI_DESIGN/[模块名]/[功能名]_UI.html`
|
||||||
|
- 验收标准:[从 PRD 功能描述提炼 2-4 条可测试的验收标准,用分号分隔]
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### US 编号规则
|
||||||
|
- US 编号全局唯一,按模块分段:
|
||||||
|
- 用户登录:US-ACCOUNT-001 ~ US-ACCOUNT-100
|
||||||
|
- 楼盘管理:US-COMPLEX-001 ~ US-COMPLEX-100
|
||||||
|
- 房源管理:US-PROPERTY-001 ~ US-PROPERTY-100
|
||||||
|
- 客源管理:US-CLIENT-001 ~ US-CLIENT-100
|
||||||
|
- 组织人事:US-ORG-001 ~ US-ORG-100
|
||||||
|
- 权限管理:US-PERMISSION-001 ~ US-PERMISSION-100
|
||||||
|
- 系统配置:US-SETTING-001 ~ US-SETTING-100
|
||||||
|
- 系统管理:US-SYSTEM-001 ~ US-SYSTEM-100
|
||||||
|
- 客户端发布:US-RELEASE-001 ~ US-RELEASE-100
|
||||||
|
|
||||||
|
### 文件头部格式
|
||||||
|
```
|
||||||
|
|
||||||
|
## Project Task Board
|
||||||
|
|
||||||
|
### 项目状态总览
|
||||||
|
|
||||||
|
- 产品名称:Fonrey 房睿
|
||||||
|
- 当前阶段:MVP Phase 1
|
||||||
|
- 技术栈:[待填写]
|
||||||
|
- 最后更新:2026-04-24
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### 文件尾部格式
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 已完成
|
||||||
|
|
||||||
|
(暂无)
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## 生成规则与约束
|
||||||
|
|
||||||
|
1. **PRD 里每一行功能条目都必须生成至少一条 Task**,不得遗漏
|
||||||
|
2. **Phase 4(Out of Scope)** 只用注释格式列出,不写 US 编号和子项:
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- OUT OF SCOPE: 移动端适配 - v2 规划 -->
|
||||||
|
|
||||||
|
```
|
||||||
|
3. **验收标准**必须是可测试的具体行为,禁止写"功能正常"等模糊描述
|
||||||
|
4. 文档路径中的模块英文名对照:
|
||||||
|
- 房源管理 → PROPERTY
|
||||||
|
- 客源管理 → CLIENT
|
||||||
|
- 楼盘管理 → COMPLEX
|
||||||
|
- 组织人事 → ORG
|
||||||
|
- 权限管理 → PERMISSION
|
||||||
|
- 用户登录 → ACCOUNT
|
||||||
|
- 系统配置 → SETTING
|
||||||
|
- 系统管理 → SYSTEM
|
||||||
|
3. 一个 PRD 功能条目如果包含多个子操作(如"新增/编辑/查看"),可以拆成多条 Task,也可以合并为一条,根据复杂度判断
|
||||||
|
4. 输出纯 Markdown 格式,不加任何解释说明,直接输出文件内容
|
||||||
@@ -1,131 +1,131 @@
|
|||||||
# OpenClaw Skills 状态表
|
# OpenClaw Skills 状态表
|
||||||
|
|
||||||
> 更新时间:2026-04-18
|
> 更新时间:2026-04-18
|
||||||
|
|
||||||
| 状态 | 图标 | 说明 |
|
| 状态 | 图标 | 说明 |
|
||||||
|------|------|------|
|
|------|------|------|
|
||||||
| ✅ ready | ✓ | 已安装并可用 |
|
| ✅ ready | ✓ | 已安装并可用 |
|
||||||
| △ needs setup | △ | 需要配置才能使用 |
|
| △ needs setup | △ | 需要配置才能使用 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Skills 列表
|
## Skills 列表
|
||||||
|
|
||||||
### ✅ Ready (62 个)
|
### ✅ Ready (62 个)
|
||||||
|
|
||||||
| 图标 | 技能 | 描述 | 来源 |
|
| 图标 | 技能 | 描述 | 来源 |
|
||||||
|------|------|------|------|
|
|------|------|------|------|
|
||||||
| 📦 | `1password` | **中文:** 设置和使用 1Password CLI (op)。用于安装 CLI、启用桌面应用集成、签名(单账户或多账户)或通过 op 读取/注入/运行密钥<br><br>**English:** *Set up and use 1Password CLI (op). Use when installing the CLI, enabling desktop app integration, signing in (single or multi- account), or reading/ injecting/ running secrets via op.* | agents-skills-personal |
|
| 📦 | `1password` | **中文:** 设置和使用 1Password CLI (op)。用于安装 CLI、启用桌面应用集成、签名(单账户或多账户)或通过 op 读取/注入/运行密钥<br><br>**English:** *Set up and use 1Password CLI (op). Use when installing the CLI, enabling desktop app integration, signing in (single or multi- account), or reading/ injecting/ running secrets via op.* | agents-skills-personal |
|
||||||
| 📦 | `apple-notes` | **中文:** 通过 macOS 上的 `memo` CLI 管理 Apple Notes(创建、查看、编辑、删除、搜索、移动和导出笔记)<br><br>**English:** *Manage Apple Notes via the `memo` CLI on macOS (create, view, edit, delete, search, move, and export notes). Use when a user asks Clawdbot to add a note, list notes, search notes, or manage note folders.* | openclaw-managed |
|
| 📦 | `apple-notes` | **中文:** 通过 macOS 上的 `memo` CLI 管理 Apple Notes(创建、查看、编辑、删除、搜索、移动和导出笔记)<br><br>**English:** *Manage Apple Notes via the `memo` CLI on macOS (create, view, edit, delete, search, move, and export notes). Use when a user asks Clawdbot to add a note, list notes, search notes, or manage note folders.* | openclaw-managed |
|
||||||
| 📦 | `apple-reminders` | **中文:** 通过 macOS 上的 `remindctl` CLI 管理 Apple 提醒(列出、添加、编辑、完成、删除)<br><br>**English:** *Manage Apple Reminders via the `remindctl` CLI on macOS (list, add, edit, complete, delete). Supports lists, date filters, and JSON/plain output.* | openclaw-managed |
|
| 📦 | `apple-reminders` | **中文:** 通过 macOS 上的 `remindctl` CLI 管理 Apple 提醒(列出、添加、编辑、完成、删除)<br><br>**English:** *Manage Apple Reminders via the `remindctl` CLI on macOS (list, add, edit, complete, delete). Supports lists, date filters, and JSON/plain output.* | openclaw-managed |
|
||||||
| 📦 | `clawhub` | **中文:** 使用 ClawHub CLI 从 clawhub.com 搜索、安装、更新和发布代理技能<br><br>**English:** *Use the ClawHub CLI to search, install, update, and publish agent skills from clawhub.com. Use when you need to fetch new skills on the fly, sync installed skills to latest or a specific version, or publish new/ updated skill folders with the npm- installed clawhub CLI.* | openclaw-bundled |
|
| 📦 | `clawhub` | **中文:** 使用 ClawHub CLI 从 clawhub.com 搜索、安装、更新和发布代理技能<br><br>**English:** *Use the ClawHub CLI to search, install, update, and publish agent skills from clawhub.com. Use when you need to fetch new skills on the fly, sync installed skills to latest or a specific version, or publish new/ updated skill folders with the npm- installed clawhub CLI.* | openclaw-bundled |
|
||||||
| 📦 | `coding-agent` | **中文:** 通过后台进程将编码任务委托给 Codex、Claude Code 或 Pi 代理<br><br>**English:** *Delegate coding tasks to Codex, Claude Code, or Pi agents via background process. Use when: (1) building/ creating new features or apps, (2) reviewing PRs (spawn in temp dir), (3) refactoring large codebases, (4) iterative coding that needs file exploration. NOT for: simple one- liner fixes (just edit), reading code (use read tool), thread- bound ACP harness requests in chat (for example spawn/ run Codex or Claude Code in a Discord thread; use sessions_ spawn with runtime:"acp") , or any work in ~/clawd workspace (never spawn agents here). Claude Code: use --print -- permission- mode bypassPermissi ons (no PTY). Codex/Pi/ OpenCode: pty:true required.* | openclaw-bundled |
|
| 📦 | `coding-agent` | **中文:** 通过后台进程将编码任务委托给 Codex、Claude Code 或 Pi 代理<br><br>**English:** *Delegate coding tasks to Codex, Claude Code, or Pi agents via background process. Use when: (1) building/ creating new features or apps, (2) reviewing PRs (spawn in temp dir), (3) refactoring large codebases, (4) iterative coding that needs file exploration. NOT for: simple one- liner fixes (just edit), reading code (use read tool), thread- bound ACP harness requests in chat (for example spawn/ run Codex or Claude Code in a Discord thread; use sessions_ spawn with runtime:"acp") , or any work in ~/clawd workspace (never spawn agents here). Claude Code: use --print -- permission- mode bypassPermissi ons (no PTY). Codex/Pi/ OpenCode: pty:true required.* | openclaw-bundled |
|
||||||
| 📦 | `gog` | **中文:** Google Workspace CLI for Gmail, Calendar, Drive, Contacts, Sheets, and Docs.<br><br>**English:** *Google Workspace CLI for Gmail, Calendar, Drive, Contacts, Sheets, and Docs.* | agents-skills-personal |
|
| 📦 | `gog` | **中文:** Google Workspace CLI for Gmail, Calendar, Drive, Contacts, Sheets, and Docs.<br><br>**English:** *Google Workspace CLI for Gmail, Calendar, Drive, Contacts, Sheets, and Docs.* | agents-skills-personal |
|
||||||
| 📦 | `healthcheck` | **中文:** OpenClaw 部署的主机安全加固和风险容忍配置<br><br>**English:** *Host security hardening and risk- tolerance configuration for OpenClaw deployments. Use when a user asks for security audits, firewall/SSH/ update hardening, risk posture, exposure review, OpenClaw cron scheduling for periodic checks, or version status checks on a machine running OpenClaw (laptop, workstation, Pi, VPS).* | openclaw-bundled |
|
| 📦 | `healthcheck` | **中文:** OpenClaw 部署的主机安全加固和风险容忍配置<br><br>**English:** *Host security hardening and risk- tolerance configuration for OpenClaw deployments. Use when a user asks for security audits, firewall/SSH/ update hardening, risk posture, exposure review, OpenClaw cron scheduling for periodic checks, or version status checks on a machine running OpenClaw (laptop, workstation, Pi, VPS).* | openclaw-bundled |
|
||||||
| 📦 | `node-connect` | **中文:** 诊断 Android、iOS 和 macOS 伴侣应用的 OpenClaw 节点连接和配对失败<br><br>**English:** *Diagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps. Use when QR/setup code/manual connect fails, local Wi-Fi works but VPS/ tailnet does not, or errors mention pairing required, unauthorized, bootstrap token invalid or expired, gateway.bind, gateway. remote.url, Tailscale, or plugins. entries. device-pair. config. publicUrl.* | openclaw-bundled |
|
| 📦 | `node-connect` | **中文:** 诊断 Android、iOS 和 macOS 伴侣应用的 OpenClaw 节点连接和配对失败<br><br>**English:** *Diagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps. Use when QR/setup code/manual connect fails, local Wi-Fi works but VPS/ tailnet does not, or errors mention pairing required, unauthorized, bootstrap token invalid or expired, gateway.bind, gateway. remote.url, Tailscale, or plugins. entries. device-pair. config. publicUrl.* | openclaw-bundled |
|
||||||
| 📦 | `openai-whisper` | **中文:** 本地语音转文字,使用 Whisper CLI(无需 API key)<br><br>**English:** *Local speech- to-text with the Whisper CLI (no API key).* | openclaw-bundled |
|
| 📦 | `openai-whisper` | **中文:** 本地语音转文字,使用 Whisper CLI(无需 API key)<br><br>**English:** *Local speech- to-text with the Whisper CLI (no API key).* | openclaw-bundled |
|
||||||
| 📦 | `sag` | **中文:** ElevenLabs 文字转语音,mac 风格 say UX<br><br>**English:** *ElevenLabs text-to- speech with mac-style say UX.* | openclaw-bundled |
|
| 📦 | `sag` | **中文:** ElevenLabs 文字转语音,mac 风格 say UX<br><br>**English:** *ElevenLabs text-to- speech with mac-style say UX.* | openclaw-bundled |
|
||||||
| 📦 | `session-logs` | **中文:** 使用 jq 搜索和分析你自己的会话日志(旧对话/父对话)<br><br>**English:** *Search and analyze your own session logs (older/ parent conversations) using jq. △ needs setup 🔉 sherpa-onnx-tts Local text-to- speech via sherpa-onnx (offline, no cloud)* | agents-skills-personal |
|
| 📦 | `session-logs` | **中文:** 使用 jq 搜索和分析你自己的会话日志(旧对话/父对话)<br><br>**English:** *Search and analyze your own session logs (older/ parent conversations) using jq. △ needs setup 🔉 sherpa-onnx-tts Local text-to- speech via sherpa-onnx (offline, no cloud)* | agents-skills-personal |
|
||||||
| 📦 | `skill-creator` | **中文:** 创建有效技能的指南。当用户想创建新技能(或更新现有技能)时使用<br><br>**English:** *Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.* | agents-skills-personal |
|
| 📦 | `skill-creator` | **中文:** 创建有效技能的指南。当用户想创建新技能(或更新现有技能)时使用<br><br>**English:** *Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.* | agents-skills-personal |
|
||||||
| 📦 | `slack` | **中文:** 通过 slack 工具控制 Slack,包括在 Slack 频道或 DM 中对消息添加反应或固定/取消固定内容<br><br>**English:** *Use when you need to control Slack from OpenClaw via the slack tool, including reacting to messages or pinning/ unpinning items in Slack channels or DMs.* | openclaw-bundled |
|
| 📦 | `slack` | **中文:** 通过 slack 工具控制 Slack,包括在 Slack 频道或 DM 中对消息添加反应或固定/取消固定内容<br><br>**English:** *Use when you need to control Slack from OpenClaw via the slack tool, including reacting to messages or pinning/ unpinning items in Slack channels or DMs.* | openclaw-bundled |
|
||||||
| 📦 | `summarize` | **中文:** 使用 summarize CLI 总结 URL 或文件(网页、PDF、图片、音频、YouTube)<br><br>**English:** *Summarize URLs or files with the summarize CLI (web, PDFs, images, audio, YouTube).* | openclaw-managed |
|
| 📦 | `summarize` | **中文:** 使用 summarize CLI 总结 URL 或文件(网页、PDF、图片、音频、YouTube)<br><br>**English:** *Summarize URLs or files with the summarize CLI (web, PDFs, images, audio, YouTube).* | openclaw-managed |
|
||||||
| 📦 | `tmux` | **中文:** 通过发送按键和抓取面板输出远程控制 tmux 会话以进行交互式 CLI 操作<br><br>**English:** *Remote- control tmux sessions for interactive CLIs by sending keystrokes and scraping pane output.* | agents-skills-personal |
|
| 📦 | `tmux` | **中文:** 通过发送按键和抓取面板输出远程控制 tmux 会话以进行交互式 CLI 操作<br><br>**English:** *Remote- control tmux sessions for interactive CLIs by sending keystrokes and scraping pane output.* | agents-skills-personal |
|
||||||
| 📦 | `video-frames` | **中文:** 使用 ffmpeg 从视频中提取帧或短片段<br><br>**English:** *Extract frames or short clips from videos using ffmpeg.* | agents-skills-personal |
|
| 📦 | `video-frames` | **中文:** 使用 ffmpeg 从视频中提取帧或短片段<br><br>**English:** *Extract frames or short clips from videos using ffmpeg.* | agents-skills-personal |
|
||||||
| 📦 | `weather` | **中文:** 通过 wttr.in 或 Open-Meteo 获取当前天气和预报。无需 API key<br><br>**English:** *Get current weather and forecasts via wttr.in or Open-Meteo. Use when: user asks about weather, temperature, or forecasts for any location. NOT for: historical weather data, severe alerts, or detailed meteorological analysis. No API key needed.* | openclaw-bundled |
|
| 📦 | `weather` | **中文:** 通过 wttr.in 或 Open-Meteo 获取当前天气和预报。无需 API key<br><br>**English:** *Get current weather and forecasts via wttr.in or Open-Meteo. Use when: user asks about weather, temperature, or forecasts for any location. NOT for: historical weather data, severe alerts, or detailed meteorological analysis. No API key needed.* | openclaw-bundled |
|
||||||
| 📦 | `accli` | **中文:** 在 macOS 上与 Apple Calendar 交互。用于列出日历、查看事件、创建/更新/删除日历事件、检查可用性/忙闲时间<br><br>**English:** *This skill should be used when interacting with Apple Calendar on macOS. Use it for listing calendars, viewing events, creating/ updating/ deleting calendar events, and checking availability/ free-busy times. Triggers on requests like "check my calendar", "schedule a meeting", "what's on my schedule", "am I free tomorrow", or any calendar- related operations.* | openclaw-managed |
|
| 📦 | `accli` | **中文:** 在 macOS 上与 Apple Calendar 交互。用于列出日历、查看事件、创建/更新/删除日历事件、检查可用性/忙闲时间<br><br>**English:** *This skill should be used when interacting with Apple Calendar on macOS. Use it for listing calendars, viewing events, creating/ updating/ deleting calendar events, and checking availability/ free-busy times. Triggers on requests like "check my calendar", "schedule a meeting", "what's on my schedule", "am I free tomorrow", or any calendar- related operations.* | openclaw-managed |
|
||||||
| 📦 | `agent-browser` | **中文:** 为 AI 代理优化的无头浏览器自动化 CLI,具有无障碍树快照和基于引用的元素选择<br><br>**English:** *Headless browser automation CLI optimized for AI agents with accessibility tree snapshots and ref-based element selection* | openclaw-managed |
|
| 📦 | `agent-browser` | **中文:** 为 AI 代理优化的无头浏览器自动化 CLI,具有无障碍树快照和基于引用的元素选择<br><br>**English:** *Headless browser automation CLI optimized for AI agents with accessibility tree snapshots and ref-based element selection* | openclaw-managed |
|
||||||
| 📦 | `agentmail` | **中文:** 为 AI 代理设计的 API 优先电子邮件平台<br><br>**English:** *API-first email platform designed for AI agents. Create and manage dedicated email inboxes, send and receive emails programmatical ly, and handle email- based workflows with webhooks and real-time events. Use when you need to set up agent email identity, send emails from agents, handle incoming email workflows, or replace traditional email providers like Gmail with agent- friendly infrastructure .* | openclaw-managed |
|
| 📦 | `agentmail` | **中文:** 为 AI 代理设计的 API 优先电子邮件平台<br><br>**English:** *API-first email platform designed for AI agents. Create and manage dedicated email inboxes, send and receive emails programmatical ly, and handle email- based workflows with webhooks and real-time events. Use when you need to set up agent email identity, send emails from agents, handle incoming email workflows, or replace traditional email providers like Gmail with agent- friendly infrastructure .* | openclaw-managed |
|
||||||
| 📦 | `baoyu-imagine` | **中文:** 使用 OpenAI、Azure OpenAI、Google、OpenRouter、DashScope、MiniMax、Jimeng、Seedream 和 Replicate API 进行 AI 图像生成<br><br>**English:** *AI image generation with OpenAI, Azure OpenAI, Google, OpenRouter, DashScope, MiniMax, Jimeng, Seedream and Replicate APIs. Supports text- to-image, reference images, aspect ratios, and batch generation from saved prompt files. Sequential by default; use batch parallel generation when the user already has multiple prompts or wants stable multi-image throughput. Use when user asks to generate, create, or draw images.* | openclaw-managed |
|
| 📦 | `baoyu-imagine` | **中文:** 使用 OpenAI、Azure OpenAI、Google、OpenRouter、DashScope、MiniMax、Jimeng、Seedream 和 Replicate API 进行 AI 图像生成<br><br>**English:** *AI image generation with OpenAI, Azure OpenAI, Google, OpenRouter, DashScope, MiniMax, Jimeng, Seedream and Replicate APIs. Supports text- to-image, reference images, aspect ratios, and batch generation from saved prompt files. Sequential by default; use batch parallel generation when the user already has multiple prompts or wants stable multi-image throughput. Use when user asks to generate, create, or draw images.* | openclaw-managed |
|
||||||
| 📦 | `baoyu-infographic` | **中文:** 生成 21 种布局类型和 20 种视觉样式的专业信息图<br><br>**English:** *Generates professional infographics with 21 layout types and 20 visual styles. Analyzes content, recommends layout×style combinations, and generates publication- ready infographics. Use when user asks to create "infographic", "信息图", "visual summary", "可视化", or "高密度信息大 图".* | openclaw-managed |
|
| 📦 | `baoyu-infographic` | **中文:** 生成 21 种布局类型和 20 种视觉样式的专业信息图<br><br>**English:** *Generates professional infographics with 21 layout types and 20 visual styles. Analyzes content, recommends layout×style combinations, and generates publication- ready infographics. Use when user asks to create "infographic", "信息图", "visual summary", "可视化", or "高密度信息大 图".* | openclaw-managed |
|
||||||
| 📦 | `bitwarden` | **中文:** 设置和使用 Bitwarden CLI (bw)<br><br>**English:** *Set up and use Bitwarden CLI (bw). Use when installing the CLI, authenticating (login/ unlock), or reading secrets from your vault. Supports email/ password, API key, and SSO authentication methods.* | openclaw-managed |
|
| 📦 | `bitwarden` | **中文:** 设置和使用 Bitwarden CLI (bw)<br><br>**English:** *Set up and use Bitwarden CLI (bw). Use when installing the CLI, authenticating (login/ unlock), or reading secrets from your vault. Supports email/ password, API key, and SSO authentication methods.* | openclaw-managed |
|
||||||
| 📦 | `defuddle` | **中文:** 使用 Defuddle CLI 从网页提取干净的 markdown 内容<br><br>**English:** *Extract clean markdown content from web pages using Defuddle CLI, removing clutter and navigation to save tokens. Use instead of WebFetch when the user provides a URL to read or analyze, for online documentation, articles, blog posts, or any standard web page. Do NOT use for URLs ending in .md — those are already markdown, use WebFetch directly.* | openclaw-managed |
|
| 📦 | `defuddle` | **中文:** 使用 Defuddle CLI 从网页提取干净的 markdown 内容<br><br>**English:** *Extract clean markdown content from web pages using Defuddle CLI, removing clutter and navigation to save tokens. Use instead of WebFetch when the user provides a URL to read or analyze, for online documentation, articles, blog posts, or any standard web page. Do NOT use for URLs ending in .md — those are already markdown, use WebFetch directly.* | openclaw-managed |
|
||||||
| 📦 | `Docker` | **中文:** Docker containers, images, Compose stacks, networking, volumes, debugging, production hardening, and the commands that keep real environments stable. Use when (1) the task touches Docker, Dockerfiles, images, containers, or Compose; (2) build reliability, runtime behavior, logs, ports, volumes, or security matter; (3) the agent needs Docker guidance and should apply it by default.<br><br>**English:** *Docker containers, images, Compose stacks, networking, volumes, debugging, production hardening, and the commands that keep real environments stable. Use when (1) the task touches Docker, Dockerfiles, images, containers, or Compose; (2) build reliability, runtime behavior, logs, ports, volumes, or security matter; (3) the agent needs Docker guidance and should apply it by default.* | openclaw-managed |
|
| 📦 | `Docker` | **中文:** Docker containers, images, Compose stacks, networking, volumes, debugging, production hardening, and the commands that keep real environments stable. Use when (1) the task touches Docker, Dockerfiles, images, containers, or Compose; (2) build reliability, runtime behavior, logs, ports, volumes, or security matter; (3) the agent needs Docker guidance and should apply it by default.<br><br>**English:** *Docker containers, images, Compose stacks, networking, volumes, debugging, production hardening, and the commands that keep real environments stable. Use when (1) the task touches Docker, Dockerfiles, images, containers, or Compose; (2) build reliability, runtime behavior, logs, ports, volumes, or security matter; (3) the agent needs Docker guidance and should apply it by default.* | openclaw-managed |
|
||||||
| 📦 | `last30days` | **中文:** 研究过去 30 天内 Reddit、X、YouTube、TikTok、Instagram、Hacker News、Polymarket 和网页上的热门内容<br><br>**English:** *Research a topic from the last 30 days. Also triggered by 'last30'. Sources: Reddit, X, YouTube, TikTok, Instagram, Hacker News, Polymarket, web. Become an expert and write copy- paste-ready prompts.* | openclaw-managed |
|
| 📦 | `last30days` | **中文:** 研究过去 30 天内 Reddit、X、YouTube、TikTok、Instagram、Hacker News、Polymarket 和网页上的热门内容<br><br>**English:** *Research a topic from the last 30 days. Also triggered by 'last30'. Sources: Reddit, X, YouTube, TikTok, Instagram, Hacker News, Polymarket, web. Become an expert and write copy- paste-ready prompts.* | openclaw-managed |
|
||||||
| 📦 | `memory-lancedb-pro` | **中文:** 生产级长期记忆 MCP 插件,支持向量+BM25 混合检索、LLM 智能分类<br><br>**English:** *This skill should be used when working with memory- lancedb-pro, a production- grade long- term memory MCP plugin for OpenClaw AI agents. Use when installing, configuring, or using any feature of memory- lancedb-pro including Smart Extraction, hybrid retrieval, memory lifecycle management, multi-scope isolation, self- improvement governance, or any MCP memory tools (memory_ recall, memory_store, memory_ forget, memory_ update, memory_stats, memory_list, self_ improvement_ log, self_ improvement_ extract_ skill, self_ improvement_ review).* | openclaw-managed |
|
| 📦 | `memory-lancedb-pro` | **中文:** 生产级长期记忆 MCP 插件,支持向量+BM25 混合检索、LLM 智能分类<br><br>**English:** *This skill should be used when working with memory- lancedb-pro, a production- grade long- term memory MCP plugin for OpenClaw AI agents. Use when installing, configuring, or using any feature of memory- lancedb-pro including Smart Extraction, hybrid retrieval, memory lifecycle management, multi-scope isolation, self- improvement governance, or any MCP memory tools (memory_ recall, memory_store, memory_ forget, memory_ update, memory_stats, memory_list, self_ improvement_ log, self_ improvement_ extract_ skill, self_ improvement_ review).* | openclaw-managed |
|
||||||
| 📦 | `⚙️ n8n` | **中文:** Manage n8n workflows and automations via API. Use when working with n8n workflows, executions, or automation tasks - listing workflows, activating/ deactivating, checking execution status, manually triggering workflows, or debugging automation issues.<br><br>**English:** *Manage n8n workflows and automations via API. Use when working with n8n workflows, executions, or automation tasks - listing workflows, activating/ deactivating, checking execution status, manually triggering workflows, or debugging automation issues.* | openclaw-managed |
|
| 📦 | `⚙️ n8n` | **中文:** Manage n8n workflows and automations via API. Use when working with n8n workflows, executions, or automation tasks - listing workflows, activating/ deactivating, checking execution status, manually triggering workflows, or debugging automation issues.<br><br>**English:** *Manage n8n workflows and automations via API. Use when working with n8n workflows, executions, or automation tasks - listing workflows, activating/ deactivating, checking execution status, manually triggering workflows, or debugging automation issues.* | openclaw-managed |
|
||||||
| 📦 | `obsidian-bases` | **中文:** 创建和编辑 Obsidian Bases(.base 文件),具有视图、过滤器、公式和摘要功能<br><br>**English:** *Create and edit Obsidian Bases (.base files) with views, filters, formulas, and summaries. Use when working with . base files, creating database-like views of notes, or when the user mentions Bases, table views, card views, filters, or formulas in Obsidian.* | openclaw-managed |
|
| 📦 | `obsidian-bases` | **中文:** 创建和编辑 Obsidian Bases(.base 文件),具有视图、过滤器、公式和摘要功能<br><br>**English:** *Create and edit Obsidian Bases (.base files) with views, filters, formulas, and summaries. Use when working with . base files, creating database-like views of notes, or when the user mentions Bases, table views, card views, filters, or formulas in Obsidian.* | openclaw-managed |
|
||||||
| 📦 | `obsidian-cli` | **中文:** 使用 Obsidian CLI 与 Obsidian 保险库交互<br><br>**English:** *Interact with Obsidian vaults using the Obsidian CLI to read, create, search, and manage notes, tasks, properties, and more. Also supports plugin and theme development with commands to reload plugins, run JavaScript, capture errors, take screenshots, and inspect the DOM. Use when the user asks to interact with their Obsidian vault, manage notes, search vault content, perform vault operations from the command line, or develop and debug Obsidian plugins and themes.* | openclaw-managed |
|
| 📦 | `obsidian-cli` | **中文:** 使用 Obsidian CLI 与 Obsidian 保险库交互<br><br>**English:** *Interact with Obsidian vaults using the Obsidian CLI to read, create, search, and manage notes, tasks, properties, and more. Also supports plugin and theme development with commands to reload plugins, run JavaScript, capture errors, take screenshots, and inspect the DOM. Use when the user asks to interact with their Obsidian vault, manage notes, search vault content, perform vault operations from the command line, or develop and debug Obsidian plugins and themes.* | openclaw-managed |
|
||||||
| 📦 | `ontology` | **中文:** 用于结构化代理记忆的 typed 知识图谱<br><br>**English:** *Typed knowledge graph for structured agent memory and composable skills. Use when creating/ querying entities (Person, Project, Task, Event, Document), linking related objects, enforcing constraints, planning multi-step actions as graph transformation s, or when skills need to share state. Trigger on "remember", "what do I know about", "link X to Y", "show dependencies", entity CRUD, or cross- skill data access.* | agents-skills-personal |
|
| 📦 | `ontology` | **中文:** 用于结构化代理记忆的 typed 知识图谱<br><br>**English:** *Typed knowledge graph for structured agent memory and composable skills. Use when creating/ querying entities (Person, Project, Task, Event, Document), linking related objects, enforcing constraints, planning multi-step actions as graph transformation s, or when skills need to share state. Trigger on "remember", "what do I know about", "link X to Y", "show dependencies", entity CRUD, or cross- skill data access.* | agents-skills-personal |
|
||||||
| 📦 | `tavily-search` | **中文:** 通过 Tavily API 进行网络搜索<br><br>**English:** *Web search via Tavily API (alternative to Brave). Use when the user asks to search the web / look up sources / find links and Brave web_ search is unavailable or undesired. Returns a small set of relevant results (title, url, snippet) and can optionally include short answer summaries.* | openclaw-managed |
|
| 📦 | `tavily-search` | **中文:** 通过 Tavily API 进行网络搜索<br><br>**English:** *Web search via Tavily API (alternative to Brave). Use when the user asks to search the web / look up sources / find links and Brave web_ search is unavailable or undesired. Returns a small set of relevant results (title, url, snippet) and can optionally include short answer summaries.* | openclaw-managed |
|
||||||
| 📦 | `Powerpoint` | **中文:** Create, inspect, and edit Microsoft PowerPoint presentations and PPTX decks with reliable layouts, templates, placeholders, notes, charts, and visual QA. Use when (1) the task is about PowerPoint or `.pptx`; (2) layouts, placeholders, notes, charts, comments, or template fidelity matter; (3) the deck must render cleanly after edits.<br><br>**English:** *Create, inspect, and edit Microsoft PowerPoint presentations and PPTX decks with reliable layouts, templates, placeholders, notes, charts, and visual QA. Use when (1) the task is about PowerPoint or `.pptx`; (2) layouts, placeholders, notes, charts, comments, or template fidelity matter; (3) the deck must render cleanly after edits.* | openclaw-managed |
|
| 📦 | `Powerpoint` | **中文:** Create, inspect, and edit Microsoft PowerPoint presentations and PPTX decks with reliable layouts, templates, placeholders, notes, charts, and visual QA. Use when (1) the task is about PowerPoint or `.pptx`; (2) layouts, placeholders, notes, charts, comments, or template fidelity matter; (3) the deck must render cleanly after edits.<br><br>**English:** *Create, inspect, and edit Microsoft PowerPoint presentations and PPTX decks with reliable layouts, templates, placeholders, notes, charts, and visual QA. Use when (1) the task is about PowerPoint or `.pptx`; (2) layouts, placeholders, notes, charts, comments, or template fidelity matter; (3) the deck must render cleanly after edits.* | openclaw-managed |
|
||||||
| 📦 | `proactive-agent-lite` | **中文:** 将 AI 代理从任务执行者转变为主动合作伙伴<br><br>**English:** *Transform AI agents from task- followers into proactive partners with memory architecture, reverse prompting, and self- healing patterns. Lightweight version focused on core proactive capabilities.* | openclaw-managed |
|
| 📦 | `proactive-agent-lite` | **中文:** 将 AI 代理从任务执行者转变为主动合作伙伴<br><br>**English:** *Transform AI agents from task- followers into proactive partners with memory architecture, reverse prompting, and self- healing patterns. Lightweight version focused on core proactive capabilities.* | openclaw-managed |
|
||||||
| 📦 | `self-improvement` | **中文:** 捕获学习、错误和修正以实现持续改进<br><br>**English:** *Captures learnings, errors, and corrections to enable continuous improvement. Use when: (1) A command or operation fails unexpectedly, (2) User corrects Claude ('No, that's wrong.. .', 'Actually. ..'), (3) User requests a capability that doesn't exist, (4) An external API or tool fails, (5) Claude realizes its knowledge is outdated or incorrect, (6) A better approach is discovered for a recurring task. Also review learnings before major tasks.* | openclaw-managed |
|
| 📦 | `self-improvement` | **中文:** 捕获学习、错误和修正以实现持续改进<br><br>**English:** *Captures learnings, errors, and corrections to enable continuous improvement. Use when: (1) A command or operation fails unexpectedly, (2) User corrects Claude ('No, that's wrong.. .', 'Actually. ..'), (3) User requests a capability that doesn't exist, (4) An external API or tool fails, (5) Claude realizes its knowledge is outdated or incorrect, (6) A better approach is discovered for a recurring task. Also review learnings before major tasks.* | openclaw-managed |
|
||||||
| 📦 | `skill-vetter` | **中文:** AI 代理的安全优先技能审查<br><br>**English:** *Security- first skill vetting for AI agents. Use before installing any skill from ClawdHub, GitHub, or other sources. Checks for red flags, permission scope, and suspicious patterns. ✓ ready 📦 task-summary 任务执行总结技 能。用于在完成 任务后生成结构 化的任务总结, 记录任务目标、 执行步骤、结果 和经验教训,以 便后续追溯和改 进。* | agents-skills-personal |
|
| 📦 | `skill-vetter` | **中文:** AI 代理的安全优先技能审查<br><br>**English:** *Security- first skill vetting for AI agents. Use before installing any skill from ClawdHub, GitHub, or other sources. Checks for red flags, permission scope, and suspicious patterns. ✓ ready 📦 task-summary 任务执行总结技 能。用于在完成 任务后生成结构 化的任务总结, 记录任务目标、 执行步骤、结果 和经验教训,以 便后续追溯和改 进。* | agents-skills-personal |
|
||||||
| 📦 | `backtest-expert` | **中文:** 系统交易策略回测的专家指导<br><br>**English:** *Expert guidance for systematic backtesting of trading strategies. Use when developing, testing, stress- testing, or validating quantitative trading strategies. Covers "beating ideas to death" methodology, parameter robustness testing, slippage modeling, bias prevention, and interpreting backtest results. Applicable when user asks about backtesting, strategy validation, robustness testing, avoiding overfitting, or systematic trading development. ✓ ready 📦 bazi 四柱八字命理分 析。通过交互式 步骤收集出生信 息(姓名、曾用 名、阳历/ 农历生日、时辰 、性别、出生地 ), 排出四柱八字, 参照经典命理典 籍(穷通宝典、 三命通会、滴天 髓、渊海子平、 子平真诠等)进 行专业分析。 Use this skill whenever the user asks for 八字、四柱、命 理、算命、Bazi 、fortune telling、 birth chart analysis, or wants to know about their 八字命盘、运势 、大运、流年. Triggers: "算八字", "看八字", "批八字", "排八字", "四柱", "命盘", "算命", "帮我看看八字" , "我想算八字", "分析八字", "排盘", "bazi", "bazi analysis", "fortune telling", "birth chart", "算一卦", "看运势", "命运分析". 即使只是提到" 算命"、"八字" 而没有明确说要 用skill,也应 该使用此skill 。* | agents-skills-personal |
|
| 📦 | `backtest-expert` | **中文:** 系统交易策略回测的专家指导<br><br>**English:** *Expert guidance for systematic backtesting of trading strategies. Use when developing, testing, stress- testing, or validating quantitative trading strategies. Covers "beating ideas to death" methodology, parameter robustness testing, slippage modeling, bias prevention, and interpreting backtest results. Applicable when user asks about backtesting, strategy validation, robustness testing, avoiding overfitting, or systematic trading development. ✓ ready 📦 bazi 四柱八字命理分 析。通过交互式 步骤收集出生信 息(姓名、曾用 名、阳历/ 农历生日、时辰 、性别、出生地 ), 排出四柱八字, 参照经典命理典 籍(穷通宝典、 三命通会、滴天 髓、渊海子平、 子平真诠等)进 行专业分析。 Use this skill whenever the user asks for 八字、四柱、命 理、算命、Bazi 、fortune telling、 birth chart analysis, or wants to know about their 八字命盘、运势 、大运、流年. Triggers: "算八字", "看八字", "批八字", "排八字", "四柱", "命盘", "算命", "帮我看看八字" , "我想算八字", "分析八字", "排盘", "bazi", "bazi analysis", "fortune telling", "birth chart", "算一卦", "看运势", "命运分析". 即使只是提到" 算命"、"八字" 而没有明确说要 用skill,也应 该使用此skill 。* | agents-skills-personal |
|
||||||
| 📦 | `blog-writer` | **中文:** 以作家独特风格撰写博客文章<br><br>**English:** *This skill should be used when writing blog posts, articles, or long-form content in the writer's distinctive writing style. It produces authentic, opinionated content that matches the writer's voice—direct, conversational , and grounded in personal experience. The skill handles the complete workflow from research review through Notion publication. Use this skill for drafting blog posts, thought leadership pieces, or any writing meant to reflect the writer's perspective on AI, productivity, sales, marketing, or technology topics.* | agents-skills-personal |
|
| 📦 | `blog-writer` | **中文:** 以作家独特风格撰写博客文章<br><br>**English:** *This skill should be used when writing blog posts, articles, or long-form content in the writer's distinctive writing style. It produces authentic, opinionated content that matches the writer's voice—direct, conversational , and grounded in personal experience. The skill handles the complete workflow from research review through Notion publication. Use this skill for drafting blog posts, thought leadership pieces, or any writing meant to reflect the writer's perspective on AI, productivity, sales, marketing, or technology topics.* | agents-skills-personal |
|
||||||
| 📦 | `brainstorming` | **中文:** 在任何创意工作之前必须使用<br><br>**English:** *You MUST use this before any creative work - creating features, building components, adding functionality, or modifying behavior. Explores user intent, requirements and design before implementation .* | agents-skills-personal |
|
| 📦 | `brainstorming` | **中文:** 在任何创意工作之前必须使用<br><br>**English:** *You MUST use this before any creative work - creating features, building components, adding functionality, or modifying behavior. Explores user intent, requirements and design before implementation .* | agents-skills-personal |
|
||||||
| 📦 | `clawdefender` | **中文:** AI 代理的安全扫描器和输入清理器<br><br>**English:** *Security scanner and input sanitizer for AI agents. Detects prompt injection, command injection, SSRF, credential exfiltration, and path traversal attacks. Use when (1) installing new skills from ClawHub, (2) processing external input like emails, calendar events, Trello cards, or API responses, (3) validating URLs before fetching, (4) running security audits on your workspace. Protects agents from malicious content in untrusted data sources.* | agents-skills-personal |
|
| 📦 | `clawdefender` | **中文:** AI 代理的安全扫描器和输入清理器<br><br>**English:** *Security scanner and input sanitizer for AI agents. Detects prompt injection, command injection, SSRF, credential exfiltration, and path traversal attacks. Use when (1) installing new skills from ClawHub, (2) processing external input like emails, calendar events, Trello cards, or API responses, (3) validating URLs before fetching, (4) running security audits on your workspace. Protects agents from malicious content in untrusted data sources.* | agents-skills-personal |
|
||||||
| 📦 | `Code` | **中文:** Coding workflow with planning, implementation , verification, and testing for clean software development.<br><br>**English:** *Coding workflow with planning, implementation , verification, and testing for clean software development.* | agents-skills-personal |
|
| 📦 | `Code` | **中文:** Coding workflow with planning, implementation , verification, and testing for clean software development.<br><br>**English:** *Coding workflow with planning, implementation , verification, and testing for clean software development.* | agents-skills-personal |
|
||||||
| 📦 | `content-strategy` | **中文:** 为独立创业者业务构建和执行内容营销策略<br><br>**English:** *Build and execute a content marketing strategy for a solopreneur business. Use when planning what content to create, deciding on content formats and channels, building a content calendar, measuring content performance, or systematizing content production. Covers audience research for content, content pillars, distribution strategy, repurposing workflows, and metrics. Trigger on "content strategy", "content marketing", "what content should I create", "content plan", "content calendar", "content ideas", "content distribution", "grow through content".* | agents-skills-personal |
|
| 📦 | `content-strategy` | **中文:** 为独立创业者业务构建和执行内容营销策略<br><br>**English:** *Build and execute a content marketing strategy for a solopreneur business. Use when planning what content to create, deciding on content formats and channels, building a content calendar, measuring content performance, or systematizing content production. Covers audience research for content, content pillars, distribution strategy, repurposing workflows, and metrics. Trigger on "content strategy", "content marketing", "what content should I create", "content plan", "content calendar", "content ideas", "content distribution", "grow through content".* | agents-skills-personal |
|
||||||
| 📦 | `diamond-sutra` | **中文:** Use this skill to answer questions related to the Diamond Sutra (Mahayana Buddhism, Prajna division) and when the user seeks spiritual or psychological advice on letting go of anxiety, workplace stress, and social labels using modern Buddhist interpretation s from Master Nan Huai-Jin and Prof. Fei Yong.<br><br>**English:** *Use this skill to answer questions related to the Diamond Sutra (Mahayana Buddhism, Prajna division) and when the user seeks spiritual or psychological advice on letting go of anxiety, workplace stress, and social labels using modern Buddhist interpretation s from Master Nan Huai-Jin and Prof. Fei Yong.* | agents-skills-personal |
|
| 📦 | `diamond-sutra` | **中文:** Use this skill to answer questions related to the Diamond Sutra (Mahayana Buddhism, Prajna division) and when the user seeks spiritual or psychological advice on letting go of anxiety, workplace stress, and social labels using modern Buddhist interpretation s from Master Nan Huai-Jin and Prof. Fei Yong.<br><br>**English:** *Use this skill to answer questions related to the Diamond Sutra (Mahayana Buddhism, Prajna division) and when the user seeks spiritual or psychological advice on letting go of anxiety, workplace stress, and social labels using modern Buddhist interpretation s from Master Nan Huai-Jin and Prof. Fei Yong.* | agents-skills-personal |
|
||||||
| 📦 | `executing-plans` | **中文:** 当你有书面实施计划时使用<br><br>**English:** *Use when you have a written implementation plan to execute in a separate session with review checkpoints* | agents-skills-personal |
|
| 📦 | `executing-plans` | **中文:** 当你有书面实施计划时使用<br><br>**English:** *Use when you have a written implementation plan to execute in a separate session with review checkpoints* | agents-skills-personal |
|
||||||
| 📦 | `FFmpeg` | **中文:** Generate commands from natural language video editing requests - cut, trim, convert, compress, change aspect ratio, extract audio, and more.<br><br>**English:** *Generate commands from natural language video editing requests - cut, trim, convert, compress, change aspect ratio, extract audio, and more.* | agents-skills-personal |
|
| 📦 | `FFmpeg` | **中文:** Generate commands from natural language video editing requests - cut, trim, convert, compress, change aspect ratio, extract audio, and more.<br><br>**English:** *Generate commands from natural language video editing requests - cut, trim, convert, compress, change aspect ratio, extract audio, and more.* | agents-skills-personal |
|
||||||
| 📦 | `find-skills` | **中文:** 帮助用户发现和安装代理技能<br><br>**English:** *Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.* | agents-skills-personal |
|
| 📦 | `find-skills` | **中文:** 帮助用户发现和安装代理技能<br><br>**English:** *Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.* | agents-skills-personal |
|
||||||
| 📦 | `frontend-design` | **中文:** 创建独特、生产级的前端界面,具有高设计质量<br><br>**English:** *Create distinctive, production- grade frontend interfaces with high design quality. Use this skill when building web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.* | agents-skills-personal |
|
| 📦 | `frontend-design` | **中文:** 创建独特、生产级的前端界面,具有高设计质量<br><br>**English:** *Create distinctive, production- grade frontend interfaces with high design quality. Use this skill when building web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.* | agents-skills-personal |
|
||||||
| 📦 | `git-essentials` | **中文:** 版本控制、分支和协作的基本 Git 命令和工作流<br><br>**English:** *Essential Git commands and workflows for version control, branching, and collaboration.* | agents-skills-personal |
|
| 📦 | `git-essentials` | **中文:** 版本控制、分支和协作的基本 Git 命令和工作流<br><br>**English:** *Essential Git commands and workflows for version control, branching, and collaboration.* | agents-skills-personal |
|
||||||
| 📦 | `laozi-confucius-buddha-wisdom` | **中文:** 查询老子、孔子和佛陀的智慧<br><br>**English:** *Query wisdom from Laozi (Daoism), Confucius (Confucianism) , and Buddha (Buddhism) - core teachings, quotes, and applied insights.* | agents-skills-personal |
|
| 📦 | `laozi-confucius-buddha-wisdom` | **中文:** 查询老子、孔子和佛陀的智慧<br><br>**English:** *Query wisdom from Laozi (Daoism), Confucius (Confucianism) , and Buddha (Buddhism) - core teachings, quotes, and applied insights.* | agents-skills-personal |
|
||||||
| 📦 | `Market` | **中文:** Size markets, analyze competitors, and validate opportunities with practical frameworks and free data sources.<br><br>**English:** *Size markets, analyze competitors, and validate opportunities with practical frameworks and free data sources.* | agents-skills-personal |
|
| 📦 | `Market` | **中文:** Size markets, analyze competitors, and validate opportunities with practical frameworks and free data sources.<br><br>**English:** *Size markets, analyze competitors, and validate opportunities with practical frameworks and free data sources.* | agents-skills-personal |
|
||||||
| 📦 | `Memory` | **中文:** Infinite organized memory that complements your agent's built-in memory with unlimited categorized storage. ✓ ready 📦 huashu-nuwa 女娲造人:输入 人名/主题/ 甚至只是模糊需 求,自动深度调 研→思维框架提 炼→生成可运行 的人物Skill。 两种入口:(1) 明确人名→直接 蒸馏 (2)模糊需求→诊 断推荐→再蒸馏 。 触发词:「造sk ill」「蒸馏XX 」「女娲」「造 人」「XX的思维 方式」「做个XX 视角」「更新XX 的skill」。 模糊需求也触发 :「我想提升决 策质量」「有没 有一种思维方式 能帮我... 」「我需要一个 思维顾问」。<br><br>**English:** *Infinite organized memory that complements your agent's built-in memory with unlimited categorized storage. ✓ ready 📦 huashu-nuwa 女娲造人:输入 人名/主题/ 甚至只是模糊需 求,自动深度调 研→思维框架提 炼→生成可运行 的人物Skill。 两种入口:(1) 明确人名→直接 蒸馏 (2)模糊需求→诊 断推荐→再蒸馏 。 触发词:「造sk ill」「蒸馏XX 」「女娲」「造 人」「XX的思维 方式」「做个XX 视角」「更新XX 的skill」。 模糊需求也触发 :「我想提升决 策质量」「有没 有一种思维方式 能帮我... 」「我需要一个 思维顾问」。* | agents-skills-personal |
|
| 📦 | `Memory` | **中文:** Infinite organized memory that complements your agent's built-in memory with unlimited categorized storage. ✓ ready 📦 huashu-nuwa 女娲造人:输入 人名/主题/ 甚至只是模糊需 求,自动深度调 研→思维框架提 炼→生成可运行 的人物Skill。 两种入口:(1) 明确人名→直接 蒸馏 (2)模糊需求→诊 断推荐→再蒸馏 。 触发词:「造sk ill」「蒸馏XX 」「女娲」「造 人」「XX的思维 方式」「做个XX 视角」「更新XX 的skill」。 模糊需求也触发 :「我想提升决 策质量」「有没 有一种思维方式 能帮我... 」「我需要一个 思维顾问」。<br><br>**English:** *Infinite organized memory that complements your agent's built-in memory with unlimited categorized storage. ✓ ready 📦 huashu-nuwa 女娲造人:输入 人名/主题/ 甚至只是模糊需 求,自动深度调 研→思维框架提 炼→生成可运行 的人物Skill。 两种入口:(1) 明确人名→直接 蒸馏 (2)模糊需求→诊 断推荐→再蒸馏 。 触发词:「造sk ill」「蒸馏XX 」「女娲」「造 人」「XX的思维 方式」「做个XX 视角」「更新XX 的skill」。 模糊需求也触发 :「我想提升决 策质量」「有没 有一种思维方式 能帮我... 」「我需要一个 思维顾问」。* | agents-skills-personal |
|
||||||
| 📦 | `obsidian-ontology-sync` | **中文:** Obsidian PKM 和结构化本体之间的双向同步<br><br>**English:** *Bidirectional sync between Obsidian PKM (human- friendly notes) and structured ontology (machine- queryable graph). Automatically extracts entities and relationships from markdown, maintains ontology graph, and provides feedback to improve note structure. Run sync every few hours via cron.* | agents-skills-personal |
|
| 📦 | `obsidian-ontology-sync` | **中文:** Obsidian PKM 和结构化本体之间的双向同步<br><br>**English:** *Bidirectional sync between Obsidian PKM (human- friendly notes) and structured ontology (machine- queryable graph). Automatically extracts entities and relationships from markdown, maintains ontology graph, and provides feedback to improve note structure. Run sync every few hours via cron.* | agents-skills-personal |
|
||||||
| 📦 | `opencode-controller` | **中文:** 通过斜杠命令控制和操作 Opencode<br><br>**English:** *Control and operate Opencode via slash commands. Use this skill to manage sessions, select models, switch agents (plan/build), and coordinate coding through Opencode. ✓ ready 📦 poetry-master 诗词雅韵助手—— 中华传统诗词专 业点评与润色。 此技能应在以下 场景触发:用户 提交古体诗、近 体诗(五绝、七 绝、五律、七律 )、宋词、元曲 等中华传统诗词 作品并请求点评 、赏析、修改或 润色;用户询问 诗词格律(平仄 、押韵、对仗、 词谱);用户请 求诗词创作指导 或灵感建议。覆 盖体裁包括但不 限于古风、绝句 、律诗、词(小 令、中调、长调 )、散曲等。* | agents-skills-personal |
|
| 📦 | `opencode-controller` | **中文:** 通过斜杠命令控制和操作 Opencode<br><br>**English:** *Control and operate Opencode via slash commands. Use this skill to manage sessions, select models, switch agents (plan/build), and coordinate coding through Opencode. ✓ ready 📦 poetry-master 诗词雅韵助手—— 中华传统诗词专 业点评与润色。 此技能应在以下 场景触发:用户 提交古体诗、近 体诗(五绝、七 绝、五律、七律 )、宋词、元曲 等中华传统诗词 作品并请求点评 、赏析、修改或 润色;用户询问 诗词格律(平仄 、押韵、对仗、 词谱);用户请 求诗词创作指导 或灵感建议。覆 盖体裁包括但不 限于古风、绝句 、律诗、词(小 令、中调、长调 )、散曲等。* | agents-skills-personal |
|
||||||
| 📦 | `qmd` | **中文:** 使用 QMD 搜索 markdown 知识库、笔记和文档<br><br>**English:** *Search markdown knowledge bases, notes, and documentation using QMD. Use when users ask to search notes, find documents, or look up information.* | agents-skills-personal |
|
| 📦 | `qmd` | **中文:** 使用 QMD 搜索 markdown 知识库、笔记和文档<br><br>**English:** *Search markdown knowledge bases, notes, and documentation using QMD. Use when users ask to search notes, find documents, or look up information.* | agents-skills-personal |
|
||||||
| 📦 | `security-auditor` | **中文:** 审查代码安全漏洞、实施身份验证流程、审计 OWASP Top 10<br><br>**English:** *Use when reviewing code for security vulnerabilitie s, implementing authentication flows, auditing OWASP Top 10, configuring CORS/CSP headers, handling secrets, input validation, SQL injection prevention, XSS protection, or any security- related code review. ⏸ disabled 📦 Self-Improving Agent (With Self-Reflection) Self- reflection + Self- criticism + learning from corrections. Agent evaluates its own work, catches mistakes, and improves permanently. ✓ ready 📦 SEO (Site Audit + Content Writer + Competitor Analysis) SEO specialist agent with site audits, content writing, keyword research, technical fixes, link building, and ranking strategies.* | agents-skills-personal |
|
| 📦 | `security-auditor` | **中文:** 审查代码安全漏洞、实施身份验证流程、审计 OWASP Top 10<br><br>**English:** *Use when reviewing code for security vulnerabilitie s, implementing authentication flows, auditing OWASP Top 10, configuring CORS/CSP headers, handling secrets, input validation, SQL injection prevention, XSS protection, or any security- related code review. ⏸ disabled 📦 Self-Improving Agent (With Self-Reflection) Self- reflection + Self- criticism + learning from corrections. Agent evaluates its own work, catches mistakes, and improves permanently. ✓ ready 📦 SEO (Site Audit + Content Writer + Competitor Analysis) SEO specialist agent with site audits, content writing, keyword research, technical fixes, link building, and ranking strategies.* | agents-skills-personal |
|
||||||
| 📦 | `seo-content-writer` | **中文:** 创建在搜索引擎中排名的高质量、SEO 优化内容<br><br>**English:** *Use when the user asks to "write SEO content", "create a blog post", "write an article", "content writing", "draft optimized content", "write me an article", "create a blog post about", "help me write SEO content", or "draft content for". Creates high- quality, SEO- optimized content that ranks in search engines. Applies on- page SEO best practices, keyword optimization, and content structure for maximum visibility and engagement. For AI citation optimization, see geo- content- optimizer. For updating existing content, see content- refresher.* | agents-skills-personal |
|
| 📦 | `seo-content-writer` | **中文:** 创建在搜索引擎中排名的高质量、SEO 优化内容<br><br>**English:** *Use when the user asks to "write SEO content", "create a blog post", "write an article", "content writing", "draft optimized content", "write me an article", "create a blog post about", "help me write SEO content", or "draft content for". Creates high- quality, SEO- optimized content that ranks in search engines. Applies on- page SEO best practices, keyword optimization, and content structure for maximum visibility and engagement. For AI citation optimization, see geo- content- optimizer. For updating existing content, see content- refresher.* | agents-skills-personal |
|
||||||
| 📦 | `social-content` | **中文:** 帮助创建、安排或优化 LinkedIn、Twitter/X、Instagram、TikTok、Facebook 或其他平台的内容<br><br>**English:** *When the user wants help creating, scheduling, or optimizing social media content for LinkedIn, Twitter/X, Instagram, TikTok, Facebook, or other platforms. Also use when the user mentions 'LinkedIn post,' 'Twitter thread,' 'social media,' 'content calendar,' 'social scheduling,' 'engagement,' or 'viral content.' This skill covers content creation, repurposing, and platform- specific strategies.* | agents-skills-personal |
|
| 📦 | `social-content` | **中文:** 帮助创建、安排或优化 LinkedIn、Twitter/X、Instagram、TikTok、Facebook 或其他平台的内容<br><br>**English:** *When the user wants help creating, scheduling, or optimizing social media content for LinkedIn, Twitter/X, Instagram, TikTok, Facebook, or other platforms. Also use when the user mentions 'LinkedIn post,' 'Twitter thread,' 'social media,' 'content calendar,' 'social scheduling,' 'engagement,' or 'viral content.' This skill covers content creation, repurposing, and platform- specific strategies.* | agents-skills-personal |
|
||||||
| 📦 | `Social` | **中文:** Plan, draft, and organize social media content across platforms. Create content calendars, write platform- optimized posts, and maintain consistent posting schedules.<br><br>**English:** *Plan, draft, and organize social media content across platforms. Create content calendars, write platform- optimized posts, and maintain consistent posting schedules.* | agents-skills-personal |
|
| 📦 | `Social` | **中文:** Plan, draft, and organize social media content across platforms. Create content calendars, write platform- optimized posts, and maintain consistent posting schedules.<br><br>**English:** *Plan, draft, and organize social media content across platforms. Create content calendars, write platform- optimized posts, and maintain consistent posting schedules.* | agents-skills-personal |
|
||||||
| 📦 | `su-dongpo-perspective` | **中文:** 苏东坡(苏轼)的思维框架与表达方式<br><br>**English:** *苏东坡(苏轼, 1037- 1101)的思维框 架与表达方式。 基于诗词文章、 史书传记、千年 评述的深度研究 , 提炼6个核心心 智模型、8条决 策启发式和完整 的表达DNA。 用途:作为思维 顾问,用苏东坡 的视角分析问题 、审视抉择、提 供逆境中的智慧 。 当用户提到「用 苏东坡的视角」 「苏东坡会怎么 看」「东坡模式 」「苏东坡 perspective」 时使用。 即使用户只是说 「帮我用苏东坡 的角度想想」「 如果苏东坡会怎 么做」「切换到 苏东坡」也应触 发。 适用于:逆境咨 询、审美鉴赏、 人生进退的抉择 、文学创作、跨 时空的精神对话 。 △ needs setup 📜 Today in History - 历史上的今天 按月日查询历史 上同日大事、诞 辰与逝世等。当 用户说:历史上 的今天发生了什 么?3 月 15 日有什么大事? 或类似历史纪事 问题时,使用本 技能。* | agents-skills-personal |
|
| 📦 | `su-dongpo-perspective` | **中文:** 苏东坡(苏轼)的思维框架与表达方式<br><br>**English:** *苏东坡(苏轼, 1037- 1101)的思维框 架与表达方式。 基于诗词文章、 史书传记、千年 评述的深度研究 , 提炼6个核心心 智模型、8条决 策启发式和完整 的表达DNA。 用途:作为思维 顾问,用苏东坡 的视角分析问题 、审视抉择、提 供逆境中的智慧 。 当用户提到「用 苏东坡的视角」 「苏东坡会怎么 看」「东坡模式 」「苏东坡 perspective」 时使用。 即使用户只是说 「帮我用苏东坡 的角度想想」「 如果苏东坡会怎 么做」「切换到 苏东坡」也应触 发。 适用于:逆境咨 询、审美鉴赏、 人生进退的抉择 、文学创作、跨 时空的精神对话 。 △ needs setup 📜 Today in History - 历史上的今天 按月日查询历史 上同日大事、诞 辰与逝世等。当 用户说:历史上 的今天发生了什 么?3 月 15 日有什么大事? 或类似历史纪事 问题时,使用本 技能。* | agents-skills-personal |
|
||||||
| 📦 | `ui-ux-pro-max` | **中文:** UI/UX 设计智能和实施指导,用于构建精美界面<br><br>**English:** *UI/UX design intelligence and implementation guidance for building polished interfaces. Use when the user asks for UI design, UX flows, information architecture, visual style direction, design systems/ tokens, component specs, copy/ microcopy, accessibility, or to generate/ critique/ refine frontend UI (HTML/CSS/JS, React, Next. js, Vue, Svelte, Tailwind). Includes workflows for (1) generating new UI layouts and styling, (2) improving existing UI/ UX, (3) producing design-system tokens and component guidelines, and (4) turning UX recommendation s into concrete code changes.* | agents-skills-personal |
|
| 📦 | `ui-ux-pro-max` | **中文:** UI/UX 设计智能和实施指导,用于构建精美界面<br><br>**English:** *UI/UX design intelligence and implementation guidance for building polished interfaces. Use when the user asks for UI design, UX flows, information architecture, visual style direction, design systems/ tokens, component specs, copy/ microcopy, accessibility, or to generate/ critique/ refine frontend UI (HTML/CSS/JS, React, Next. js, Vue, Svelte, Tailwind). Includes workflows for (1) generating new UI layouts and styling, (2) improving existing UI/ UX, (3) producing design-system tokens and component guidelines, and (4) turning UX recommendation s into concrete code changes.* | agents-skills-personal |
|
||||||
| 📦 | `wisdom-claw` | **中文:** 佛教智慧和正念对话伴侣<br><br>**English:** *Buddhist wisdom and mindful dialogue companion. Built on Madhyamaka (Middle Way) philosophy, integrating meditation, dialog skills, and classic Buddhist teachings. Use when: (1) helping users understand core Buddhist teachings (emptiness, no-self, middle way), (2) guiding users to see their own attachments in conversation, (3) pointing with force rather than lecturing. Triggered when users ask about Buddhist philosophy, practice confusion, life challenges, or encounter dilemmas.* | agents-skills-personal |
|
| 📦 | `wisdom-claw` | **中文:** 佛教智慧和正念对话伴侣<br><br>**English:** *Buddhist wisdom and mindful dialogue companion. Built on Madhyamaka (Middle Way) philosophy, integrating meditation, dialog skills, and classic Buddhist teachings. Use when: (1) helping users understand core Buddhist teachings (emptiness, no-self, middle way), (2) guiding users to see their own attachments in conversation, (3) pointing with force rather than lecturing. Triggered when users ask about Buddhist philosophy, practice confusion, life challenges, or encounter dilemmas.* | agents-skills-personal |
|
||||||
| 📦 | `writing-plans` | **中文:** 当你有规范或需求时使用<br><br>**English:** *Use when you have a spec or requirements for a multi- step task, before touching code ✓ ready 📦 xiao-jue 小觉是一个看过 很多佛法的AI助 手。心法和wisd om- claw一样,但更 纯粹、更直接。 不说教,不啰嗦 ,一句话点到。 用于佛法讨论、 当下对话。 ✓ ready 📦 zen-master 禅宗禅师技能 - 将任意 Agent 转型为精通禅宗 经论、公案、语 录的禅宗大法师 。包含完整知识 库(心经、金刚 经、坛经、公案 、禅诗),支持 一键安装。* | agents-skills-personal |
|
| 📦 | `writing-plans` | **中文:** 当你有规范或需求时使用<br><br>**English:** *Use when you have a spec or requirements for a multi- step task, before touching code ✓ ready 📦 xiao-jue 小觉是一个看过 很多佛法的AI助 手。心法和wisd om- claw一样,但更 纯粹、更直接。 不说教,不啰嗦 ,一句话点到。 用于佛法讨论、 当下对话。 ✓ ready 📦 zen-master 禅宗禅师技能 - 将任意 Agent 转型为精通禅宗 经论、公案、语 录的禅宗大法师 。包含完整知识 库(心经、金刚 经、坛经、公案 、禅诗),支持 一键安装。* | agents-skills-personal |
|
||||||
|
|
||||||
### △ Needs Setup (32 个)
|
### △ Needs Setup (32 个)
|
||||||
|
|
||||||
| 图标 | 技能 | 描述 | 来源 |
|
| 图标 | 技能 | 描述 | 来源 |
|
||||||
|------|------|------|------|
|
|------|------|------|------|
|
||||||
| 📦 | `bear-notes` | **中文:** 通过 grizzly CLI 创建、搜索和管理 Bear 笔记<br><br>**English:** *Create, search, and manage Bear notes via grizzly CLI.* | openclaw-bundled |
|
| 📦 | `bear-notes` | **中文:** 通过 grizzly CLI 创建、搜索和管理 Bear 笔记<br><br>**English:** *Create, search, and manage Bear notes via grizzly CLI.* | openclaw-bundled |
|
||||||
| 📦 | `blogwatcher` | **中文:** 使用 blogwatcher CLI 监控博客和 RSS/Atom 订阅更新<br><br>**English:** *Monitor blogs and RSS/Atom feeds for updates using the CLI.* | openclaw-bundled |
|
| 📦 | `blogwatcher` | **中文:** 使用 blogwatcher CLI 监控博客和 RSS/Atom 订阅更新<br><br>**English:** *Monitor blogs and RSS/Atom feeds for updates using the CLI.* | openclaw-bundled |
|
||||||
| 📦 | `🫐 blucli` | **中文:** BluOS CLI (blu) for discovery, playback, grouping, and volume.<br><br>**English:** *BluOS CLI (blu) for discovery, playback, grouping, and volume.* | openclaw-bundled |
|
| 📦 | `🫐 blucli` | **中文:** BluOS CLI (blu) for discovery, playback, grouping, and volume.<br><br>**English:** *BluOS CLI (blu) for discovery, playback, grouping, and volume.* | openclaw-bundled |
|
||||||
| 📦 | `🫧 bluebubbles` | **中文:** Use when you need to send or manage iMessages via BlueBubbles (recommended iMessage integration). Calls go through the generic message tool with channel="blueb ubbles".<br><br>**English:** *Use when you need to send or manage iMessages via BlueBubbles (recommended iMessage integration). Calls go through the generic message tool with channel="blueb ubbles".* | openclaw-bundled |
|
| 📦 | `🫧 bluebubbles` | **中文:** Use when you need to send or manage iMessages via BlueBubbles (recommended iMessage integration). Calls go through the generic message tool with channel="blueb ubbles".<br><br>**English:** *Use when you need to send or manage iMessages via BlueBubbles (recommended iMessage integration). Calls go through the generic message tool with channel="blueb ubbles".* | openclaw-bundled |
|
||||||
| 📦 | `camsnap` | **中文:** 从 RTSP/ONVIF 摄像头捕获帧或片段<br><br>**English:** *Capture frames or clips from RTSP/ONVIF cameras.* | openclaw-bundled |
|
| 📦 | `camsnap` | **中文:** 从 RTSP/ONVIF 摄像头捕获帧或片段<br><br>**English:** *Capture frames or clips from RTSP/ONVIF cameras.* | openclaw-bundled |
|
||||||
| 📦 | `discord` | **中文:** 通过 message 工具进行 Discord 操作<br><br>**English:** *Discord ops via the message tool (channel=disco rd).* | openclaw-bundled |
|
| 📦 | `discord` | **中文:** 通过 message 工具进行 Discord 操作<br><br>**English:** *Discord ops via the message tool (channel=disco rd).* | openclaw-bundled |
|
||||||
| 📦 | `eightctl` | **中文:** 控制 Eight Sleep pods(状态、温度、闹钟、日程)<br><br>**English:** *Control Eight Sleep pods (status, temperature, alarms, schedules).* | openclaw-bundled |
|
| 📦 | `eightctl` | **中文:** 控制 Eight Sleep pods(状态、温度、闹钟、日程)<br><br>**English:** *Control Eight Sleep pods (status, temperature, alarms, schedules).* | openclaw-bundled |
|
||||||
| 📦 | `✨ gemini` | **中文:** Gemini CLI for one-shot Q&A, summaries, and generation.<br><br>**English:** *Gemini CLI for one-shot Q&A, summaries, and generation.* | openclaw-bundled |
|
| 📦 | `✨ gemini` | **中文:** Gemini CLI for one-shot Q&A, summaries, and generation.<br><br>**English:** *Gemini CLI for one-shot Q&A, summaries, and generation.* | openclaw-bundled |
|
||||||
| 📦 | `gh-issues` | **中文:** 获取 GitHub issues,生成子代理实施修复并打开 PR,然后监控和处理 PR 审查评论<br><br>**English:** *Fetch GitHub issues, spawn sub-agents to implement fixes and open PRs, then monitor and address PR review comments. Usage: /gh- issues [owner/ repo] [-- label bug] [-- limit 5] [-- milestone v1. 0] [-- assignee @me] [--fork user/ repo] [-- watch] [-- interval 5] [- -reviews- only] [-- cron] [--dry- run] [--model glm-5] [-- notify- channel - 1002381931352]* | openclaw-bundled |
|
| 📦 | `gh-issues` | **中文:** 获取 GitHub issues,生成子代理实施修复并打开 PR,然后监控和处理 PR 审查评论<br><br>**English:** *Fetch GitHub issues, spawn sub-agents to implement fixes and open PRs, then monitor and address PR review comments. Usage: /gh- issues [owner/ repo] [-- label bug] [-- limit 5] [-- milestone v1. 0] [-- assignee @me] [--fork user/ repo] [-- watch] [-- interval 5] [- -reviews- only] [-- cron] [--dry- run] [--model glm-5] [-- notify- channel - 1002381931352]* | openclaw-bundled |
|
||||||
| 📦 | `gifgrep` | **中文:** Search GIF providers with CLI/TUI, download results, and extract stills/sheets.<br><br>**English:** *Search GIF providers with CLI/TUI, download results, and extract stills/sheets.* | openclaw-bundled |
|
| 📦 | `gifgrep` | **中文:** Search GIF providers with CLI/TUI, download results, and extract stills/sheets.<br><br>**English:** *Search GIF providers with CLI/TUI, download results, and extract stills/sheets.* | openclaw-bundled |
|
||||||
| 📦 | `github` | **中文:** GitHub operations via `gh` CLI: issues, PRs, CI runs, code review, API queries. Use when: (1) checking PR status or CI, (2) creating/ commenting on issues, (3) listing/ filtering PRs or issues, (4) viewing run logs. NOT for: complex web UI interactions requiring manual browser flows (use browser tooling when available), bulk operations across many repos (script with gh api), or when gh auth is not configured.<br><br>**English:** *GitHub operations via `gh` CLI: issues, PRs, CI runs, code review, API queries. Use when: (1) checking PR status or CI, (2) creating/ commenting on issues, (3) listing/ filtering PRs or issues, (4) viewing run logs. NOT for: complex web UI interactions requiring manual browser flows (use browser tooling when available), bulk operations across many repos (script with gh api), or when gh auth is not configured.* | openclaw-bundled |
|
| 📦 | `github` | **中文:** GitHub operations via `gh` CLI: issues, PRs, CI runs, code review, API queries. Use when: (1) checking PR status or CI, (2) creating/ commenting on issues, (3) listing/ filtering PRs or issues, (4) viewing run logs. NOT for: complex web UI interactions requiring manual browser flows (use browser tooling when available), bulk operations across many repos (script with gh api), or when gh auth is not configured.<br><br>**English:** *GitHub operations via `gh` CLI: issues, PRs, CI runs, code review, API queries. Use when: (1) checking PR status or CI, (2) creating/ commenting on issues, (3) listing/ filtering PRs or issues, (4) viewing run logs. NOT for: complex web UI interactions requiring manual browser flows (use browser tooling when available), bulk operations across many repos (script with gh api), or when gh auth is not configured.* | openclaw-bundled |
|
||||||
| 📦 | `goplaces` | **中文:** Query Google Places API (New) via the goplaces CLI for text search, place details, resolve, and reviews. Use for human- friendly place lookup or JSON output for scripts.<br><br>**English:** *Query Google Places API (New) via the goplaces CLI for text search, place details, resolve, and reviews. Use for human- friendly place lookup or JSON output for scripts.* | openclaw-bundled |
|
| 📦 | `goplaces` | **中文:** Query Google Places API (New) via the goplaces CLI for text search, place details, resolve, and reviews. Use for human- friendly place lookup or JSON output for scripts.<br><br>**English:** *Query Google Places API (New) via the goplaces CLI for text search, place details, resolve, and reviews. Use for human- friendly place lookup or JSON output for scripts.* | openclaw-bundled |
|
||||||
| 📦 | `himalaya` | **中文:** CLI to manage emails via IMAP/SMTP. Use `himalaya` to list, read, write, reply, forward, search, and organize emails from the terminal. Supports multiple accounts and message composition with MML (MIME Meta Language).<br><br>**English:** *CLI to manage emails via IMAP/SMTP. Use `himalaya` to list, read, write, reply, forward, search, and organize emails from the terminal. Supports multiple accounts and message composition with MML (MIME Meta Language).* | openclaw-bundled |
|
| 📦 | `himalaya` | **中文:** CLI to manage emails via IMAP/SMTP. Use `himalaya` to list, read, write, reply, forward, search, and organize emails from the terminal. Supports multiple accounts and message composition with MML (MIME Meta Language).<br><br>**English:** *CLI to manage emails via IMAP/SMTP. Use `himalaya` to list, read, write, reply, forward, search, and organize emails from the terminal. Supports multiple accounts and message composition with MML (MIME Meta Language).* | openclaw-bundled |
|
||||||
| 📦 | `imsg` | **中文:** iMessage/SMS CLI for listing chats, history, and sending messages via Messages.app.<br><br>**English:** *iMessage/SMS CLI for listing chats, history, and sending messages via Messages.app.* | openclaw-bundled |
|
| 📦 | `imsg` | **中文:** iMessage/SMS CLI for listing chats, history, and sending messages via Messages.app.<br><br>**English:** *iMessage/SMS CLI for listing chats, history, and sending messages via Messages.app.* | openclaw-bundled |
|
||||||
| 📦 | `mcporter` | **中文:** Use the mcporter CLI to list, configure, auth, and call MCP servers/tools directly (HTTP or stdio), including ad- hoc servers, config edits, and CLI/type generation.<br><br>**English:** *Use the mcporter CLI to list, configure, auth, and call MCP servers/tools directly (HTTP or stdio), including ad- hoc servers, config edits, and CLI/type generation.* | openclaw-bundled |
|
| 📦 | `mcporter` | **中文:** Use the mcporter CLI to list, configure, auth, and call MCP servers/tools directly (HTTP or stdio), including ad- hoc servers, config edits, and CLI/type generation.<br><br>**English:** *Use the mcporter CLI to list, configure, auth, and call MCP servers/tools directly (HTTP or stdio), including ad- hoc servers, config edits, and CLI/type generation.* | openclaw-bundled |
|
||||||
| 📦 | `model-usage` | **中文:** Use CodexBar CLI local cost usage to summarize per- model usage for Codex or Claude, including the current (most recent) model or a full model breakdown. Trigger when asked for model-level usage/cost data from codexbar, or when you need a scriptable per-model summary from codexbar cost JSON.<br><br>**English:** *Use CodexBar CLI local cost usage to summarize per- model usage for Codex or Claude, including the current (most recent) model or a full model breakdown. Trigger when asked for model-level usage/cost data from codexbar, or when you need a scriptable per-model summary from codexbar cost JSON.* | openclaw-bundled |
|
| 📦 | `model-usage` | **中文:** Use CodexBar CLI local cost usage to summarize per- model usage for Codex or Claude, including the current (most recent) model or a full model breakdown. Trigger when asked for model-level usage/cost data from codexbar, or when you need a scriptable per-model summary from codexbar cost JSON.<br><br>**English:** *Use CodexBar CLI local cost usage to summarize per- model usage for Codex or Claude, including the current (most recent) model or a full model breakdown. Trigger when asked for model-level usage/cost data from codexbar, or when you need a scriptable per-model summary from codexbar cost JSON.* | openclaw-bundled |
|
||||||
| 📦 | `nano-pdf` | **中文:** Edit PDFs with natural- language instructions using the nano-pdf CLI.<br><br>**English:** *Edit PDFs with natural- language instructions using the nano-pdf CLI.* | openclaw-bundled |
|
| 📦 | `nano-pdf` | **中文:** Edit PDFs with natural- language instructions using the nano-pdf CLI.<br><br>**English:** *Edit PDFs with natural- language instructions using the nano-pdf CLI.* | openclaw-bundled |
|
||||||
| 📦 | `notion` | **中文:** Notion API for creating and managing pages, databases, and blocks.<br><br>**English:** *Notion API for creating and managing pages, databases, and blocks.* | openclaw-bundled |
|
| 📦 | `notion` | **中文:** Notion API for creating and managing pages, databases, and blocks.<br><br>**English:** *Notion API for creating and managing pages, databases, and blocks.* | openclaw-bundled |
|
||||||
| 📦 | `obsidian` | **中文:** Work with Obsidian vaults (plain Markdown notes) and automate via obsidian-cli.<br><br>**English:** *Work with Obsidian vaults (plain Markdown notes) and automate via obsidian-cli.* | openclaw-bundled |
|
| 📦 | `obsidian` | **中文:** Work with Obsidian vaults (plain Markdown notes) and automate via obsidian-cli.<br><br>**English:** *Work with Obsidian vaults (plain Markdown notes) and automate via obsidian-cli.* | openclaw-bundled |
|
||||||
| 📦 | `openai-whisper-api` | **中文:** 通过 OpenAI Audio Transcriptions API (Whisper) 转录音频<br><br>**English:** *Transcribe audio via OpenAI Audio Transcriptions API (Whisper).* | openclaw-bundled |
|
| 📦 | `openai-whisper-api` | **中文:** 通过 OpenAI Audio Transcriptions API (Whisper) 转录音频<br><br>**English:** *Transcribe audio via OpenAI Audio Transcriptions API (Whisper).* | openclaw-bundled |
|
||||||
| 📦 | `openhue` | **中文:** 通过 OpenHue CLI 控制飞利浦 Hue 灯光和场景<br><br>**English:** *Control Philips Hue lights and scenes via the OpenHue CLI.* | openclaw-bundled |
|
| 📦 | `openhue` | **中文:** 通过 OpenHue CLI 控制飞利浦 Hue 灯光和场景<br><br>**English:** *Control Philips Hue lights and scenes via the OpenHue CLI.* | openclaw-bundled |
|
||||||
| 📦 | `oracle` | **中文:** 使用 oracle CLI 的最佳实践(prompt + 文件绑定、引擎、会话和文件附件模式)<br><br>**English:** *Best practices for using the oracle CLI (prompt + file bundling, engines, sessions, and file attachment patterns).* | openclaw-bundled |
|
| 📦 | `oracle` | **中文:** 使用 oracle CLI 的最佳实践(prompt + 文件绑定、引擎、会话和文件附件模式)<br><br>**English:** *Best practices for using the oracle CLI (prompt + file bundling, engines, sessions, and file attachment patterns).* | openclaw-bundled |
|
||||||
| 📦 | `ordercli` | **中文:** Foodora 专用 CLI,用于查看历史订单和当前订单状态<br><br>**English:** *Foodora-only CLI for checking past orders and active order status (Deliveroo WIP).* | openclaw-bundled |
|
| 📦 | `ordercli` | **中文:** Foodora 专用 CLI,用于查看历史订单和当前订单状态<br><br>**English:** *Foodora-only CLI for checking past orders and active order status (Deliveroo WIP).* | openclaw-bundled |
|
||||||
| 📦 | `peekaboo` | **中文:** 使用 Peekaboo CLI 捕获和自动化 macOS UI<br><br>**English:** *Capture and automate macOS UI with the Peekaboo CLI.* | openclaw-bundled |
|
| 📦 | `peekaboo` | **中文:** 使用 Peekaboo CLI 捕获和自动化 macOS UI<br><br>**English:** *Capture and automate macOS UI with the Peekaboo CLI.* | openclaw-bundled |
|
||||||
| 📦 | `songsee` | **中文:** 使用 songsee CLI 从音频生成频谱图和特征面板可视化<br><br>**English:** *Generate spectrograms and feature- panel visualizations from audio with the songsee CLI.* | openclaw-bundled |
|
| 📦 | `songsee` | **中文:** 使用 songsee CLI 从音频生成频谱图和特征面板可视化<br><br>**English:** *Generate spectrograms and feature- panel visualizations from audio with the songsee CLI.* | openclaw-bundled |
|
||||||
| 📦 | `sonoscli` | **中文:** 控制 Sonos 扬声器(发现/状态/播放/音量/分组)<br><br>**English:** *Control Sonos speakers (discover/ status/play/ volume/group).* | openclaw-bundled |
|
| 📦 | `sonoscli` | **中文:** 控制 Sonos 扬声器(发现/状态/播放/音量/分组)<br><br>**English:** *Control Sonos speakers (discover/ status/play/ volume/group).* | openclaw-bundled |
|
||||||
| 📦 | `spotify-player` | **中文:** 通过 spogo(首选)或 spotify_player 终端控制 Spotify 播放/搜索<br><br>**English:** *Terminal Spotify playback/ search via spogo (preferred) or spotify_ player.* | openclaw-bundled |
|
| 📦 | `spotify-player` | **中文:** 通过 spogo(首选)或 spotify_player 终端控制 Spotify 播放/搜索<br><br>**English:** *Terminal Spotify playback/ search via spogo (preferred) or spotify_ player.* | openclaw-bundled |
|
||||||
| 📦 | `✅ things-mac` | **中文:** Manage Things 3 via the `things` CLI on macOS (add/ update projects+todos via URL scheme; read/ search/list from the local Things database). Use when a user asks OpenClaw to add a task to Things, list inbox/today/ upcoming, search tasks, or inspect projects/ areas/tags.<br><br>**English:** *Manage Things 3 via the `things` CLI on macOS (add/ update projects+todos via URL scheme; read/ search/list from the local Things database). Use when a user asks OpenClaw to add a task to Things, list inbox/today/ upcoming, search tasks, or inspect projects/ areas/tags.* | openclaw-bundled |
|
| 📦 | `✅ things-mac` | **中文:** Manage Things 3 via the `things` CLI on macOS (add/ update projects+todos via URL scheme; read/ search/list from the local Things database). Use when a user asks OpenClaw to add a task to Things, list inbox/today/ upcoming, search tasks, or inspect projects/ areas/tags.<br><br>**English:** *Manage Things 3 via the `things` CLI on macOS (add/ update projects+todos via URL scheme; read/ search/list from the local Things database). Use when a user asks OpenClaw to add a task to Things, list inbox/today/ upcoming, search tasks, or inspect projects/ areas/tags.* | openclaw-bundled |
|
||||||
| 📦 | `trello` | **中文:** 通过 Trello REST API 管理 Trello 看板、列表和卡片<br><br>**English:** *Manage Trello boards, lists, and cards via the Trello REST API.* | openclaw-bundled |
|
| 📦 | `trello` | **中文:** 通过 Trello REST API 管理 Trello 看板、列表和卡片<br><br>**English:** *Manage Trello boards, lists, and cards via the Trello REST API.* | openclaw-bundled |
|
||||||
| 📦 | `voice-call` | **中文:** Start voice calls via the OpenClaw plugin.<br><br>**English:** *Start voice calls via the OpenClaw plugin.* | openclaw-bundled |
|
| 📦 | `voice-call` | **中文:** Start voice calls via the OpenClaw plugin.<br><br>**English:** *Start voice calls via the OpenClaw plugin.* | openclaw-bundled |
|
||||||
| 📦 | `wacli` | **中文:** 发送 WhatsApp 消息或通过 wacli CLI 搜索/同步 WhatsApp 历史记录<br><br>**English:** *Send WhatsApp messages to other people or search/ sync WhatsApp history via the wacli CLI (not for normal user chats).* | openclaw-bundled |
|
| 📦 | `wacli` | **中文:** 发送 WhatsApp 消息或通过 wacli CLI 搜索/同步 WhatsApp 历史记录<br><br>**English:** *Send WhatsApp messages to other people or search/ sync WhatsApp history via the wacli CLI (not for normal user chats).* | openclaw-bundled |
|
||||||
| 📦 | `xurl` | **中文:** 用于向 X (Twitter) API 发出认证请求的 CLI 工具<br><br>**English:** *A CLI tool for making authenticated requests to the X (Twitter) API. Use this skill when you need to post tweets, reply, quote, search, read posts, manage followers, send DMs, upload media, or interact with any X API v2 endpoint.* | openclaw-bundled |
|
| 📦 | `xurl` | **中文:** 用于向 X (Twitter) API 发出认证请求的 CLI 工具<br><br>**English:** *A CLI tool for making authenticated requests to the X (Twitter) API. Use this skill when you need to post tweets, reply, quote, search, read posts, manage followers, send DMs, upload media, or interact with any X API v2 endpoint.* | openclaw-bundled |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 统计
|
## 统计
|
||||||
|
|
||||||
| 状态 | 数量 |
|
| 状态 | 数量 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| ✅ Ready | 62 |
|
| ✅ Ready | 62 |
|
||||||
| △ Needs Setup | 32 |
|
| △ Needs Setup | 32 |
|
||||||
| **总计** | **94** |
|
| **总计** | **94** |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
*此表由星枢自动生成*
|
*此表由星枢自动生成*
|
||||||
*最后更新:2026-04-18 18:42*
|
*最后更新:2026-04-18 18:42*
|
||||||
Reference in New Issue
Block a user