1205 lines
79 KiB
HTML
1205 lines
79 KiB
HTML
<!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 defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></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'},
|
||
},
|
||
boxShadow: {
|
||
xs:'0 1px 2px rgba(15,23,42,0.04)',
|
||
},
|
||
fontFamily: {
|
||
sans:['Inter','PingFang SC','Microsoft YaHei','sans-serif'],
|
||
mono:['JetBrains Mono','SFMono-Regular','Menlo','monospace'],
|
||
},
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||
<style>
|
||
body { font-family: 'Inter','PingFang SC','Microsoft YaHei',sans-serif; }
|
||
.tabular-nums { font-variant-numeric: tabular-nums; }
|
||
::-webkit-scrollbar{width:6px;height:6px}
|
||
::-webkit-scrollbar-thumb{background:#CBD5E1;border-radius:4px}
|
||
::-webkit-scrollbar-thumb:hover{background:#94A3B8}
|
||
[x-cloak]{display:none!important}
|
||
</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-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>
|
||
<!-- 中区:主导航 + 搜索 -->
|
||
<div class="flex items-center gap-4 flex-1 px-2">
|
||
<nav class="flex items-center gap-1 text-sm">
|
||
<a class="px-3 py-1.5 rounded-md text-primary-100 hover:bg-primary-700 hover:text-white cursor-pointer">工作台</a>
|
||
<a class="px-3 py-1.5 rounded-md text-primary-100 hover:bg-primary-700 hover:text-white cursor-pointer">房源</a>
|
||
<a class="px-3 py-1.5 rounded-md bg-primary-600 text-white font-medium cursor-pointer">客源</a>
|
||
<a class="px-3 py-1.5 rounded-md text-primary-100 hover:bg-primary-700 hover:text-white cursor-pointer">营销</a>
|
||
<a class="px-3 py-1.5 rounded-md text-primary-100 hover:bg-primary-700 hover:text-white cursor-pointer">交易</a>
|
||
<a class="px-3 py-1.5 rounded-md text-primary-100 hover:bg-primary-700 hover:text-white cursor-pointer">数据</a>
|
||
<a class="px-3 py-1.5 rounded-md text-primary-100 hover:bg-primary-700 hover:text-white cursor-pointer">人事</a>
|
||
<a class="px-3 py-1.5 rounded-md text-primary-100 hover:bg-primary-700 hover:text-white cursor-pointer">系统</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">
|
||
</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">
|
||
<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">
|
||
<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>
|
||
</header>
|
||
|
||
<!-- ============ 主容器 ============ -->
|
||
<div class="flex pt-14">
|
||
|
||
<!-- 侧边栏 -->
|
||
<aside class="w-56 shrink-0 border-r border-neutral-200 bg-white min-h-[calc(100vh-3.5rem)] fixed left-0 top-14">
|
||
<nav class="p-3 space-y-0.5 text-sm">
|
||
<div class="px-2 pt-2 pb-1 text-xs font-medium text-neutral-500 uppercase tracking-wide">客源管理</div>
|
||
<a class="flex items-center gap-2 px-2 py-1.5 rounded-md bg-primary-50 text-primary-700 font-medium cursor-pointer">
|
||
<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="M15 19.128a9.38 9.38 0 0 0 2.625.372 9.337 9.337 0 0 0 4.121-.952 4.125 4.125 0 0 0-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 0 1 8.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0 1 11.964-3.07M12 6.375a3.375 3.375 0 1 1-6.75 0 3.375 3.375 0 0 1 6.75 0Zm8.25 2.25a2.625 2.625 0 1 1-5.25 0 2.625 2.625 0 0 1 5.25 0Z"/></svg>
|
||
私客列表
|
||
<span class="ml-auto text-xs text-neutral-500 tabular-nums">1,024</span>
|
||
</a>
|
||
<a class="flex items-center gap-2 px-2 py-1.5 rounded-md text-neutral-700 hover:bg-neutral-100 cursor-pointer">
|
||
<svg class="w-4 h-4 text-neutral-400" fill="none" stroke="currentColor" stroke-width="1.8" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M18 18.72a9.094 9.094 0 0 0 3.741-.479 3 3 0 0 0-4.682-2.72m.94 3.198.001.031c0 .225-.012.447-.037.666A11.944 11.944 0 0 1 12 21c-2.17 0-4.207-.576-5.963-1.584A6.062 6.062 0 0 1 6 18.719m12 0a5.971 5.971 0 0 0-.941-3.197m0 0A5.995 5.995 0 0 0 12 12.75a5.995 5.995 0 0 0-5.058 2.772m0 0a3 3 0 0 0-4.681 2.72 8.986 8.986 0 0 0 3.74.477m.94-3.197a5.971 5.971 0 0 0-.94 3.197M15 6.75a3 3 0 1 1-6 0 3 3 0 0 1 6 0Zm6 3a2.25 2.25 0 1 1-4.5 0 2.25 2.25 0 0 1 4.5 0Zm-13.5 0a2.25 2.25 0 1 1-4.5 0 2.25 2.25 0 0 1 4.5 0Z"/></svg>
|
||
公客列表
|
||
<span class="ml-auto inline-flex items-center px-1.5 py-0.5 rounded text-xs font-medium bg-neutral-100 text-neutral-500">P2</span>
|
||
</a>
|
||
<a class="flex items-center gap-2 px-2 py-1.5 rounded-md text-neutral-700 hover:bg-neutral-100 cursor-pointer">
|
||
<svg class="w-4 h-4 text-neutral-400" fill="none" stroke="currentColor" stroke-width="1.8" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"/></svg>
|
||
成交客列表
|
||
<span class="ml-auto inline-flex items-center px-1.5 py-0.5 rounded text-xs font-medium bg-neutral-100 text-neutral-500">P2</span>
|
||
</a>
|
||
<a class="flex items-center gap-2 px-2 py-1.5 rounded-md text-neutral-700 hover:bg-neutral-100 cursor-pointer">
|
||
<svg class="w-4 h-4 text-neutral-400" fill="none" stroke="currentColor" stroke-width="1.8" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0"/></svg>
|
||
已删客源
|
||
</a>
|
||
<div class="px-2 pt-4 pb-1 text-xs font-medium text-neutral-500 uppercase tracking-wide">快速视图</div>
|
||
<a class="flex items-center gap-2 px-2 py-1.5 rounded-md text-neutral-700 hover:bg-neutral-100 cursor-pointer">
|
||
<span class="w-1.5 h-1.5 rounded-full bg-danger-600"></span> 即将掉公
|
||
<span class="ml-auto text-xs text-neutral-500 tabular-nums">23</span>
|
||
</a>
|
||
<a class="flex items-center gap-2 px-2 py-1.5 rounded-md text-neutral-700 hover:bg-neutral-100 cursor-pointer">
|
||
<span class="w-1.5 h-1.5 rounded-full bg-warning-600"></span> 与我相关
|
||
<span class="ml-auto text-xs text-neutral-500 tabular-nums">312</span>
|
||
</a>
|
||
<a class="flex items-center gap-2 px-2 py-1.5 rounded-md text-neutral-700 hover:bg-neutral-100 cursor-pointer">
|
||
<span class="w-1.5 h-1.5 rounded-full bg-info-600"></span> 重复提醒
|
||
<span class="ml-auto inline-flex items-center px-1.5 py-0.5 rounded text-xs font-medium bg-danger-50 text-danger-600 tabular-nums">8</span>
|
||
</a>
|
||
</nav>
|
||
</aside>
|
||
|
||
<!-- 内容区 -->
|
||
<main class="flex-1 min-w-0 ml-56" x-data="{
|
||
activeLevel1: 'private',
|
||
activeLevel2: 'all',
|
||
showFilters: true,
|
||
showMoreFilters: false,
|
||
selectedStatus: '',
|
||
selectedGrade: '',
|
||
selectedDemand: '',
|
||
selectedLocation: '',
|
||
selectedRoom: '',
|
||
selected: [],
|
||
showColumnModal: false,
|
||
showDialModal: false,
|
||
dialClient: { name: '', phone: '' },
|
||
level2Tabs: [
|
||
{ key: 'buying', label: '求购', count: 613 },
|
||
{ key: 'renting', label: '求租', count: 298 },
|
||
{ key: 'suspended', label: '暂缓', count: 113 },
|
||
{ key: 'all', label: '全部私客', count: null },
|
||
],
|
||
clients: [
|
||
{
|
||
id: '001', name: '李慧敏', grade: 'A', gradeLabel: 'A(急迫)',
|
||
activityTags: [
|
||
{ key: 'new_matched', label: '新配房', cls: 'bg-info-50 text-info-600' },
|
||
{ key: 'expiring', label: '即将过期', cls: 'bg-warning-50 text-warning-600' }
|
||
],
|
||
status: 'buying', statusLabel: '求购',
|
||
statusCls: 'bg-primary-50 text-primary-700',
|
||
demandType: '二手',
|
||
budgetArea: '550-600万,100㎡-110㎡...',
|
||
matchCount: 12,
|
||
location: '徐汇·田林',
|
||
owner: '雷威-都市港湾店一组',
|
||
viewingProgress: 1, viewingLabel: '一看',
|
||
viewingCls: 'bg-warning-50 text-warning-600',
|
||
viewingCount: 3,
|
||
commissionDate: '2026-03-15',
|
||
lastFollow: '3天前', lastFollowDanger: false,
|
||
phone: '138****6789',
|
||
pinned: true
|
||
},
|
||
{
|
||
id: '002', name: '张建国', grade: 'B', gradeLabel: 'B(较强)',
|
||
activityTags: [
|
||
{ key: 'active_7d', label: '7日活跃', cls: 'bg-success-50 text-success-600' }
|
||
],
|
||
status: 'buying', statusLabel: '求购',
|
||
statusCls: 'bg-primary-50 text-primary-700',
|
||
demandType: '新房',
|
||
budgetArea: '800-1000万,120㎡-150㎡...',
|
||
matchCount: 7,
|
||
location: '浦东·陆家嘴',
|
||
owner: '陈丽-陆家嘴精英店二组',
|
||
viewingProgress: 0, viewingLabel: '未带看',
|
||
viewingCls: '',
|
||
viewingCount: 0,
|
||
commissionDate: '2026-04-01',
|
||
lastFollow: '今天', lastFollowDanger: false,
|
||
phone: '186****3421',
|
||
pinned: false
|
||
},
|
||
{
|
||
id: '003', name: '王芳', grade: 'C', gradeLabel: 'C(一般)',
|
||
activityTags: [
|
||
{ key: 'active_30d', label: '30日活跃', cls: 'bg-green-50 text-green-500' },
|
||
{ key: 'marketing', label: '营销客', cls: 'bg-purple-50 text-purple-600' }
|
||
],
|
||
status: 'renting', statusLabel: '求租',
|
||
statusCls: 'bg-info-50 text-info-600',
|
||
demandType: '租房',
|
||
budgetArea: '4000-5500元,60㎡-80㎡...',
|
||
matchCount: 5,
|
||
location: '静安·南京西路',
|
||
owner: '周杰-南西核心店一组',
|
||
viewingProgress: 2, viewingLabel: '二看',
|
||
viewingCls: 'bg-info-50 text-info-600',
|
||
viewingCount: 5,
|
||
commissionDate: '2026-03-28',
|
||
lastFollow: '12天前', lastFollowDanger: false,
|
||
phone: '135****0088',
|
||
pinned: false
|
||
},
|
||
{
|
||
id: '004', name: '刘思远', grade: 'A', gradeLabel: 'A(急迫)',
|
||
activityTags: [
|
||
{ key: 'new_matched', label: '新配房', cls: 'bg-info-50 text-info-600' }
|
||
],
|
||
status: 'buy_or_rent', statusLabel: '租购',
|
||
statusCls: 'bg-warning-50 text-warning-600',
|
||
demandType: '二手',
|
||
budgetArea: '300-400万,80㎡-100㎡...',
|
||
matchCount: 18,
|
||
location: '宝山·共康',
|
||
owner: '魏深-宝山北区一店三组',
|
||
viewingProgress: 3, viewingLabel: '复看',
|
||
viewingCls: 'bg-success-50 text-success-600',
|
||
viewingCount: 7,
|
||
commissionDate: '2026-02-20',
|
||
lastFollow: '1天前', lastFollowDanger: false,
|
||
phone: '139****5566',
|
||
pinned: false
|
||
},
|
||
{
|
||
id: '005', name: '陈晓琳', grade: 'D', gradeLabel: 'D(较弱)',
|
||
activityTags: [
|
||
{ key: 'invalid', label: '无效', cls: 'bg-danger-50 text-danger-600' }
|
||
],
|
||
status: 'suspended', statusLabel: '暂缓',
|
||
statusCls: 'bg-neutral-100 text-neutral-500',
|
||
demandType: '二手',
|
||
budgetArea: '200-280万,70㎡-90㎡...',
|
||
matchCount: 2,
|
||
location: '闵行·古美',
|
||
owner: '李敏-古美路店二组',
|
||
viewingProgress: 0, viewingLabel: '未带看',
|
||
viewingCls: '',
|
||
viewingCount: 0,
|
||
commissionDate: '2026-01-10',
|
||
lastFollow: '45天前', lastFollowDanger: true,
|
||
phone: '150****2233',
|
||
pinned: false
|
||
},
|
||
{
|
||
id: '006', name: '孙大伟', grade: 'B', gradeLabel: 'B(较强)',
|
||
activityTags: [
|
||
{ key: 'active_7d', label: '7日活跃', cls: 'bg-success-50 text-success-600' },
|
||
{ key: 'sales', label: '销售客', cls: 'bg-orange-50 text-orange-600' }
|
||
],
|
||
status: 'buying', statusLabel: '求购',
|
||
statusCls: 'bg-primary-50 text-primary-700',
|
||
demandType: '新房',
|
||
budgetArea: '1500-2000万,200㎡以上...',
|
||
matchCount: 4,
|
||
location: '黄浦·外滩',
|
||
owner: '张帆-外滩豪宅店一组',
|
||
viewingProgress: 1, viewingLabel: '一看',
|
||
viewingCls: 'bg-warning-50 text-warning-600',
|
||
viewingCount: 2,
|
||
commissionDate: '2026-04-10',
|
||
lastFollow: '今天', lastFollowDanger: false,
|
||
phone: '177****9900',
|
||
pinned: false
|
||
},
|
||
{
|
||
id: '007', name: '赵梅', grade: 'C', gradeLabel: 'C(一般)',
|
||
activityTags: [
|
||
{ key: 'visitor', label: '访客', cls: 'bg-neutral-100 text-neutral-500' }
|
||
],
|
||
status: 'renting', statusLabel: '求租',
|
||
statusCls: 'bg-info-50 text-info-600',
|
||
demandType: '租房',
|
||
budgetArea: '6000-8000元,90㎡-120㎡...',
|
||
matchCount: 9,
|
||
location: '长宁·中山公园',
|
||
owner: '吴洁-长宁西区店三组',
|
||
viewingProgress: 0, viewingLabel: '未带看',
|
||
viewingCls: '',
|
||
viewingCount: 0,
|
||
commissionDate: '2026-04-15',
|
||
lastFollow: '8天前', lastFollowDanger: false,
|
||
phone: '158****4477',
|
||
pinned: false
|
||
},
|
||
{
|
||
id: '008', name: '钱志明', grade: 'E', gradeLabel: 'E(暂不关注)',
|
||
activityTags: [
|
||
{ key: 'frozen', label: '暂缓', cls: 'bg-neutral-100 text-neutral-500' }
|
||
],
|
||
status: 'suspended', statusLabel: '暂缓',
|
||
statusCls: 'bg-neutral-100 text-neutral-500',
|
||
demandType: '二手',
|
||
budgetArea: '150-180万,60㎡以下...',
|
||
matchCount: 0,
|
||
location: '-',
|
||
owner: '郑磊-松江新城店一组',
|
||
viewingProgress: 0, viewingLabel: '未带看',
|
||
viewingCls: '',
|
||
viewingCount: 0,
|
||
commissionDate: '2025-12-01',
|
||
lastFollow: '62天前', lastFollowDanger: true,
|
||
phone: '136****1122',
|
||
pinned: false
|
||
},
|
||
{
|
||
id: '009', name: '林晓彤', grade: 'A', gradeLabel: 'A(急迫)',
|
||
activityTags: [
|
||
{ key: 'new_matched', label: '新配房', cls: 'bg-info-50 text-info-600' },
|
||
{ key: 'active_7d', label: '7日活跃', cls: 'bg-success-50 text-success-600' }
|
||
],
|
||
status: 'buying', statusLabel: '求购',
|
||
statusCls: 'bg-primary-50 text-primary-700',
|
||
demandType: '二手',
|
||
budgetArea: '420-500万,90㎡-110㎡...',
|
||
matchCount: 21,
|
||
location: '杨浦·五角场',
|
||
owner: '何宇-五角场店二组',
|
||
viewingProgress: 2, viewingLabel: '二看',
|
||
viewingCls: 'bg-info-50 text-info-600',
|
||
viewingCount: 4,
|
||
commissionDate: '2026-04-20',
|
||
lastFollow: '今天', lastFollowDanger: false,
|
||
phone: '180****3344',
|
||
pinned: false
|
||
},
|
||
{
|
||
id: '010', name: '吴建平', grade: 'B', gradeLabel: 'B(较强)',
|
||
activityTags: [
|
||
{ key: 'expiring', label: '即将过期', cls: 'bg-warning-50 text-warning-600' }
|
||
],
|
||
status: 'buying', statusLabel: '求购',
|
||
statusCls: 'bg-primary-50 text-primary-700',
|
||
demandType: '新房',
|
||
budgetArea: '650-780万,110㎡-130㎡...',
|
||
matchCount: 6,
|
||
location: '普陀·长寿路',
|
||
owner: '徐峰-普陀中区店一组',
|
||
viewingProgress: 1, viewingLabel: '一看',
|
||
viewingCls: 'bg-warning-50 text-warning-600',
|
||
viewingCount: 1,
|
||
commissionDate: '2026-03-05',
|
||
lastFollow: '19天前', lastFollowDanger: false,
|
||
phone: '152****8899',
|
||
pinned: false
|
||
}
|
||
],
|
||
get selectedCount() { return this.selected.length },
|
||
toggleAll(e) {
|
||
if (e.target.checked) {
|
||
this.selected = this.clients.map(c => c.id);
|
||
} else {
|
||
this.selected = [];
|
||
}
|
||
},
|
||
openDial(client) {
|
||
this.dialClient = { name: client.name, phone: client.phone };
|
||
this.showDialModal = true;
|
||
}
|
||
}">
|
||
|
||
<!-- ============ 一级 Tab 导航区 ============ -->
|
||
<div class="bg-white border-b border-neutral-200 px-6">
|
||
<div class="flex items-center justify-between">
|
||
<!-- 一级 Tab -->
|
||
<nav class="flex items-center gap-0">
|
||
<button @click="activeLevel1 = 'private'"
|
||
:class="activeLevel1 === 'private' ? 'border-primary-600 text-primary-600 font-medium' : 'border-transparent text-neutral-500 hover:text-neutral-700'"
|
||
class="px-4 py-3.5 text-sm border-b-2 transition-colors whitespace-nowrap">
|
||
私客
|
||
</button>
|
||
<button @click="activeLevel1 = 'data'"
|
||
:class="activeLevel1 === 'data' ? 'border-primary-600 text-primary-600 font-medium' : 'border-transparent text-neutral-500 hover:text-neutral-700'"
|
||
class="px-4 py-3.5 text-sm border-b-2 transition-colors whitespace-nowrap">
|
||
资料客
|
||
<span class="ml-1 px-1.5 py-0.5 text-xs bg-neutral-100 text-neutral-500 rounded">即将上线</span>
|
||
</button>
|
||
<button @click="activeLevel1 = 'marketing'"
|
||
:class="activeLevel1 === 'marketing' ? 'border-primary-600 text-primary-600 font-medium' : 'border-transparent text-neutral-500 hover:text-neutral-700'"
|
||
class="px-4 py-3.5 text-sm border-b-2 transition-colors whitespace-nowrap">
|
||
营销客
|
||
<span class="ml-1 px-1.5 py-0.5 text-xs bg-neutral-100 text-neutral-500 rounded">即将上线</span>
|
||
</button>
|
||
<button @click="activeLevel1 = 'transacted'"
|
||
:class="activeLevel1 === 'transacted' ? 'border-primary-600 text-primary-600 font-medium' : 'border-transparent text-neutral-500 hover:text-neutral-700'"
|
||
class="px-4 py-3.5 text-sm border-b-2 transition-colors whitespace-nowrap">
|
||
成交客
|
||
</button>
|
||
<button @click="activeLevel1 = 'public'"
|
||
:class="activeLevel1 === 'public' ? 'border-primary-600 text-primary-600 font-medium' : 'border-transparent text-neutral-500 hover:text-neutral-700'"
|
||
class="px-4 py-3.5 text-sm border-b-2 transition-colors whitespace-nowrap">
|
||
公客
|
||
</button>
|
||
</nav>
|
||
<!-- 右侧操作区 -->
|
||
<div class="flex items-center gap-4 text-sm py-2">
|
||
<span class="text-neutral-500">
|
||
私客与成交客重复:
|
||
<a href="#" class="text-info-600 hover:underline font-medium tabular-nums">5</a>
|
||
</span>
|
||
<span class="text-neutral-500">
|
||
私客与公客重复:
|
||
<a href="#" class="text-info-600 hover:underline font-medium tabular-nums">3</a>
|
||
</span>
|
||
<a href="#" class="text-neutral-500 hover:text-neutral-700">已删客源</a>
|
||
<a href="#"
|
||
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>
|
||
</div>
|
||
|
||
<!-- 内容主体 -->
|
||
<div class="px-6 py-4 space-y-3">
|
||
|
||
<!-- ============ 二级 Tab 导航 ============ -->
|
||
<div class="flex items-center gap-1 p-1 bg-neutral-100 rounded-lg w-fit">
|
||
<template x-for="tab in level2Tabs" :key="tab.key">
|
||
<button
|
||
:class="activeLevel2 === 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"
|
||
@click="activeLevel2 = tab.key">
|
||
<span x-text="tab.label"></span>
|
||
<span x-show="tab.count !== null"
|
||
class="ml-1.5 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">
|
||
|
||
<!-- 搜索行 -->
|
||
<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 value="all">客户信息</option>
|
||
<option value="client_no">客源编号</option>
|
||
<option value="complex">小区</option>
|
||
</select>
|
||
|
||
<!-- 搜索输入框 -->
|
||
<div class="relative flex-1 max-w-lg">
|
||
<input type="search"
|
||
placeholder="输入客源姓名/号码/号码后4位/客源编号/备注信息"
|
||
class="w-full pl-3 pr-12 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 }" @click.away="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.5 px-3 py-2 border border-neutral-200 rounded-lg hover:border-neutral-300 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 text-neutral-400" 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 x-transition.opacity
|
||
class="absolute left-0 top-full mt-1 w-64 bg-white shadow-md border border-neutral-200 rounded-lg z-40 py-1">
|
||
<div class="px-3 py-1.5 text-xs text-neutral-400 border-b border-neutral-100">已存搜索条件</div>
|
||
<button class="w-full text-left px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-50 flex items-center justify-between">
|
||
<span>求购·浦东·500-800万</span>
|
||
<svg class="w-3.5 h-3.5 text-neutral-400 hover:text-danger-600" 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>
|
||
<button class="w-full text-left px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-50 flex items-center justify-between">
|
||
<span>A级·与我相关</span>
|
||
<svg class="w-3.5 h-3.5 text-neutral-400 hover:text-danger-600" 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>
|
||
<button class="w-full text-left px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-50 flex items-center justify-between">
|
||
<span>本月录入·求租</span>
|
||
<svg class="w-3.5 h-3.5 text-neutral-400 hover:text-danger-600" 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>
|
||
</div>
|
||
|
||
<!-- 收起/展开 -->
|
||
<button @click="showFilters = !showFilters"
|
||
class="ml-auto text-sm text-neutral-500 hover:text-primary-600 flex items-center gap-1 shrink-0">
|
||
<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"
|
||
class="mt-3 space-y-2">
|
||
|
||
<!-- 快捷筛选行 -->
|
||
<div class="flex items-center gap-4 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">
|
||
<input type="checkbox" class="w-4 h-4 rounded accent-primary-600">
|
||
即将掉公
|
||
<span class="text-xs text-danger-600 tabular-nums">(23)</span>
|
||
</label>
|
||
<div class="flex items-center gap-1.5">
|
||
<span class="text-neutral-600">录入时间</span>
|
||
<select class="text-sm border border-neutral-200 rounded-md px-2 py-1 text-neutral-600 bg-white focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-600/40">
|
||
<option value="">不限</option>
|
||
<option value="today">今天</option>
|
||
<option value="7d">最近7天</option>
|
||
<option value="30d">最近30天</option>
|
||
<option value="custom">自定义</option>
|
||
</select>
|
||
</div>
|
||
<label class="flex items-center gap-1.5 cursor-pointer text-neutral-600 hover:text-primary-600">
|
||
<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">
|
||
<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="border-t border-neutral-100"></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-6 shrink-0">状态</span>
|
||
<button @click="selectedStatus = ''"
|
||
:class="selectedStatus === '' ? '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">不限</button>
|
||
<button @click="selectedStatus = 'buying'"
|
||
:class="selectedStatus === 'buying' ? '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">求购</button>
|
||
<button @click="selectedStatus = 'renting'"
|
||
:class="selectedStatus === 'renting' ? '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">求租</button>
|
||
<button @click="selectedStatus = 'buy_or_rent'"
|
||
:class="selectedStatus === 'buy_or_rent' ? '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">租购</button>
|
||
</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-6 shrink-0">需求</span>
|
||
<button @click="selectedDemand = ''"
|
||
:class="selectedDemand === '' ? '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">不限</button>
|
||
<button @click="selectedDemand = 'second_hand'"
|
||
:class="selectedDemand === 'second_hand' ? '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">二手</button>
|
||
<button @click="selectedDemand = 'new_house'"
|
||
:class="selectedDemand === 'new_house' ? '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">新房</button>
|
||
<button @click="selectedDemand = 'rental'"
|
||
:class="selectedDemand === 'rental' ? '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">租房</button>
|
||
</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-6 shrink-0">等级</span>
|
||
<button @click="selectedGrade = ''"
|
||
:class="selectedGrade === '' ? '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">不限</button>
|
||
<button @click="selectedGrade = 'A'"
|
||
:class="selectedGrade === 'A' ? '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">A 急迫</button>
|
||
<button @click="selectedGrade = 'B'"
|
||
:class="selectedGrade === 'B' ? '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">B 较强</button>
|
||
<button @click="selectedGrade = 'C'"
|
||
:class="selectedGrade === 'C' ? '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">C 一般</button>
|
||
<button @click="selectedGrade = 'D'"
|
||
:class="selectedGrade === 'D' ? '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">D 较弱</button>
|
||
<button @click="selectedGrade = 'E'"
|
||
:class="selectedGrade === 'E' ? '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">E 暂不关注</button>
|
||
<button @click="selectedGrade = 'none'"
|
||
:class="selectedGrade === 'none' ? '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">未填写</button>
|
||
</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-6 shrink-0">位置</span>
|
||
<button @click="selectedLocation = ''"
|
||
:class="selectedLocation === '' ? '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">不限</button>
|
||
<button @click="selectedLocation = '浦东'"
|
||
:class="selectedLocation === '浦东' ? '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">浦东</button>
|
||
<button @click="selectedLocation = '徐汇'"
|
||
:class="selectedLocation === '徐汇' ? '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">徐汇</button>
|
||
<button @click="selectedLocation = '静安'"
|
||
:class="selectedLocation === '静安' ? '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">静安</button>
|
||
<button @click="selectedLocation = '黄浦'"
|
||
:class="selectedLocation === '黄浦' ? '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">黄浦</button>
|
||
<button @click="selectedLocation = '长宁'"
|
||
:class="selectedLocation === '长宁' ? '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">长宁</button>
|
||
<button @click="selectedLocation = '杨浦'"
|
||
:class="selectedLocation === '杨浦' ? '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">杨浦</button>
|
||
<button @click="selectedLocation = '普陀'"
|
||
:class="selectedLocation === '普陀' ? '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">普陀</button>
|
||
<button @click="selectedLocation = '宝山'"
|
||
:class="selectedLocation === '宝山' ? '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">宝山</button>
|
||
<button @click="selectedLocation = '闵行'"
|
||
:class="selectedLocation === '闵行' ? '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">闵行</button>
|
||
<span class="text-neutral-400 text-xs">…更多区</span>
|
||
</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-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-400万</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">400-600万</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">600-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">
|
||
<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">~</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-3 gap-y-1.5 text-sm">
|
||
<span class="text-neutral-400 text-xs w-6 shrink-0">居室</span>
|
||
<button @click="selectedRoom = ''"
|
||
:class="selectedRoom === '' ? '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">不限</button>
|
||
<button @click="selectedRoom = '1'"
|
||
:class="selectedRoom === '1' ? '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">1居</button>
|
||
<button @click="selectedRoom = '2'"
|
||
:class="selectedRoom === '2' ? '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">2居</button>
|
||
<button @click="selectedRoom = '3'"
|
||
:class="selectedRoom === '3' ? '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">3居</button>
|
||
<button @click="selectedRoom = '4'"
|
||
:class="selectedRoom === '4' ? '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">4居</button>
|
||
<button @click="selectedRoom = '5+'"
|
||
:class="selectedRoom === '5+' ? '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">5居及以上</button>
|
||
<label class="flex items-center gap-1.5 text-xs text-neutral-600 cursor-pointer hover:text-primary-600 ml-2">
|
||
<input type="checkbox" class="w-3.5 h-3.5 rounded accent-primary-600">
|
||
是大价值
|
||
</label>
|
||
</div>
|
||
|
||
<!-- 更多筛选展开 -->
|
||
<div class="pt-0.5">
|
||
<button @click="showMoreFilters = !showMoreFilters"
|
||
class="text-xs text-primary-600 hover:text-primary-700 flex items-center gap-1">
|
||
<svg class="w-3.5 h-3.5 transition-transform" :class="showMoreFilters ? '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="showMoreFilters ? '收起' : '展开更多筛选'"></span>
|
||
<span x-show="!showMoreFilters" class="ml-1 px-1.5 py-0.5 rounded-full bg-neutral-100 text-neutral-600">更多条件</span>
|
||
</button>
|
||
|
||
<!-- 更多筛选内容 -->
|
||
<div x-show="showMoreFilters"
|
||
x-transition:enter="transition ease-out duration-150"
|
||
x-transition:enter-start="opacity-0"
|
||
x-transition:enter-end="opacity-100"
|
||
class="mt-2 space-y-2 pt-2 border-t border-neutral-100">
|
||
<!-- 相关方 -->
|
||
<div class="flex items-center flex-wrap gap-x-3 gap-y-1.5 text-sm">
|
||
<span class="text-neutral-400 text-xs w-14 shrink-0">相关方</span>
|
||
<select class="text-sm border border-neutral-200 rounded-md px-3 py-1.5 text-neutral-600 bg-white focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-600/40">
|
||
<option value="">不限</option>
|
||
<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-14 shrink-0">委托日期</span>
|
||
<input type="text" placeholder="开始日期 - 结束日期"
|
||
class="text-sm border border-neutral-300 rounded-md px-3 py-1.5 text-neutral-600 w-60 focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-600/40">
|
||
</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-14 shrink-0">来源</span>
|
||
<select class="text-sm border border-neutral-200 rounded-md px-3 py-1.5 text-neutral-600 bg-white focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-600/40">
|
||
<option value="">不限</option>
|
||
<option>主动上门</option>
|
||
<option>老带新</option>
|
||
<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-14 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-3 gap-y-1.5 text-sm">
|
||
<span class="text-neutral-400 text-xs w-14 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-3 gap-y-1.5 text-sm">
|
||
<span class="text-neutral-400 text-xs w-14 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">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-3 gap-y-1.5 text-sm">
|
||
<span class="text-neutral-400 text-xs w-14 shrink-0">跟进时间</span>
|
||
<input type="text" placeholder="开始日期 - 结束日期"
|
||
class="text-sm border border-neutral-300 rounded-md px-3 py-1.5 text-neutral-600 w-60 focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-600/40">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ============ 数据表格区域 ============ -->
|
||
<div id="client-list-container">
|
||
<div class="rounded-lg border border-neutral-200 overflow-hidden bg-white">
|
||
|
||
<!-- 工具栏 -->
|
||
<div class="flex items-center justify-between px-4 py-2.5 border-b border-neutral-100">
|
||
<!-- 左侧:批量操作 + 总条数 -->
|
||
<div class="flex items-center gap-2">
|
||
<button :disabled="selectedCount === 0"
|
||
:class="selectedCount > 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="selectedCount === 0"
|
||
:class="selectedCount > 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="selectedCount === 0"
|
||
:class="selectedCount > 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="selectedCount === 0"
|
||
:class="selectedCount > 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-1">
|
||
共 <strong class="text-neutral-800 tabular-nums">1,024</strong> 条
|
||
</span>
|
||
<span x-show="selectedCount > 0" class="text-sm text-primary-600">
|
||
已选 <span x-text="selectedCount" class="tabular-nums font-medium"></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 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 text-center">
|
||
<input type="checkbox" id="select-all"
|
||
class="w-4 h-4 rounded accent-primary-600 cursor-pointer"
|
||
@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">
|
||
最近时间
|
||
<svg class="inline w-3.5 h-3.5 text-primary-600 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-7.5 7.5-7.5-7.5"/><path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5"/></svg>
|
||
<!-- 默认降序激活 -->
|
||
<svg class="inline w-3.5 h-3.5 text-primary-600 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-7.5 7.5-7.5-7.5"/></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">
|
||
<template x-for="client in clients" :key="client.id">
|
||
<tr class="hover:bg-neutral-50 transition-colors"
|
||
:class="[
|
||
selected.includes(client.id) ? 'bg-primary-50 hover:bg-primary-50' : '',
|
||
client.pinned ? 'bg-warning-50/30' : ''
|
||
]"
|
||
style="height:56px">
|
||
|
||
<!-- 复选框 -->
|
||
<td class="w-10 px-4 text-center align-middle">
|
||
<input type="checkbox"
|
||
class="w-4 h-4 rounded accent-primary-600 cursor-pointer"
|
||
:value="client.id"
|
||
x-model="selected">
|
||
</td>
|
||
|
||
<!-- 姓名 + 等级 + 活跃度 -->
|
||
<td class="px-4 py-2 align-middle min-w-[160px] max-w-[200px]">
|
||
<div class="flex flex-col gap-0.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>
|
||
<a href="#"
|
||
class="text-info-600 hover:underline font-medium text-sm truncate max-w-[160px]"
|
||
x-text="client.name"></a>
|
||
<span class="text-[11px] text-neutral-400 font-medium shrink-0" x-text="client.gradeLabel"></span>
|
||
</div>
|
||
<!-- 活跃度标签行 -->
|
||
<div class="flex items-center gap-1 flex-wrap">
|
||
<template x-for="tag in client.activityTags" :key="tag.key">
|
||
<span class="text-[11px] px-1.5 py-0.5 rounded-full font-medium"
|
||
:class="tag.cls"
|
||
x-text="tag.label"></span>
|
||
</template>
|
||
</div>
|
||
</div>
|
||
</td>
|
||
|
||
<!-- 状态 -->
|
||
<td class="px-4 py-2 align-middle w-20">
|
||
<span class="text-xs px-2 py-0.5 rounded-full font-medium"
|
||
:class="client.statusCls"
|
||
x-text="client.statusLabel"></span>
|
||
</td>
|
||
|
||
<!-- 需求类型 -->
|
||
<td class="px-4 py-2 align-middle w-20">
|
||
<span class="text-sm text-neutral-700" x-text="client.demandType"></span>
|
||
</td>
|
||
|
||
<!-- 需求/解读 -->
|
||
<td class="px-4 py-2 align-middle min-w-[180px]">
|
||
<span class="text-sm text-neutral-700 truncate block max-w-[220px]"
|
||
:title="client.budgetArea"
|
||
x-text="client.budgetArea"></span>
|
||
</td>
|
||
|
||
<!-- 智能配房 -->
|
||
<td class="px-4 py-2 align-middle w-24">
|
||
<div class="flex items-center gap-1">
|
||
<span class="text-sm text-neutral-700 tabular-nums" x-text="client.matchCount + '套'"></span>
|
||
<button class="text-neutral-400 hover:text-primary-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 align-middle min-w-[120px]">
|
||
<span class="text-sm text-neutral-700 truncate block max-w-[160px]"
|
||
x-text="client.location"></span>
|
||
</td>
|
||
|
||
<!-- 归属人 -->
|
||
<td class="px-4 py-2 align-middle min-w-[140px]">
|
||
<span class="text-sm text-neutral-700 truncate block max-w-[180px]"
|
||
x-text="client.owner"></span>
|
||
</td>
|
||
|
||
<!-- 带看进度 -->
|
||
<td class="px-4 py-2 align-middle w-20">
|
||
<template x-if="client.viewingProgress === 0">
|
||
<span class="text-sm text-neutral-400">未带看</span>
|
||
</template>
|
||
<template x-if="client.viewingProgress > 0">
|
||
<span class="text-xs px-2 py-0.5 rounded-full font-medium"
|
||
:class="client.viewingCls"
|
||
x-text="client.viewingLabel"></span>
|
||
</template>
|
||
</td>
|
||
|
||
<!-- 带看次数 -->
|
||
<td class="px-4 py-2 align-middle w-[72px]">
|
||
<span class="text-sm text-neutral-700 tabular-nums" x-text="client.viewingCount + '次'"></span>
|
||
</td>
|
||
|
||
<!-- 委托日期 -->
|
||
<td class="px-4 py-2 align-middle w-24">
|
||
<span class="text-sm text-neutral-700 tabular-nums" x-text="client.commissionDate || '-'"></span>
|
||
</td>
|
||
|
||
<!-- 最近时间 -->
|
||
<td class="px-4 py-2 align-middle w-24">
|
||
<span class="text-sm tabular-nums"
|
||
:class="client.lastFollowDanger ? 'text-danger-600' : 'text-neutral-700'"
|
||
x-text="client.lastFollow"></span>
|
||
</td>
|
||
|
||
<!-- 操作 -->
|
||
<td class="px-3 py-2 align-middle text-center w-16">
|
||
<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="拨号"
|
||
@click="openDial(client)">
|
||
<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.338c0-1.13.908-2.172 2.004-2.172C15.352 4.166 19.834 8.648 19.834 19.746c0 1.096-1.043 2.004-2.172 2.004h-1.344a2.504 2.504 0 0 1-2.396-1.776c-.432-1.548-.924-2.952-1.476-4.236a2.5 2.5 0 0 1 .84-2.832l.888-.672c-.552-1.788-1.644-3.42-3.228-4.752l-.672.888a2.5 2.5 0 0 1-2.832.84C5.29 9.468 3.886 8.976 2.338 8.544A2.504 2.504 0 0 1 .562 6.148v-.002H2.25V6.338Z"/></svg>
|
||
</button>
|
||
</td>
|
||
</tr>
|
||
</template>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ============ 分页栏 ============ -->
|
||
<div class="flex items-center justify-between px-1 py-1">
|
||
<!-- 左侧:总条数 -->
|
||
<div class="text-xs text-neutral-500">
|
||
共 <span class="font-medium text-neutral-800 tabular-nums">1,024</span> 条
|
||
</div>
|
||
|
||
<!-- 中间:分页按钮 -->
|
||
<nav class="flex items-center gap-1">
|
||
<button class="p-1.5 text-neutral-300 rounded cursor-not-allowed" disabled>
|
||
<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="min-w-[32px] h-8 px-2 text-sm font-medium bg-primary-600 text-white rounded-md tabular-nums">1</button>
|
||
<button class="min-w-[32px] h-8 px-2 text-sm text-neutral-700 hover:bg-neutral-100 rounded-md tabular-nums">2</button>
|
||
<button class="min-w-[32px] h-8 px-2 text-sm text-neutral-700 hover:bg-neutral-100 rounded-md tabular-nums">3</button>
|
||
<button class="min-w-[32px] h-8 px-2 text-sm text-neutral-700 hover:bg-neutral-100 rounded-md tabular-nums">4</button>
|
||
<button class="min-w-[32px] h-8 px-2 text-sm text-neutral-700 hover:bg-neutral-100 rounded-md tabular-nums">5</button>
|
||
<span class="px-1 text-neutral-400 text-sm">…</span>
|
||
<button class="min-w-[32px] h-8 px-2 text-sm text-neutral-700 hover:bg-neutral-100 rounded-md tabular-nums">52</button>
|
||
<button class="p-1.5 text-neutral-500 hover:bg-neutral-100 rounded-md">
|
||
<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>
|
||
</nav>
|
||
|
||
<!-- 右侧:每页条数 + 跳页 -->
|
||
<div class="flex items-center gap-2 text-xs text-neutral-500">
|
||
<select class="text-xs rounded-md border border-neutral-300 px-2 py-1 focus:outline-none focus:border-primary-600 bg-white">
|
||
<option>20条/页</option>
|
||
<option>50条/页</option>
|
||
<option>100条/页</option>
|
||
</select>
|
||
<span>跳至</span>
|
||
<input type="number" min="1" max="52"
|
||
class="w-12 text-xs rounded-md border border-neutral-300 text-center py-1 focus:outline-none focus:border-primary-600">
|
||
<span>页</span>
|
||
<button class="px-2 py-1 text-xs border border-neutral-300 rounded-md hover:bg-neutral-50 text-neutral-600">确定</button>
|
||
</div>
|
||
</div>
|
||
|
||
</div><!-- /内容主体 -->
|
||
</main>
|
||
|
||
<!-- ============ 拨号弹层 ============ -->
|
||
<div x-show="showDialModal" x-cloak
|
||
class="fixed inset-0 z-50 bg-neutral-900/40"
|
||
@click="showDialModal = false"
|
||
x-transition.opacity></div>
|
||
|
||
<div x-show="showDialModal" x-cloak
|
||
class="fixed inset-0 z-60 flex items-center justify-center p-4 pointer-events-none"
|
||
x-transition>
|
||
<div class="w-full max-w-sm bg-white rounded-xl shadow-lg pointer-events-auto"
|
||
@click.stop>
|
||
<div class="flex items-center justify-between px-5 py-4 border-b border-neutral-200">
|
||
<h2 class="text-base font-semibold text-neutral-800">拨号</h2>
|
||
<button @click="showDialModal = false" class="p-1 text-neutral-500 hover:bg-neutral-100 rounded-md">
|
||
<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>
|
||
<div class="px-5 py-6 space-y-4 text-center">
|
||
<div class="w-14 h-14 rounded-full bg-primary-50 flex items-center justify-center mx-auto">
|
||
<svg class="w-7 h-7 text-primary-600" fill="none" stroke="currentColor" stroke-width="1.8" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M2.25 6.338c0-1.13.908-2.172 2.004-2.172C15.352 4.166 19.834 8.648 19.834 19.746c0 1.096-1.043 2.004-2.172 2.004h-1.344a2.504 2.504 0 0 1-2.396-1.776c-.432-1.548-.924-2.952-1.476-4.236a2.5 2.5 0 0 1 .84-2.832l.888-.672c-.552-1.788-1.644-3.42-3.228-4.752l-.672.888a2.5 2.5 0 0 1-2.832.84C5.29 9.468 3.886 8.976 2.338 8.544A2.504 2.504 0 0 1 .562 6.148v-.002H2.25V6.338Z"/></svg>
|
||
</div>
|
||
<div>
|
||
<div class="text-lg font-semibold text-neutral-800" x-text="dialClient.name"></div>
|
||
<div class="text-2xl font-mono font-medium text-neutral-900 mt-1 tabular-nums" x-text="dialClient.phone"></div>
|
||
</div>
|
||
<p class="text-xs text-neutral-500">点击「查看完整号码」需要授权并记录审计日志</p>
|
||
<button class="text-sm text-primary-600 hover:underline">查看完整号码</button>
|
||
</div>
|
||
<div class="flex items-center gap-2 px-5 py-3 border-t border-neutral-200 bg-neutral-50">
|
||
<button @click="showDialModal = false"
|
||
class="flex-1 px-3 py-2 text-sm border border-neutral-300 rounded-lg hover:bg-white text-neutral-700">
|
||
取消
|
||
</button>
|
||
<button class="flex-1 px-3 py-2 text-sm bg-primary-600 hover:bg-primary-700 text-white rounded-lg font-medium transition-colors">
|
||
<span class="flex items-center justify-center gap-1.5">
|
||
<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="M2.25 6.338c0-1.13.908-2.172 2.004-2.172C15.352 4.166 19.834 8.648 19.834 19.746c0 1.096-1.043 2.004-2.172 2.004h-1.344a2.504 2.504 0 0 1-2.396-1.776c-.432-1.548-.924-2.952-1.476-4.236a2.5 2.5 0 0 1 .84-2.832l.888-.672c-.552-1.788-1.644-3.42-3.228-4.752l-.672.888a2.5 2.5 0 0 1-2.832.84C5.29 9.468 3.886 8.976 2.338 8.544A2.504 2.504 0 0 1 .562 6.148v-.002H2.25V6.338Z"/></svg>
|
||
拨打电话
|
||
</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ============ 自定义列弹窗 ============ -->
|
||
<div x-show="showColumnModal" x-cloak
|
||
class="fixed inset-0 z-50 bg-neutral-900/40"
|
||
@click="showColumnModal = false"
|
||
x-transition.opacity></div>
|
||
|
||
<div x-show="showColumnModal" x-cloak
|
||
class="fixed inset-0 z-60 flex items-center justify-center p-4 pointer-events-none"
|
||
x-transition>
|
||
<div class="w-full max-w-2xl bg-white rounded-xl shadow-lg pointer-events-auto flex flex-col max-h-[80vh]"
|
||
@click.stop
|
||
x-data="{
|
||
available: [
|
||
{ id: 'client_no', label: '客源编号' },
|
||
{ id: 'created_at', label: '录入日期' },
|
||
{ id: 'last_call_at', label: '最近通话日期' },
|
||
{ id: 'purpose', label: '用途' },
|
||
{ id: 'source', label: '来源' },
|
||
{ id: 'first_recorder', label: '首录人' },
|
||
{ id: 'deal_person', label: '成交人' }
|
||
],
|
||
selected: [
|
||
{ id: 'name', label: '姓名', locked: true },
|
||
{ id: 'status', label: '状态', locked: false },
|
||
{ id: 'req_type', label: '需求类型', locked: false },
|
||
{ id: 'budget_area', label: '需求/解读', locked: false },
|
||
{ id: 'match_count', label: '智能配房', locked: false },
|
||
{ id: 'location', label: '意向商圈/小区', locked: false },
|
||
{ id: 'owner', label: '归属人', locked: false },
|
||
{ id: 'viewing_progress', label: '带看进度', locked: false },
|
||
{ id: 'viewing_count', label: '带看次数', locked: false },
|
||
{ id: 'commission_date', label: '委托日期', locked: false },
|
||
{ id: 'last_follow', label: '最近时间', locked: false }
|
||
],
|
||
addCol(col) {
|
||
this.selected.push({ id: col.id, label: col.label, locked: false });
|
||
this.available = this.available.filter(a => a.id !== col.id);
|
||
},
|
||
removeCol(col) {
|
||
this.available.push({ id: col.id, label: col.label });
|
||
this.selected = this.selected.filter(s => s.id !== col.id);
|
||
},
|
||
resetDefault() {
|
||
// 恢复默认逻辑(原型中仅演示)
|
||
}
|
||
}">
|
||
<!-- Header -->
|
||
<div class="flex items-center justify-between px-5 py-4 border-b border-neutral-200">
|
||
<h2 class="text-base font-semibold text-neutral-800">自定义信息</h2>
|
||
<button @click="showColumnModal = false" class="p-1 text-neutral-500 hover:bg-neutral-100 rounded-md">
|
||
<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 divide-x divide-neutral-200">
|
||
<!-- 左栏:未选信息 -->
|
||
<div class="flex-1 flex flex-col overflow-hidden">
|
||
<div class="px-4 py-2.5 text-xs font-semibold text-neutral-500 uppercase tracking-wide border-b border-neutral-100 bg-neutral-50">未选信息</div>
|
||
<ul class="flex-1 overflow-y-auto py-1">
|
||
<template x-for="col in available" :key="col.id">
|
||
<li class="flex items-center gap-3 px-4 py-2.5 hover:bg-neutral-50 cursor-pointer"
|
||
@click="addCol(col)">
|
||
<input type="checkbox" class="w-4 h-4 rounded accent-primary-600">
|
||
<span class="text-sm text-neutral-700" x-text="col.label"></span>
|
||
</li>
|
||
</template>
|
||
<li x-show="available.length === 0" class="px-4 py-8 text-center text-xs text-neutral-400">所有字段已选中</li>
|
||
</ul>
|
||
</div>
|
||
<!-- 右栏:已选信息 -->
|
||
<div class="flex-1 flex flex-col overflow-hidden">
|
||
<div class="px-4 py-2.5 text-xs font-semibold text-neutral-500 uppercase tracking-wide border-b border-neutral-100 bg-neutral-50">已选信息</div>
|
||
<ul class="flex-1 overflow-y-auto py-1">
|
||
<template x-for="(col, idx) in selected" :key="col.id">
|
||
<li class="flex items-center gap-2 px-4 py-2.5 hover:bg-neutral-50 group">
|
||
<!-- 拖拽手柄 -->
|
||
<svg class="w-4 h-4 text-neutral-300 cursor-grab shrink-0" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M3.75 9h16.5m-16.5 6.75h16.5"/></svg>
|
||
<span class="text-xs text-neutral-400 tabular-nums w-5 shrink-0" x-text="idx + 1"></span>
|
||
<span class="text-sm text-neutral-700 flex-1" x-text="col.label"></span>
|
||
<!-- 锁定或删除 -->
|
||
<template x-if="col.locked">
|
||
<svg class="w-4 h-4 text-neutral-300 shrink-0" fill="none" stroke="currentColor" stroke-width="1.8" 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>
|
||
</template>
|
||
<template x-if="!col.locked">
|
||
<button @click="removeCol(col)"
|
||
class="text-neutral-300 hover:text-danger-600 transition-colors shrink-0">
|
||
<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="M6 18 18 6M6 6l12 12"/></svg>
|
||
</button>
|
||
</template>
|
||
</li>
|
||
</template>
|
||
</ul>
|
||
<div class="px-4 py-2 border-t border-neutral-100 bg-neutral-50">
|
||
<p class="text-xs text-neutral-400">拖拽可调整展示顺序</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- Footer -->
|
||
<div class="flex items-center justify-between px-5 py-3 border-t border-neutral-200 bg-neutral-50">
|
||
<button @click="resetDefault()"
|
||
class="text-sm text-neutral-500 hover:text-neutral-700 hover:underline underline-offset-2">
|
||
恢复默认
|
||
</button>
|
||
<div class="flex items-center gap-2">
|
||
<button @click="showColumnModal = false"
|
||
class="px-4 py-1.5 text-sm border border-neutral-300 rounded-lg hover:bg-white text-neutral-700 transition-colors">
|
||
取消
|
||
</button>
|
||
<button @click="showColumnModal = false"
|
||
class="px-4 py-1.5 text-sm bg-primary-600 hover:bg-primary-700 text-white rounded-lg font-medium transition-colors">
|
||
确定
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div><!-- /flex -->
|
||
|
||
<!-- ============ Toast 示例(右下角) ============ -->
|
||
<div class="fixed bottom-6 right-6 z-70 space-y-2">
|
||
<!-- 示例 Toast:Success -->
|
||
<div class="w-80 bg-white rounded-lg shadow-lg border border-neutral-200 flex items-start gap-3 p-3"
|
||
x-data="{ show: false }" x-show="show" x-transition>
|
||
<svg class="w-5 h-5 text-success-600 shrink-0 mt-0.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"/></svg>
|
||
<div class="flex-1 text-sm">
|
||
<p class="font-medium text-neutral-800">操作成功</p>
|
||
<p class="text-xs text-neutral-500 mt-0.5">客源信息已更新</p>
|
||
</div>
|
||
<button @click="show = false" class="text-neutral-400 hover:text-neutral-600 shrink-0">
|
||
<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="M6 18 18 6M6 6l12 12"/></svg>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
</body>
|
||
</html>
|