# 客源详情页 UI 设计文档 > **版本**:v1.2 · **日期**:2026-04-25 > **依赖规范**:`Project/fonrey/UI_SYSTEM/UI_SYSTEM.md` v1.2、`Project/fonrey/UI_SYSTEM/组件规范设计.md` > **视觉参考**:`Project/fonrey/UI_SYSTEM/preview.html`(页面骨架、卡片层级、工具栏密度) > **PRD 来源**:`Project/fonrey/PRD/客源管理/客源管理模块PRD.md` §5.7 私客详情页 > **静态原型**:`Project/fonrey/客源详情_静态原型.html`(以此为视觉真相来源) --- ## 1. 模块概述 ### 1.1 页面目标 - 在一个页面内完成私客详情查看、跟进、带看、状态流转、联系人管理、相关员工查看。 - 桌面优先(`>=1280px`),不做移动端适配。 - 技术栈固定:Tailwind CSS + HTMX + Alpine.js + Django Template。 ### 1.2 本版关键改动(相对 v1.1) - 修正 Topbar 配色:`bg-white border-b` → `bg-primary-800`,与 UI_SYSTEM v1.2 对齐。 - 修正主内容区 padding:`pt-14 py-4` → `pt-[72px] py-5`。 - 修正 Section 锚点导航 sticky 位置:`top-20` → `top-16`。 - 修正右侧面板 sticky:`top-20` → `top-16`,并增加 `max-h-[calc(100vh-80px)] overflow-y-auto`。 - 修正客源概览卡片顶部标识区:`bg-primary-600`(非 `bg-primary-800`)。 - 补充客源解读 Section 实际字段和数据展示规范。 - 补充 Alpine.js `clientDetailPage()` 状态机完整定义。 ### 1.3 URL 与入口 - 详情页主路由:`/clients//` - 入口:客源列表点击姓名或详情操作。 - 所有左侧 Section 默认随页面 SSR 输出,首屏即可看到首个 Section,向下滚动查看其余 Section。 --- ## 2. 设计基线(必须遵守) ### 2.1 视觉与 Token - 主色:`primary-600`,禁用硬编码 Hex。 - Topbar 背景:`bg-primary-800`(深青绿,区别于内容区)。 - 页面底色:`bg-neutral-50`,内容卡片:`bg-white border border-neutral-200 rounded-lg`。 - 正文字号:`text-sm`;辅助:`text-xs text-neutral-500`;关键数字加 `tabular-nums`。 - 圆角:卡片 `rounded-lg`,输入/按钮 `rounded-md`,标签 `rounded` 或 `rounded-full`。 - 焦点环统一:`focus-visible:ring-2 focus-visible:ring-primary-600/40`。 ### 2.2 组件与图标 - 图标库:Heroicons v2。 - 默认:Outline 24px(`w-5 h-5`) - 高密:Mini 16px(`w-4 h-4`) - 禁止独立 CSS 文件;样式全部使用 Tailwind utility class。 ### 2.3 页面骨架 - Topbar:`fixed top-0 left-0 right-0 h-14 z-20 bg-primary-800 flex items-center justify-between` - Sidebar:`fixed left-0 top-14 h-[calc(100vh-56px)] w-60 z-20 border-r border-neutral-200 bg-white` - 主内容区:`ml-60 pt-[72px] min-h-screen bg-neutral-50 px-6 py-5` - 区块垂直节奏:`space-y-4`(外层)、`space-y-6`(左侧 Section 间距) --- ## 3. 页面信息架构 ### 3.1 整体结构 ``` Topbar (h-14, bg-primary-800) -> Sidebar (w-60, fixed left) -> Content Area (ml-60, pt-[72px], bg-neutral-50, px-6 py-5) -> Breadcrumb + Page Title -> Main Grid (12 cols, gap-6) - Left (col-span-8) - Sticky Section Anchor Nav (top-16, z-30) - Section 1: 需求信息 - Section 2: 跟进记录 - Section 3: 带看记录 - Section 4: 客源解读 - Section 5: 二手配房 - Right Sidebar (col-span-4, sticky top-16) - 客源信息概览(含快捷操作) - 联系人 - 相关员工 ``` ### 3.2 主体布局骨架 ```html

