Files
nexus/Project/fonrey/UI_DESIGN/客源列表_UI.html
2026-04-26 14:03:16 +08:00

1205 lines
79 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!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">
<!-- 示例 ToastSuccess -->
<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>