Files
nexus/Project/fonrey/UI_DESIGN/客源管理/客源详情_UI.md
2026-04-26 14:03:16 +08:00

20 KiB
Raw Blame History

客源详情页 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-bbg-primary-800,与 UI_SYSTEM v1.2 对齐。
  • 修正主内容区 paddingpt-14 py-4pt-[72px] py-5
  • 修正 Section 锚点导航 sticky 位置:top-20top-16
  • 修正右侧面板 stickytop-20top-16,并增加 max-h-[calc(100vh-80px)] overflow-y-auto
  • 修正客源概览卡片顶部标识区:bg-primary-600(非 bg-primary-800)。
  • 补充客源解读 Section 实际字段和数据展示规范。
  • 补充 Alpine.js clientDetailPage() 状态机完整定义。

1.3 URL 与入口

  • 详情页主路由:/clients/<client_id>/
  • 入口:客源列表点击姓名或详情操作。
  • 所有左侧 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,标签 roundedrounded-full
  • 焦点环统一:focus-visible:ring-2 focus-visible:ring-primary-600/40

2.2 组件与图标

  • 图标库Heroicons v2。
    • 默认Outline 24pxw-5 h-5
    • 高密Mini 16pxw-4 h-4
  • 禁止独立 CSS 文件;样式全部使用 Tailwind utility class。

2.3 页面骨架

  • Topbarfixed top-0 left-0 right-0 h-14 z-20 bg-primary-800 flex items-center justify-between
  • Sidebarfixed 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 主体布局骨架

<main class="ml-60 pt-[72px] min-h-screen bg-neutral-50 px-6 py-5">
  <div class="mx-auto max-w-[1600px] space-y-4">
    <!-- 面包屑 + 页头 -->
    <div class="flex items-start justify-between">
      <div>
        <nav class="flex items-center gap-1 text-xs text-neutral-500 mb-1" aria-label="面包屑">...</nav>
        <h1 class="text-xl font-semibold text-neutral-800">客源详情</h1>
        <p class="text-xs text-neutral-500 mt-0.5">按 Section 连续展示,点击导航锚点快速定位</p>
      </div>
    </div>

    <div class="grid grid-cols-12 gap-6 items-start">
      <section class="col-span-8 min-w-0 space-y-6">
        <!-- Anchor Nav + All Sections -->
      </section>
      <aside class="col-span-4 min-w-0 space-y-3 sticky top-16 max-h-[calc(100vh-80px)] overflow-y-auto">
        <!-- Right panels -->
      </aside>
    </div>
  </div>
</main>

4. Topbar

结构同 UI_SYSTEM §5.2,客源详情页激活「客源」导航项。

<header class="fixed top-0 left-0 right-0 h-14 z-20 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 text-sm font-semibold">F</div>
    <span class="text-base font-semibold text-white">Fonrey</span>
  </div>
  <!-- 中区主导航nav flex-1无搜索框 -->
  <nav class="flex items-center gap-1 flex-1 px-2" aria-label="主导航">
    <a class="px-3 py-1.5 text-sm rounded-md text-primary-100 hover:bg-primary-700 hover:text-white">主页</a>
    <a class="px-3 py-1.5 text-sm rounded-md bg-primary-600 text-white font-medium">客源</a><!-- 激活态 -->
    <!-- …其余项 -->
  </nav>
  <!-- 右区 -->
  <div class="flex items-center gap-1 px-4 shrink-0">
    <button class="p-1.5 text-primary-200 hover:bg-primary-700 hover:text-white rounded-md" aria-label="消息"><!-- BellIcon --></button>
    <div class="flex items-center gap-2 pl-3 ml-1 border-l border-primary-700">
      <div class="w-8 h-8 rounded-full bg-primary-600 text-white flex items-center justify-center text-sm font-semibold"></div>
      <span class="text-sm font-medium text-primary-100">魏深</span>
    </div>
  </div>
</header>

注:详情页 Topbar 右区只有消息通知 + 头像姓名,省略设置按钮(与 preview.html 保持一致)。


5. 左侧主内容区(全量 Section + 锚点导航)

5.1 Section 导航(替代 Tab

5.1.1 交互定义

  • 导航仅用于锚点跳转,不切换内容,不销毁 DOM。
  • 点击导航项:scrollToSection(id) 平滑滚动到目标 Section。
  • 当前高亮:IntersectionObserverrootMargin -140px 0px -55% 0pxthreshold 0.01)驱动 activeSection
  • 导航条 stickysticky 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 数据结构

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 代码骨架

<div class="bg-white border border-neutral-200 rounded-lg px-3 py-2 sticky top-16 z-30 shadow-xs">
  <nav class="flex items-center gap-1 overflow-x-auto whitespace-nowrap" aria-label="详情分区导航">
    <template x-for="item in navItems" :key="item.id">
      <a :href="'#' + item.id"
         @click.prevent="scrollToSection(item.id)"
         :aria-current="activeSection === item.id ? 'true' : 'false'"
         :class="activeSection === item.id
           ? 'bg-primary-50 text-primary-700 font-medium'
           : 'text-neutral-600 hover:bg-neutral-100 hover:text-neutral-800'"
         class="px-3 py-1.5 text-sm rounded-md focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-600/40"
         x-text="item.label"></a>
    </template>
  </nav>
</div>

5.2 Section 1需求信息P0

  • IDsection-requirementsclass 含 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
  • 字段项:<dt class="text-xs text-neutral-500"> + <dd class="text-sm text-neutral-900">,数字型加 tabular-nums
  • 备注字段:col-span-3(跨满三列)
  • 空值:统一显示 -

字段列表总价、面积、居室、装修、朝向、楼层、楼龄、意向商圈、意向小区、交通情况、备注col-span-3


5.3 Section 2跟进记录P0

  • IDsection-followclass 含 section-anchor scroll-mt-24
  • 容器:bg-white rounded-lg border border-neutral-200 p-4 space-y-4
  • Header 右侧「写跟进」Primary 按钮,含铅笔图标 w-4 h-4,点击触发写跟进 DrawerdrawerOpen=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

  • IDsection-viewingsclass 含 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

  • IDsection-insightsclass 含 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

  • IDsection-matchesclass 含 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-4sticky 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

  • 求购 Badgeinline-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
  • dttext-xs text-neutral-500ddtext-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
  • Headerflex items-center justify-between px-5 py-4 border-b border-neutral-200,关闭按钮 p-1 text-neutral-500 hover:bg-neutral-100 rounded-md
  • Footerflex 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-fulltranslate-x-0
  • 字段跟进方式select/ 跟进内容textarea至少 6 字)/ 跟进时间input/ 附件file/ 是否开放给同事查看checkbox默认勾选

8. Alpine.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-60Drawer 遮罩 z-50Drawer 面板 z-60
  9. 全量检查 class 是否符合 token颜色、圆角、焦点环、表格密度

12. 验收标准

  • Topbar 为深青绿色 bg-primary-800,与内容区有明显层次区分。
  • 左侧主区无 Tab 切换行为,所有内容可连续滚动查看。
  • 点击 Section 导航仅发生锚点滚动,不触发内容隐藏/显示。
  • 锚点导航随滚动自动高亮当前 Section。
  • 页面视觉与 客源详情_静态原型.html 一致:层级、卡片密度、按钮和输入风格一致。
  • 颜色、字号、圆角、焦点环全部使用系统 token 与规范类名。
  • 关键路径写跟进、改状态、查看号码可在单页完成并有明确反馈loading/toast/error