客源详情

按 Section 连续展示,点击导航锚点快速定位

``` --- ## 4. Topbar 结构同 UI_SYSTEM §5.2,客源详情页激活「客源」导航项。 ```html
F
Fonrey
魏深
``` > 注:详情页 Topbar 右区只有消息通知 + 头像姓名,省略设置按钮(与 preview.html 保持一致)。 --- ## 5. 左侧主内容区(全量 Section + 锚点导航) ### 5.1 Section 导航(替代 Tab) #### 5.1.1 交互定义 - 导航仅用于锚点跳转,不切换内容,不销毁 DOM。 - 点击导航项:`scrollToSection(id)` 平滑滚动到目标 Section。 - 当前高亮:`IntersectionObserver`(rootMargin `-140px 0px -55% 0px`,threshold `0.01`)驱动 `activeSection`。 - 导航条 sticky:`sticky top-16 z-30`,滚动时固定在左栏顶部。 #### 5.1.2 导航样式 - 容器:`bg-white border border-neutral-200 rounded-lg px-3 py-2 sticky top-16 z-30 shadow-xs` - 项默认:`px-3 py-1.5 text-sm rounded-md text-neutral-600 hover:bg-neutral-100 hover:text-neutral-800` - 项激活:`bg-primary-50 text-primary-700 font-medium` - 焦点:`focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-600/40` - `aria-current="true"` 标注当前激活项 #### 5.1.3 Alpine.js 数据结构 ```js navItems: [ { id: 'section-requirements', label: '需求信息' }, { id: 'section-follow', label: '跟进记录' }, { id: 'section-viewings', label: '带看记录' }, { id: 'section-insights', label: '客源解读' }, { id: 'section-matches', label: '二手配房' } ], activeSection: 'section-requirements' ``` #### 5.1.4 代码骨架 ```html
``` --- ### 5.2 Section 1:需求信息(P0) - ID:`section-requirements`,class 含 `section-anchor scroll-mt-24` - 容器:`bg-white rounded-lg border border-neutral-200 p-4 space-y-4` - Header:标题 `text-base font-semibold text-neutral-800` + 右侧文字链「编辑」`text-sm text-primary-600 hover:text-primary-700 hover:underline underline-offset-2` - 字段网格:`grid grid-cols-3 gap-x-6 gap-y-4` - 字段项:`
` + `
`,数字型加 `tabular-nums` - 备注字段:`col-span-3`(跨满三列) - 空值:统一显示 `-` 字段列表:总价、面积、居室、装修、朝向、楼层、楼龄、意向商圈、意向小区、交通情况、备注(col-span-3) --- ### 5.3 Section 2:跟进记录(P0) - ID:`section-follow`,class 含 `section-anchor scroll-mt-24` - 容器:`bg-white rounded-lg border border-neutral-200 p-4 space-y-4` - Header 右侧:「写跟进」Primary 按钮,含铅笔图标 `w-4 h-4`,点击触发写跟进 Drawer(`drawerOpen=true`) **类型筛选条**(`flex items-center gap-2 flex-wrap`): - 激活项:`px-3 py-1 text-xs rounded-full bg-primary-600 text-white` - 默认项:`px-3 py-1 text-xs rounded-full bg-neutral-100 text-neutral-600 hover:bg-neutral-200` - 选项:全部 / 写入跟进 / 敏感信息跟进 / 修改跟进 / 其他跟进 **日期筛选栏**:`border border-neutral-200 rounded-md p-3 bg-neutral-50 flex items-center gap-3 flex-wrap text-xs`,含开始/结束日期输入框、有录音/有图片 checkbox。 **时间线**:`relative border-l-2 border-neutral-200 ml-3 space-y-4 pl-5` - 普通记录:圆点 `bg-primary-600`,卡片 `rounded-md border border-neutral-200 p-3 bg-white space-y-1` - 敏感记录:圆点 `bg-warning-600`,卡片 `rounded-md border border-warning-600/20 bg-warning-50 p-3 space-y-1` - 类型标签:`inline-flex items-center px-2 py-0.5 rounded-full bg-info-50 text-info-600 font-medium`(电话),`bg-warning-50 text-warning-600`(敏感查看) **底部**:「查看全部跟进」文字链,`text-sm text-primary-600 hover:underline underline-offset-2`。 --- ### 5.4 Section 3:带看记录(P0) - ID:`section-viewings`,class 含 `section-anchor scroll-mt-24` - Header 右侧:两个 Secondary 按钮(`新增预约` / `新增带看`) - 筛选栏:同跟进记录日期筛选样式,含「归属人带看」「其他人带看」checkbox - 时间线结构同跟进记录,房源名称用 `text-primary-600 hover:underline` 链接 - 带看次数标签:`inline-flex items-center px-2 py-0.5 rounded-full bg-primary-50 text-primary-700 font-medium`(如「一看」) --- ### 5.5 Section 4:客源解读(P1) - ID:`section-insights`,class 含 `section-anchor scroll-mt-24` - Header 右侧:更新时间文字 `text-xs text-neutral-500` **行为指标行**(`grid grid-cols-3 gap-3`): - 卡片:`border border-neutral-200 rounded-md p-3 bg-white` - 标签 `text-xs text-neutral-500`,值 `text-xl font-semibold text-neutral-900 tabular-nums` - 字段:活跃行为 / 工作日活跃 / 周末活跃 **偏好占比行**(`grid grid-cols-3 gap-3`): - 卡片:`border border-neutral-200 rounded-md p-3 text-center` - 标签 `text-xs text-neutral-500`,占比值 `text-2xl font-semibold text-primary-600 tabular-nums` - 字段:价格偏好 / 户型偏好 / 面积偏好 --- ### 5.6 Section 5:二手配房(P1) - ID:`section-matches`,class 含 `section-anchor scroll-mt-24` - Header 右侧:「批量分享」Secondary 按钮 **分组标题**:`text-sm font-semibold text-neutral-700`(如「优质户型」) **房源卡片**(`border border-neutral-200 rounded-md p-3`): - 缩略图:`w-20 h-14 rounded bg-neutral-100`(占位) - 房源名:`text-sm font-medium text-primary-600 hover:underline` - 描述:`text-xs text-neutral-500`(户型·面积·区域) - 标签行:`inline-flex items-center px-1.5 py-0.5 text-[11px] rounded`,朝向 `bg-warning-50 text-warning-600`,私盘 `bg-info-50 text-info-600` - 价格:`text-sm font-medium text-neutral-900 tabular-nums`,降价说明 `text-xs font-normal text-neutral-500` --- ## 6. 右侧信息面板 右侧 `col-span-4`,`sticky top-16 max-h-[calc(100vh-80px)] overflow-y-auto space-y-3`。 ### 6.1 客源信息概览(P0) 容器:`bg-white rounded-lg border border-neutral-200 overflow-hidden` **顶部标识区**:`bg-primary-600 px-4 py-3` - 求购 Badge:`inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-white/20 text-white` - 客户姓名:`text-sm font-semibold text-white truncate` - 带看进度副文字:`text-xs text-white/80 mt-0.5` **标签行**(`flex items-center gap-1.5 flex-wrap`): - 私客:`bg-neutral-100 text-neutral-600` - 带看进度(如「一看」):`bg-primary-50 text-primary-700` - 等级(如「C(一般)」):`bg-warning-50 text-warning-600` - 统一尺寸:`inline-flex items-center px-1.5 py-0.5 text-xs rounded` - 右侧文字链「编辑」`text-sm text-primary-600 hover:text-primary-700 hover:underline underline-offset-2` **字段列表**(`dl space-y-1.5`): - 每行:`grid grid-cols-[72px_1fr] gap-2` - `dt`:`text-xs text-neutral-500`;`dd`:`text-xs text-right text-neutral-800` - 数字/日期加 `tabular-nums`,编号加 `font-mono` - 字段:最近跟进 / 客户编号 / 委托日期 / 需求类型 / 房源用途 / 客户来源 ### 6.2 快捷操作区(P0) **三主按钮**(`grid grid-cols-3 gap-2`): - 样式:`flex flex-col items-center gap-1 py-2 text-xs font-medium bg-primary-600 text-white rounded-md hover:bg-primary-700` - 按钮:打电话 / 写跟进(触发 `drawerOpen=true`)/ 报备/常看 **操作网格**(`grid grid-cols-2 gap-1`): - 默认:`px-2 py-2 text-xs text-left rounded-md text-neutral-600 hover:bg-neutral-100` - 危险项(转无效):`text-danger-600 hover:bg-danger-50` - 按钮:收藏 / 不置顶 / 改等级(`modal='grade'`)/ 改状态(`modal='status'`)/ 转公客 / 转成交(`modal='deal'`)/ 转无效 / 编辑客源(`modal='edit'`) ### 6.3 联系人面板(P0) 容器:`bg-white rounded-lg border border-neutral-200 p-3` - Header 操作:`查看号码` / `新增联系人`,`text-xs text-primary-600 hover:underline space-x-2` - 姓名:`text-sm font-medium text-neutral-900` - 号码(脱敏):`text-xs text-neutral-600 tabular-nums` - 拨打统计:`text-xs text-neutral-500` ### 6.4 相关员工面板(P0) 容器:`bg-white rounded-lg border border-neutral-200 p-3` - Header 操作:`编辑`,`text-xs text-primary-600 hover:underline` - 每个员工块(`space-y-3`): - 角色标签:`text-xs font-medium text-neutral-700`(如「【首录人】」) - 姓名:`text-sm text-neutral-900` - 参与时间:`text-xs text-neutral-500 tabular-nums` --- ## 7. 弹窗与抽屉 ### 7.1 统一规范 - 遮罩:`fixed inset-0 z-50 bg-neutral-900/40`,点击关闭 - 弹窗层:`z-60 fixed inset-0 flex items-center justify-center p-4 pointer-events-none` - 弹窗体:`pointer-events-auto bg-white rounded-xl shadow-lg border border-neutral-200 flex flex-col` - Header:`flex items-center justify-between px-5 py-4 border-b border-neutral-200`,关闭按钮 `p-1 text-neutral-500 hover:bg-neutral-100 rounded-md` - Footer:`flex items-center justify-end gap-2 px-5 py-3 border-t border-neutral-200 bg-neutral-50`,取消 Secondary + 确认 Primary ### 7.2 弹窗清单 | 弹窗 | 触发 | 宽度 | 内容要点 | |---|---|---|---| | 改等级 | `modal='grade'` | `max-w-sm` | 原等级展示 + 下拉选择新等级 | | 改状态 | `modal='status'` | `max-w-md` | 原状态展示 + 下拉新状态 + 理由 textarea | | 转成交 | `modal='deal'` | `max-w-lg` | 状态/房源类型下拉 + 选择成交房源按钮 | | 编辑基础信息 | `modal='edit'` | `max-w-2xl max-h-[85vh] overflow-y-auto` | 需求类型/来源/用途/付款方式/证件号码 | ### 7.3 写跟进 Drawer - 触发:`drawerOpen=true` - 宽度:`w-[480px]`,从右侧滑入(`translate-x-full` → `translate-x-0`) - 字段:跟进方式(select)/ 跟进内容(textarea,至少 6 字)/ 跟进时间(input)/ 附件(file)/ 是否开放给同事查看(checkbox,默认勾选) --- ## 8. Alpine.js 状态机 ```js function clientDetailPage() { return { modal: null, // 'grade' | 'status' | 'deal' | 'edit' | null drawerOpen: false, navItems: [ { id: 'section-requirements', label: '需求信息' }, { id: 'section-follow', label: '跟进记录' }, { id: 'section-viewings', label: '带看记录' }, { id: 'section-insights', label: '客源解读' }, { id: 'section-matches', label: '二手配房' } ], activeSection: 'section-requirements', observer: null, scrollToSection(id) { const el = document.getElementById(id) if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' }) }, init() { const sections = Array.from(document.querySelectorAll('.section-anchor')) this.observer = new IntersectionObserver((entries) => { entries.forEach((entry) => { if (entry.isIntersecting) this.activeSection = entry.target.id }) }, { root: null, rootMargin: '-140px 0px -55% 0px', threshold: 0.01 }) sections.forEach((s) => this.observer.observe(s)) } } } ``` --- ## 9. HTMX 交互规范 ### 9.1 原则 - 页面首次渲染直接 SSR 输出完整 5 个 Section。 - 每个 Section 内部筛选/分页独立请求,仅刷新本 Section 容器。 - 弹窗/Drawer 提交后定向刷新对应 Section 或右侧面板。 ### 9.2 请求映射 | 操作 | URL | Target | Swap | |---|---|---|---| | 跟进类型筛选 | `/clients/{id}/follow-logs/partial` | `#follow-section-body` | `innerHTML` | | 跟进加载更多 | `/clients/{id}/follow-logs/partial?page=N` | `#follow-timeline-list` | `beforeend` | | 带看筛选 | `/clients/{id}/viewings/partial` | `#viewings-section-body` | `innerHTML` | | 客源解读刷新 | `/clients/{id}/insights/partial` | `#insights-section-body` | `innerHTML` | | 配房筛选/分页 | `/clients/{id}/matches/partial` | `#matches-section-body` | `innerHTML` | | 查看号码 | `/clients/{id}/contacts/{cid}/reveal-phone/` | `#phone-{cid}` | `innerHTML` | --- ## 10. 状态与可用性规范 ### 10.1 Loading - 每个 Section 内独立 `htmx-indicator` 骨架。 - 按钮提交中显示 Spinner + 进行时文案(如 `保存中...`)。 ### 10.2 Empty - 跟进为空:`暂无跟进` - 带看为空:`暂无带看记录` + `新增带看` 按钮 - 配房为空:`暂无匹配房源` ### 10.3 Error - `htmx:responseError` 保留旧内容 + 右下角 Error Toast。 ### 10.4 A11y - 可点击项支持键盘 Tab 聚焦。 - 所有交互控件保留 `focus-visible` 样式。 - 锚点导航当前项 `aria-current="true"`。 - Modal 打开时 `role="dialog"` + `aria-modal="true"`。 --- ## 11. 工程落地清单 1. `body` 挂载 `x-data="clientDetailPage()"`,包含完整状态机(见第 8 节)。 2. Topbar 使用 `bg-primary-800`,激活项 `bg-primary-600 text-white`。 3. 主内容区:`ml-60 pt-[72px] min-h-screen bg-neutral-50 px-6 py-5`。 4. Section 锚点导航 sticky `top-16 z-30`;右侧面板 sticky `top-16 max-h-[calc(100vh-80px)] overflow-y-auto`。 5. 所有 Section 添加 class `section-anchor scroll-mt-24`,供 IntersectionObserver 监听。 6. 右侧客源概览顶部标识区用 `bg-primary-600`(非 `bg-primary-800`)。 7. 每个 Section 设置独立 HTMX target,避免全页刷新。 8. Modal 遮罩 `z-50`,弹窗体 `z-60`;Drawer 遮罩 `z-50`,Drawer 面板 `z-60`。 9. 全量检查 class 是否符合 token(颜色、圆角、焦点环、表格密度)。 --- ## 12. 验收标准 - Topbar 为深青绿色 `bg-primary-800`,与内容区有明显层次区分。 - 左侧主区无 Tab 切换行为,所有内容可连续滚动查看。 - 点击 Section 导航仅发生锚点滚动,不触发内容隐藏/显示。 - 锚点导航随滚动自动高亮当前 Section。 - 页面视觉与 `客源详情_静态原型.html` 一致:层级、卡片密度、按钮和输入风格一致。 - 颜色、字号、圆角、焦点环全部使用系统 token 与规范类名。 - 关键路径(写跟进、改状态、查看号码)可在单页完成并有明确反馈(loading/toast/error)。