1143 lines
80 KiB
HTML
1143 lines
80 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',700:'#15803D'},
|
||
warning:{50:'#FFFBEB',600:'#D97706',700:'#B45309'},
|
||
danger: {50:'#FEF2F2',600:'#DC2626',700:'#B91C1C'},
|
||
info: {50:'#EFF6FF',600:'#2563EB',700:'#1D4ED8'},
|
||
},
|
||
boxShadow: { xs:'0 1px 2px rgba(15,23,42,0.04)' },
|
||
fontFamily: {
|
||
sans:['Inter','PingFang SC','Microsoft YaHei','sans-serif'],
|
||
},
|
||
}
|
||
}
|
||
}
|
||
</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 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>
|
||
<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 border-l-2 border-primary-600 rounded-l-none">
|
||
<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="m2.25 12 8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25"/></svg>
|
||
全部房源
|
||
<span class="ml-auto text-xs text-neutral-500 tabular-nums">3,629</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="M2.25 18.75a60.07 60.07 0 0 1 15.797 2.101c.727.198 1.453-.342 1.453-1.096V18.75M3.75 4.5v.75A.75.75 0 0 1 3 6h-.75m0 0v-.375c0-.621.504-1.125 1.125-1.125H20.25M2.25 6v9m18-10.5v.75c0 .414.336.75.75.75h.75m-1.5-1.5h.375c.621 0 1.125.504 1.125 1.125v9.75c0 .621-.504 1.125-1.125 1.125h-.375m1.5-1.5H21a.75.75 0 0 0-.75.75v.75m0 0H3.75m0 0h-.375a1.125 1.125 0 0 1-1.125-1.125V15m1.5 1.5v-.75A.75.75 0 0 0 3 15h-.75M15 10.5a3 3 0 1 1-6 0 3 3 0 0 1 6 0Zm3 0h.008v.008H18V10.5Zm-12 0h.008v.008H6V10.5Z"/></svg>
|
||
出售房源
|
||
<span class="ml-auto text-xs text-neutral-500 tabular-nums">1,842</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="M8.25 21v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21m0 0h4.5V3.545M12.75 21h7.5V10.75M2.25 21h1.5m18 0h-18M2.25 9l4.5-1.636M18.75 3l-1.5.545m0 6.205 3 1m1.5.5-1.5-.5M6.75 7.364V3h-3v18m3-13.636 10.5-3.819"/></svg>
|
||
出租房源
|
||
<span class="ml-auto text-xs text-neutral-500 tabular-nums">641</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.364 18.364A9 9 0 0 0 5.636 5.636m12.728 12.728A9 9 0 0 1 5.636 5.636m12.728 12.728L5.636 5.636"/></svg>
|
||
未挂牌
|
||
<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">
|
||
<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 text-xs text-neutral-500 tabular-nums">834</span>
|
||
</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">
|
||
<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="M3.75 21h16.5M4.5 3h15M5.25 3v18m13.5-18v18M9 6.75h1.5m-1.5 3h1.5m-1.5 3h1.5m3-6H15m-1.5 3H15m-1.5 3H15M9 21v-3.375c0-.621.504-1.125 1.125-1.125h3.75c.621 0 1.125.504 1.125 1.125V21"/></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">47</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">286</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">12</span>
|
||
</a>
|
||
</nav>
|
||
</aside>
|
||
|
||
<!-- ============ 内容区 ============ -->
|
||
<main class="flex-1 min-w-0 ml-56" x-data="{
|
||
activeTab: 'all',
|
||
showFilters: true,
|
||
showMoreFilters: false,
|
||
priceMode: 'sale',
|
||
selectedDistricts: [],
|
||
selectedArea: '',
|
||
selectedRooms: [],
|
||
selectedFloors: [],
|
||
selectedPrice: '',
|
||
selectedStatus: '',
|
||
selected: [],
|
||
showColumnModal: false,
|
||
get selectedCount() { return this.selected.length },
|
||
toggleAll(e) {
|
||
if (e.target.checked) {
|
||
this.selected = properties.map(p => p.id);
|
||
} else {
|
||
this.selected = [];
|
||
}
|
||
},
|
||
toggleDistrict(d) {
|
||
if (this.selectedDistricts.includes(d)) {
|
||
this.selectedDistricts = this.selectedDistricts.filter(x => x !== d);
|
||
} else {
|
||
this.selectedDistricts.push(d);
|
||
}
|
||
},
|
||
properties: [
|
||
{
|
||
id: '001',
|
||
complex: '中远两湾城',
|
||
block_no: '12', unit_no: '2', room_no: '802',
|
||
district: '普陀', business_area: '长寿路',
|
||
status: 'for_sale', status_label: '出售', status_cls: 'bg-success-50 text-success-700',
|
||
transaction_type: 'sale', transaction_label: '买卖', transaction_cls: 'bg-primary-200 text-primary-800',
|
||
tags: [
|
||
{ label: '满五', cls: 'bg-success-50 text-success-600' },
|
||
{ label: '电梯', cls: 'bg-neutral-100 text-neutral-600' },
|
||
{ label: '独家', cls: 'bg-primary-50 text-primary-600' }
|
||
],
|
||
sale_price: '320', sale_unit_price: '65,306',
|
||
rent_price: null,
|
||
area: '81.3', layout: '2室1厅', floor: '8/12',
|
||
orientation: '南北', listed_at: '2026-03-12', last_followed_at: '2026-04-25',
|
||
follow_overdue: false, price_trend: 'down'
|
||
},
|
||
{
|
||
id: '002',
|
||
complex: '张江花园',
|
||
block_no: '3', unit_no: '1', room_no: '1501',
|
||
district: '浦东', business_area: '张江',
|
||
status: 'for_sale', status_label: '出售', status_cls: 'bg-success-50 text-success-700',
|
||
transaction_type: 'sale', transaction_label: '买卖', transaction_cls: 'bg-primary-200 text-primary-800',
|
||
tags: [
|
||
{ label: '满五', cls: 'bg-success-50 text-success-600' },
|
||
{ label: '视频', cls: 'bg-neutral-100 text-neutral-600' }
|
||
],
|
||
sale_price: '580', sale_unit_price: '65,169',
|
||
rent_price: null,
|
||
area: '89.0', layout: '2室1厅', floor: '15/18',
|
||
orientation: '南', listed_at: '2026-01-08', last_followed_at: '2026-04-20',
|
||
follow_overdue: false, price_trend: null
|
||
},
|
||
{
|
||
id: '003',
|
||
complex: '古北国际花园',
|
||
block_no: '7', unit_no: '3', room_no: '601',
|
||
district: '闵行', business_area: '古北',
|
||
status: 'for_sale_rent', status_label: '租售', status_cls: 'bg-primary-50 text-primary-700',
|
||
transaction_type: 'sale_rent', transaction_label: '租售', transaction_cls: 'bg-neutral-300 text-neutral-800',
|
||
tags: [
|
||
{ label: '私', cls: 'bg-warning-50 text-warning-700' },
|
||
{ label: '速销', cls: 'bg-danger-50 text-danger-600' }
|
||
],
|
||
sale_price: '850', sale_unit_price: '70,833',
|
||
rent_price: '12,000',
|
||
area: '120.0', layout: '3室2厅', floor: '6/20',
|
||
orientation: '东南', listed_at: '2026-04-01', last_followed_at: '2026-04-26',
|
||
follow_overdue: false, price_trend: 'up'
|
||
},
|
||
{
|
||
id: '004',
|
||
complex: '仁恒河滨城',
|
||
block_no: '1', unit_no: '1', room_no: '2201',
|
||
district: '黄浦', business_area: '南外滩',
|
||
status: 'for_rent', status_label: '出租', status_cls: 'bg-info-50 text-info-600',
|
||
transaction_type: 'rent', transaction_label: '租赁', transaction_cls: 'bg-warning-200 text-warning-800',
|
||
tags: [
|
||
{ label: '电梯', cls: 'bg-neutral-100 text-neutral-600' }
|
||
],
|
||
sale_price: null, sale_unit_price: null,
|
||
rent_price: '18,000',
|
||
area: '145.0', layout: '3室2厅', floor: '22/30',
|
||
orientation: '南', listed_at: '2026-04-10', last_followed_at: '2026-03-15',
|
||
follow_overdue: true, price_trend: null
|
||
},
|
||
{
|
||
id: '005',
|
||
complex: '长风生态商务区',
|
||
block_no: '5', unit_no: '2', room_no: '306',
|
||
district: '普陀', business_area: '长风',
|
||
status: 'suspended', status_label: '暂缓', status_cls: 'bg-neutral-100 text-neutral-500',
|
||
transaction_type: 'sale', transaction_label: '买卖', transaction_cls: 'bg-primary-200 text-primary-800',
|
||
tags: [],
|
||
sale_price: '260', sale_unit_price: '52,000',
|
||
rent_price: null,
|
||
area: '50.0', layout: '1室1厅', floor: '3/6',
|
||
orientation: '西', listed_at: '2025-11-20', last_followed_at: '2026-02-10',
|
||
follow_overdue: true, price_trend: 'down'
|
||
},
|
||
{
|
||
id: '006',
|
||
complex: '泰晤士小镇',
|
||
block_no: '8', unit_no: '4', room_no: '1102',
|
||
district: '松江', business_area: '泰晤士小镇',
|
||
status: 'for_sale', status_label: '出售', status_cls: 'bg-success-50 text-success-700',
|
||
transaction_type: 'sale', transaction_label: '买卖', transaction_cls: 'bg-primary-200 text-primary-800',
|
||
tags: [
|
||
{ label: '满五', cls: 'bg-success-50 text-success-600' },
|
||
{ label: '独家', cls: 'bg-primary-50 text-primary-600' },
|
||
{ label: '有钥匙', cls: 'bg-neutral-100 text-neutral-600' }
|
||
],
|
||
sale_price: '190', sale_unit_price: '27,143',
|
||
rent_price: null,
|
||
area: '70.0', layout: '2室1厅', floor: '11/18',
|
||
orientation: '南北', listed_at: '2026-02-14', last_followed_at: '2026-04-22',
|
||
follow_overdue: false, price_trend: null
|
||
},
|
||
{
|
||
id: '007',
|
||
complex: '陆家嘴滨江凯旋门',
|
||
block_no: '2', unit_no: '1', room_no: '3801',
|
||
district: '浦东', business_area: '陆家嘴',
|
||
status: 'for_sale', status_label: '出售', status_cls: 'bg-success-50 text-success-700',
|
||
transaction_type: 'sale', transaction_label: '买卖', transaction_cls: 'bg-primary-200 text-primary-800',
|
||
tags: [
|
||
{ label: '私', cls: 'bg-warning-50 text-warning-700' },
|
||
{ label: '速销', cls: 'bg-danger-50 text-danger-600' },
|
||
{ label: '视频', cls: 'bg-neutral-100 text-neutral-600' }
|
||
],
|
||
sale_price: '1,580', sale_unit_price: '135,043',
|
||
rent_price: null,
|
||
area: '117.0', layout: '3室2厅', floor: '38/40',
|
||
orientation: '东南', listed_at: '2026-04-15', last_followed_at: '2026-04-26',
|
||
follow_overdue: false, price_trend: 'down'
|
||
},
|
||
{
|
||
id: '008',
|
||
complex: '世纪公园壹号',
|
||
block_no: '4', unit_no: '1', room_no: '903',
|
||
district: '浦东', business_area: '世纪公园',
|
||
status: 'sold', status_label: '成交', status_cls: 'bg-neutral-200 text-neutral-600',
|
||
transaction_type: 'sale', transaction_label: '买卖', transaction_cls: 'bg-primary-200 text-primary-800',
|
||
tags: [
|
||
{ label: '满五', cls: 'bg-success-50 text-success-600' }
|
||
],
|
||
sale_price: '450', sale_unit_price: '56,250',
|
||
rent_price: null,
|
||
area: '80.0', layout: '2室1厅', floor: '9/15',
|
||
orientation: '南', listed_at: '2026-01-05', last_followed_at: '2026-04-18',
|
||
follow_overdue: false, price_trend: null
|
||
}
|
||
]
|
||
}">
|
||
|
||
<!-- ============ 一级 Tab 导航区 ============ -->
|
||
<div class="bg-white border-b border-neutral-200 px-6">
|
||
<div class="flex items-center justify-between">
|
||
<nav class="flex items-center gap-0">
|
||
<button @click="activeTab = 'for_sale'"
|
||
:class="activeTab === 'for_sale' ? '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-600 rounded tabular-nums">1,842</span>
|
||
</button>
|
||
<button @click="activeTab = 'for_rent'"
|
||
:class="activeTab === 'for_rent' ? '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-600 rounded tabular-nums">641</span>
|
||
</button>
|
||
<button @click="activeTab = 'unlisted'"
|
||
:class="activeTab === 'unlisted' ? '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="activeTab = 'sold'"
|
||
:class="activeTab === 'sold' ? '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="activeTab = 'all'"
|
||
:class="activeTab === 'all' ? '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-3 text-sm py-2">
|
||
<a href="#" class="text-neutral-500 hover:text-neutral-700 text-sm">重复房源</a>
|
||
<a href="#" class="text-neutral-500 hover:text-neutral-700 text-sm">疑似问题号码房源</a>
|
||
<!-- 更多 -->
|
||
<div x-data="{ open: false }" @click.away="open=false" class="relative">
|
||
<button @click="open=!open"
|
||
class="flex items-center gap-1 text-sm text-neutral-600 border border-neutral-300 rounded-lg px-3 py-1.5 hover:bg-neutral-50 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="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 right-0 top-full mt-1 w-36 bg-white shadow-lg border border-neutral-200 rounded-lg z-50 py-1">
|
||
<a href="#" class="block px-4 py-2 text-sm text-neutral-700 hover:bg-neutral-50">海报视图</a>
|
||
</div>
|
||
</div>
|
||
<!-- 新增房源 -->
|
||
<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">
|
||
|
||
<!-- ============ 搜索 + 筛选区 ============ -->
|
||
<div class="bg-white rounded-lg border border-neutral-200 px-4 py-3">
|
||
|
||
<!-- 搜索行 -->
|
||
<div class="flex items-center gap-2 flex-wrap">
|
||
<!-- 关键词搜索 -->
|
||
<div class="relative flex-1 min-w-[260px] max-w-lg">
|
||
<input type="search"
|
||
placeholder="房源编号/小区/学校名称/地址/业主姓名/电话/钥匙编号等"
|
||
class="w-full pl-3 pr-10 py-2 border border-neutral-300 rounded-lg text-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-600/40">
|
||
</div>
|
||
<!-- 楼栋 -->
|
||
<div class="flex items-center gap-1.5">
|
||
<span class="text-sm text-neutral-500 whitespace-nowrap">楼栋</span>
|
||
<input type="text" placeholder="请输入" class="w-20 px-2 py-2 border border-neutral-300 rounded-lg text-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-600/40">
|
||
</div>
|
||
<!-- 单元 -->
|
||
<div class="flex items-center gap-1.5">
|
||
<span class="text-sm text-neutral-500 whitespace-nowrap">单元</span>
|
||
<input type="text" placeholder="请输入" class="w-20 px-2 py-2 border border-neutral-300 rounded-lg text-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-600/40">
|
||
</div>
|
||
<!-- 房号 -->
|
||
<div class="flex items-center gap-1.5">
|
||
<span class="text-sm text-neutral-500 whitespace-nowrap">房号</span>
|
||
<div class="relative">
|
||
<input type="text" placeholder="请输入" class="w-20 px-2 pr-6 py-2 border border-neutral-300 rounded-lg text-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-600/40">
|
||
<svg class="absolute right-1.5 top-1/2 -translate-y-1/2 w-4 h-4 text-neutral-400 cursor-pointer" fill="none" stroke="currentColor" stroke-width="1.8" viewBox="0 0 24 24" title="支持精确匹配房间号码"><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>
|
||
</div>
|
||
</div>
|
||
<!-- 搜索按钮 -->
|
||
<button class="bg-primary-600 hover:bg-primary-700 text-white w-9 h-9 rounded-lg flex items-center justify-center flex-shrink-0 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>
|
||
<!-- 地图找房(P2,置灰) -->
|
||
<button disabled class="ml-auto flex items-center gap-1.5 px-3 py-2 text-sm text-neutral-400 border border-neutral-200 rounded-lg cursor-not-allowed bg-neutral-50">
|
||
<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="M9 6.75V15m6-6v8.25m.503 3.498 4.875-2.437c.381-.19.622-.58.622-1.006V4.82c0-.836-.88-1.38-1.628-1.006l-3.869 1.934c-.317.159-.69.159-1.006 0L9.503 3.252a1.125 1.125 0 0 0-1.006 0L3.622 5.689C3.24 5.88 3 6.27 3 6.695V19.18c0 .836.88 1.38 1.628 1.006l3.869-1.934c.317-.159.69-.159 1.006 0l4.994 2.497c.317.158.69.158 1.006 0Z"/></svg>
|
||
地图找房
|
||
<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="M13.5 4.5 21 12m0 0-7.5 7.5M21 12H3"/></svg>
|
||
</button>
|
||
<!-- 收起/展开 -->
|
||
<button @click="showFilters = !showFilters"
|
||
class="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>
|
||
<!-- 搜索提示 -->
|
||
<p class="mt-1.5 text-xs text-neutral-400">搜索历史在后台记录,请勿违规!</p>
|
||
|
||
<!-- 关注小区提示条(P1)-->
|
||
<div x-data="{ show: true }" x-show="show"
|
||
class="mt-2 flex items-center gap-2 px-3 py-2 bg-warning-50 border border-warning-200 rounded-lg text-sm">
|
||
<svg class="w-4 h-4 text-warning-600 flex-shrink-0" 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>
|
||
<span class="text-warning-700">
|
||
<a href="#" class="font-medium text-warning-700 hover:underline">配置关注小区</a>
|
||
(关注小区后,当该小区产生对应交易类型下的新上房源、降价房源时,系统将第一时间通知您,提升您的作业效率哦!)
|
||
</span>
|
||
<button @click="show = false" class="ml-auto 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 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 flex-wrap">
|
||
<span class="text-neutral-400 text-xs w-8 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"> 最新挂牌
|
||
</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"> 最新降价
|
||
</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>
|
||
<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 x-data="{ open: false }" @click.away="open=false" class="relative">
|
||
<button @click="open=!open" class="flex items-center gap-1 text-sm text-neutral-600 hover:text-primary-600">
|
||
收藏房源 <svg class="w-3 h-3" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5"/></svg>
|
||
</button>
|
||
<div x-show="open" x-cloak class="absolute left-0 top-full mt-1 w-40 bg-white shadow-lg border border-neutral-200 rounded-lg z-50 py-1">
|
||
<label class="flex items-center gap-2 px-4 py-2 text-sm text-neutral-600 hover:bg-neutral-50 cursor-pointer">
|
||
<input type="checkbox" class="w-4 h-4 rounded accent-primary-600"> 我的收藏
|
||
</label>
|
||
</div>
|
||
</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"> 超时未跟进房源
|
||
</label>
|
||
</div>
|
||
|
||
<div class="border-t border-neutral-100"></div>
|
||
|
||
<!-- 区域 -->
|
||
<div class="flex items-start gap-2 text-sm flex-wrap">
|
||
<span class="text-neutral-400 text-xs w-8 shrink-0 mt-1">区域</span>
|
||
<div class="flex items-center gap-1.5 flex-wrap flex-1">
|
||
<template x-for="d in ['浦东','徐汇','静安','黄浦','长宁','杨浦','普陀','宝山','闵行','嘉定','松江','奉贤','青浦','金山']" :key="d">
|
||
<button @click="toggleDistrict(d)"
|
||
:class="selectedDistricts.includes(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"
|
||
x-text="d"></button>
|
||
</template>
|
||
<div x-data="{ open: false }" @click.away="open=false" class="relative ml-1">
|
||
<button @click="open=!open" class="flex items-center gap-1 px-3 py-1 text-xs border border-neutral-200 rounded-md text-neutral-600 hover:border-primary-400 hover:text-primary-600 transition-colors">
|
||
地铁 <svg class="w-3 h-3" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5"/></svg>
|
||
</button>
|
||
<div x-show="open" x-cloak class="absolute left-0 top-full mt-1 w-56 bg-white shadow-lg border border-neutral-200 rounded-lg z-50 py-2 px-3">
|
||
<p class="text-xs text-neutral-400">选择地铁线路 → 选择站点(联动)</p>
|
||
<div class="mt-1 space-y-1">
|
||
<button class="w-full text-left px-2 py-1 text-xs text-neutral-700 hover:bg-neutral-50 rounded">1号线</button>
|
||
<button class="w-full text-left px-2 py-1 text-xs text-neutral-700 hover:bg-neutral-50 rounded">2号线</button>
|
||
<button class="w-full text-left px-2 py-1 text-xs text-neutral-700 hover:bg-neutral-50 rounded">4号线</button>
|
||
<button class="w-full text-left px-2 py-1 text-xs text-neutral-500 hover:bg-neutral-50 rounded">…更多</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 价格 -->
|
||
<div class="flex items-start gap-2 text-sm flex-wrap">
|
||
<span class="text-neutral-400 text-xs w-8 shrink-0 mt-1">价格</span>
|
||
<div class="flex-1 space-y-1.5">
|
||
<!-- 售价/单价/租价 切换 -->
|
||
<div class="flex items-center gap-1 mb-1">
|
||
<button :class="priceMode === 'sale' ? 'text-primary-600 font-medium' : 'text-neutral-500'"
|
||
class="text-xs hover:text-primary-600 transition-colors"
|
||
@click="priceMode = 'sale'">售价</button>
|
||
<span class="text-neutral-300">|</span>
|
||
<button :class="priceMode === 'unit' ? 'text-primary-600 font-medium' : 'text-neutral-500'"
|
||
class="text-xs hover:text-primary-600 transition-colors"
|
||
@click="priceMode = 'unit'">单价</button>
|
||
<span class="text-neutral-300" x-show="activeTab !== 'for_sale'">|</span>
|
||
<button x-show="activeTab !== 'for_sale'"
|
||
:class="priceMode === 'rent' ? 'text-primary-600 font-medium' : 'text-neutral-500'"
|
||
class="text-xs hover:text-primary-600 transition-colors"
|
||
@click="priceMode = 'rent'">租价</button>
|
||
</div>
|
||
<div class="flex items-center gap-1.5 flex-wrap">
|
||
<button @click="selectedPrice=''"
|
||
:class="selectedPrice==='' ? '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>
|
||
<template x-for="p in ['200万以下','250-300万','300-400万','400-500万','500-700万','700-1000万','1000-1500万','1500-2000万','2000万以上']" :key="p">
|
||
<button @click="selectedPrice=p"
|
||
:class="selectedPrice===p ? '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"
|
||
x-text="p"></button>
|
||
</template>
|
||
</div>
|
||
<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>
|
||
|
||
<!-- 面积 -->
|
||
<div class="flex items-start gap-2 text-sm flex-wrap">
|
||
<span class="text-neutral-400 text-xs w-8 shrink-0 mt-1">面积</span>
|
||
<div class="flex-1 space-y-1.5">
|
||
<div class="flex items-center gap-1.5 flex-wrap">
|
||
<button @click="selectedArea=''"
|
||
:class="selectedArea==='' ? '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>
|
||
<template x-for="a in ['50㎡以下','50-70㎡','70-90㎡','90-110㎡','110-130㎡','130-150㎡','150㎡以上']" :key="a">
|
||
<button @click="selectedArea=a"
|
||
:class="selectedArea===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"
|
||
x-text="a"></button>
|
||
</template>
|
||
</div>
|
||
<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">m²</span>
|
||
</div>
|
||
</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-8 shrink-0">房型</span>
|
||
<button @click="selectedRooms.includes('1') ? selectedRooms = selectedRooms.filter(x=>x!=='1') : selectedRooms.push('1')"
|
||
:class="selectedRooms.includes('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="selectedRooms.includes('2') ? selectedRooms = selectedRooms.filter(x=>x!=='2') : selectedRooms.push('2')"
|
||
:class="selectedRooms.includes('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="selectedRooms.includes('3') ? selectedRooms = selectedRooms.filter(x=>x!=='3') : selectedRooms.push('3')"
|
||
:class="selectedRooms.includes('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="selectedRooms.includes('4') ? selectedRooms = selectedRooms.filter(x=>x!=='4') : selectedRooms.push('4')"
|
||
:class="selectedRooms.includes('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="selectedRooms.includes('5+') ? selectedRooms = selectedRooms.filter(x=>x!=='5+') : selectedRooms.push('5+')"
|
||
:class="selectedRooms.includes('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>
|
||
</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-8 shrink-0">楼层</span>
|
||
<template x-for="f in ['低层(1-3层)','中层(4-9层)','高层(10层+)','顶楼','底楼']" :key="f">
|
||
<button @click="selectedFloors.includes(f) ? selectedFloors = selectedFloors.filter(x=>x!==f) : selectedFloors.push(f)"
|
||
:class="selectedFloors.includes(f) ? '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"
|
||
x-text="f"></button>
|
||
</template>
|
||
<div class="flex items-center gap-1.5 ml-1">
|
||
<input type="number" placeholder="最低层" class="w-16 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-16 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-8 shrink-0">标签</span>
|
||
<template x-for="t in ['速销','独家','有钥匙','电梯','唯一','有照片','贷款','视频','AI视频','有VR','3D','一键装换','一般委托']" :key="t">
|
||
<label class="flex items-center gap-1 cursor-pointer text-neutral-600 hover:text-primary-600">
|
||
<input type="checkbox" class="w-3.5 h-3.5 rounded accent-primary-600">
|
||
<span class="text-xs" x-text="t"></span>
|
||
</label>
|
||
</template>
|
||
</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>
|
||
</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 gap-4 flex-wrap 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>
|
||
</select>
|
||
<span class="text-neutral-400 text-xs 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>
|
||
</select>
|
||
</div>
|
||
|
||
<!-- 装修 / 朝向 / 房屋现状 -->
|
||
<div class="flex items-center gap-4 flex-wrap 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>
|
||
</select>
|
||
<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>
|
||
<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 gap-4 flex-wrap 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>
|
||
</select>
|
||
<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>
|
||
</select>
|
||
<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>
|
||
</select>
|
||
<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>
|
||
<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>0-25%</option><option>25-50%</option><option>50-75%</option><option>75-100%</option>
|
||
</select>
|
||
</div>
|
||
|
||
<!-- 挂牌日期 -->
|
||
<div class="flex items-center gap-4 flex-wrap 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 class="flex items-center gap-3 mt-3 pt-3 border-t border-neutral-100">
|
||
<button class="px-5 py-2 bg-primary-600 hover:bg-primary-700 text-white text-sm font-medium rounded-lg transition-colors">查询</button>
|
||
<button class="px-5 py-2 text-sm text-neutral-600 border border-neutral-300 rounded-lg hover:bg-neutral-50 transition-colors">重置</button>
|
||
<!-- 已存搜索(P1) -->
|
||
<div x-data="{ open: false }" @click.away="open=false" class="relative">
|
||
<button @click="open=!open" class="flex items-center gap-1 text-sm text-neutral-500 hover:text-neutral-700">
|
||
<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>
|
||
已存搜索条件
|
||
<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-60 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>浦东·三室·400-600万</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">
|
||
<span x-text="showFilters ? '收起更多 ∧' : '展开更多 ∨'"></span>
|
||
</button>
|
||
</div>
|
||
|
||
</div><!-- /筛选区 -->
|
||
</div><!-- /搜索筛选卡 -->
|
||
|
||
<!-- ============ 数据表格区域 ============ -->
|
||
<div id="property-list-container">
|
||
<div class="rounded-lg border border-neutral-200 overflow-hidden bg-white">
|
||
|
||
<!-- 工具栏 -->
|
||
<div class="flex items-center gap-2 px-4 py-2.5 border-b border-neutral-100">
|
||
<!-- 左侧:视图切换 + 批量操作 -->
|
||
<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.75 6A2.25 2.25 0 0 1 6 3.75h2.25A2.25 2.25 0 0 1 10.5 6v2.25a2.25 2.25 0 0 1-2.25 2.25H6a2.25 2.25 0 0 1-2.25-2.25V6ZM3.75 15.75A2.25 2.25 0 0 1 6 13.5h2.25a2.25 2.25 0 0 1 2.25 2.25V18a2.25 2.25 0 0 1-2.25 2.25H6A2.25 2.25 0 0 1 3.75 18v-2.25ZM13.5 6a2.25 2.25 0 0 1 2.25-2.25H18A2.25 2.25 0 0 1 20.25 6v2.25A2.25 2.25 0 0 1 18 10.5h-2.25a2.25 2.25 0 0 1-2.25-2.25V6ZM13.5 15.75a2.25 2.25 0 0 1 2.25-2.25H18a2.25 2.25 0 0 1 2.25 2.25V18A2.25 2.25 0 0 1 18 20.25h-2.25A2.25 2.25 0 0 1 13.5 18v-2.25Z"/></svg>
|
||
房源海报
|
||
</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-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-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>
|
||
<!-- 更多批量 -->
|
||
<div x-data="{ open: false }" @click.away="open=false" class="relative">
|
||
<button @click="open=!open"
|
||
: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="flex items-center gap-1 px-3 py-1.5 text-sm border rounded-md transition-colors">
|
||
更多 <svg class="w-3 h-3" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5"/></svg>
|
||
</button>
|
||
<div x-show="open" x-cloak class="absolute left-0 top-full mt-1 w-28 bg-white shadow-lg border border-neutral-200 rounded-lg z-50 py-1">
|
||
<button class="w-full text-left px-4 py-2 text-sm text-danger-600 hover:bg-danger-50">删除</button>
|
||
</div>
|
||
</div>
|
||
<!-- 总条数 -->
|
||
<span class="text-sm text-neutral-500 ml-1">
|
||
共 <strong class="text-neutral-800 tabular-nums">3,629</strong> 条
|
||
</span>
|
||
<span x-show="selectedCount > 0" class="text-sm text-primary-600">
|
||
已选 <span x-text="selectedCount" class="font-medium tabular-nums"></span> 条
|
||
</span>
|
||
<!-- 右侧工具 -->
|
||
<div class="flex items-center gap-2 ml-auto">
|
||
<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>
|
||
<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="M9.813 15.904 9 18.75l-.813-2.846a4.5 4.5 0 0 0-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 0 0 3.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 0 0 3.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 0 0-3.09 3.09ZM18.259 8.715 18 9.75l-.259-1.035a3.375 3.375 0 0 0-2.455-2.456L14.25 6l1.036-.259a3.375 3.375 0 0 0 2.455-2.456L18 2.25l.259 1.035a3.375 3.375 0 0 0 2.456 2.456L21.75 6l-1.035.259a3.375 3.375 0 0 0-2.456 2.456Z"/></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" 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-[200px]">房源名称</th>
|
||
<th class="px-4 py-3 text-left text-xs font-semibold text-neutral-500 uppercase tracking-wide whitespace-nowrap w-16">楼栋</th>
|
||
<th class="px-4 py-3 text-left text-xs font-semibold text-neutral-500 uppercase tracking-wide whitespace-nowrap w-16">单元</th>
|
||
<th class="px-4 py-3 text-left text-xs font-semibold text-neutral-500 uppercase tracking-wide whitespace-nowrap w-16">房号</th>
|
||
<th class="px-4 py-3 text-left text-xs font-semibold text-neutral-500 uppercase tracking-wide whitespace-nowrap min-w-[100px]">区域板块</th>
|
||
<th class="px-4 py-3 text-left text-xs font-semibold text-neutral-500 uppercase tracking-wide whitespace-nowrap w-16">状态</th>
|
||
<!-- 售价(出租 Tab 隐藏) -->
|
||
<th x-show="activeTab !== 'for_rent'"
|
||
class="px-4 py-3 text-right 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>
|
||
<!-- 单价(出租 Tab 隐藏) -->
|
||
<th x-show="activeTab !== 'for_rent'"
|
||
class="px-4 py-3 text-right text-xs font-semibold text-neutral-500 uppercase tracking-wide whitespace-nowrap w-28 cursor-pointer hover:bg-neutral-100 select-none">
|
||
单价(元/m²)
|
||
<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>
|
||
<!-- 租价(出售 Tab 隐藏) -->
|
||
<th x-show="activeTab !== 'for_sale'"
|
||
class="px-4 py-3 text-right text-xs font-semibold text-neutral-500 uppercase tracking-wide whitespace-nowrap w-28 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-right text-xs font-semibold text-neutral-500 uppercase tracking-wide whitespace-nowrap w-20 cursor-pointer hover:bg-neutral-100 select-none">
|
||
面积(m²)
|
||
<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-16">户型</th>
|
||
<th class="px-4 py-3 text-left text-xs font-semibold text-neutral-500 uppercase tracking-wide whitespace-nowrap w-16">楼层</th>
|
||
<th class="px-4 py-3 text-left text-xs font-semibold text-neutral-500 uppercase tracking-wide whitespace-nowrap w-12">朝向</th>
|
||
<th class="px-4 py-3 text-left text-xs font-semibold text-neutral-500 uppercase tracking-wide whitespace-nowrap w-28 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-28 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"/></svg>
|
||
</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="property-table-body" class="divide-y divide-neutral-100 bg-white">
|
||
<template x-for="prop in properties" :key="prop.id">
|
||
<tr class="hover:bg-neutral-50 transition-colors"
|
||
:class="[
|
||
selected.includes(prop.id) ? 'bg-primary-50 hover:bg-primary-100' : '',
|
||
prop.status === 'sold' ? 'opacity-70' : ''
|
||
]"
|
||
style="min-height:56px">
|
||
|
||
<!-- 复选框 -->
|
||
<td class="w-10 px-4 align-middle text-center">
|
||
<input type="checkbox" class="w-4 h-4 rounded accent-primary-600 cursor-pointer"
|
||
:value="prop.id" x-model="selected">
|
||
</td>
|
||
|
||
<!-- 房源名称 -->
|
||
<td class="px-4 py-2 align-middle min-w-[200px] max-w-[280px]">
|
||
<div class="flex flex-col gap-0.5">
|
||
<!-- 交易类型 Badge + 名称链接 -->
|
||
<div class="flex items-center gap-1.5 flex-wrap">
|
||
<span class="text-xs px-2 py-0.5 rounded font-semibold flex-shrink-0"
|
||
:class="prop.transaction_cls"
|
||
x-text="prop.transaction_label"></span>
|
||
<a href="#"
|
||
class="text-info-600 hover:underline font-medium text-sm truncate max-w-[180px]"
|
||
x-text="prop.complex"></a>
|
||
</div>
|
||
<!-- 附加标签行 -->
|
||
<div class="flex items-center gap-1 flex-wrap">
|
||
<template x-for="tag in prop.tags" :key="tag.label">
|
||
<span class="text-[10px] px-1.5 py-0.5 rounded-sm font-medium"
|
||
:class="tag.cls"
|
||
x-text="tag.label"></span>
|
||
</template>
|
||
</div>
|
||
</div>
|
||
</td>
|
||
|
||
<!-- 楼栋 -->
|
||
<td class="px-4 py-2 align-middle w-16">
|
||
<span class="text-sm text-neutral-700" x-text="prop.block_no || '-'"></span>
|
||
</td>
|
||
<!-- 单元 -->
|
||
<td class="px-4 py-2 align-middle w-16">
|
||
<span class="text-sm text-neutral-700" x-text="prop.unit_no || '-'"></span>
|
||
</td>
|
||
<!-- 房号 -->
|
||
<td class="px-4 py-2 align-middle w-16">
|
||
<span class="text-sm text-neutral-700" x-text="prop.room_no || '-'"></span>
|
||
</td>
|
||
|
||
<!-- 区域板块 -->
|
||
<td class="px-4 py-2 align-middle min-w-[100px]">
|
||
<div class="flex flex-col">
|
||
<span class="text-sm text-neutral-700" x-text="prop.district"></span>
|
||
<span class="text-xs text-neutral-400" x-text="prop.business_area"></span>
|
||
</div>
|
||
</td>
|
||
|
||
<!-- 状态 -->
|
||
<td class="px-4 py-2 align-middle w-16 whitespace-nowrap">
|
||
<span class="text-xs px-2 py-0.5 rounded-full font-medium"
|
||
:class="prop.status_cls"
|
||
x-text="prop.status_label"></span>
|
||
</td>
|
||
|
||
<!-- 售价(出租 Tab 隐藏) -->
|
||
<td class="px-4 py-2 align-middle text-right w-24 whitespace-nowrap" x-show="activeTab !== 'for_rent'">
|
||
<template x-if="prop.sale_price">
|
||
<div class="flex flex-col items-end gap-0.5">
|
||
<span class="text-sm font-medium text-neutral-800 tabular-nums" x-text="prop.sale_price"></span>
|
||
<template x-if="prop.price_trend === 'down'">
|
||
<span class="text-[10px] text-danger-600 flex items-center gap-0.5">
|
||
<svg class="w-3 h-3" fill="none" stroke="currentColor" stroke-width="2.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M19.5 13.5 12 21m0 0-7.5-7.5M12 21V3"/></svg>
|
||
</span>
|
||
</template>
|
||
<template x-if="prop.price_trend === 'up'">
|
||
<span class="text-[10px] text-success-600 flex items-center gap-0.5">
|
||
<svg class="w-3 h-3" fill="none" stroke="currentColor" stroke-width="2.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M4.5 10.5 12 3m0 0 7.5 7.5M12 3v18"/></svg>
|
||
</span>
|
||
</template>
|
||
</div>
|
||
</template>
|
||
<template x-if="!prop.sale_price">
|
||
<span class="text-sm text-neutral-400">-</span>
|
||
</template>
|
||
</td>
|
||
|
||
<!-- 单价(出租 Tab 隐藏) -->
|
||
<td class="px-4 py-2 align-middle text-right w-28 whitespace-nowrap" x-show="activeTab !== 'for_rent'">
|
||
<span class="text-sm text-neutral-700 tabular-nums" x-text="prop.sale_unit_price || '-'"></span>
|
||
</td>
|
||
|
||
<!-- 租价(出售 Tab 隐藏) -->
|
||
<td class="px-4 py-2 align-middle text-right w-28 whitespace-nowrap" x-show="activeTab !== 'for_sale'">
|
||
<span class="text-sm text-neutral-700 tabular-nums" x-text="prop.rent_price || '-'"></span>
|
||
</td>
|
||
|
||
<!-- 面积 -->
|
||
<td class="px-4 py-2 align-middle text-right w-20">
|
||
<span class="text-sm text-neutral-700 tabular-nums" x-text="prop.area"></span>
|
||
</td>
|
||
|
||
<!-- 户型 -->
|
||
<td class="px-4 py-2 align-middle w-16 whitespace-nowrap">
|
||
<span class="text-sm text-neutral-700" x-text="prop.layout"></span>
|
||
</td>
|
||
|
||
<!-- 楼层 -->
|
||
<td class="px-4 py-2 align-middle w-16 whitespace-nowrap">
|
||
<span class="text-sm text-neutral-700" x-text="prop.floor || '-'"></span>
|
||
</td>
|
||
|
||
<!-- 朝向 -->
|
||
<td class="px-4 py-2 align-middle w-12 whitespace-nowrap">
|
||
<span class="text-sm text-neutral-700" x-text="prop.orientation || '-'"></span>
|
||
</td>
|
||
|
||
<!-- 挂牌日期 -->
|
||
<td class="px-4 py-2 align-middle w-28 whitespace-nowrap">
|
||
<span class="text-sm text-neutral-700 tabular-nums" x-text="prop.listed_at || '-'"></span>
|
||
</td>
|
||
|
||
<!-- 最后跟进日 -->
|
||
<td class="px-4 py-2 align-middle w-28 whitespace-nowrap">
|
||
<span class="text-sm tabular-nums"
|
||
:class="prop.follow_overdue ? 'text-danger-600' : 'text-neutral-700'"
|
||
x-text="prop.last_followed_at || '-'"></span>
|
||
</td>
|
||
|
||
</tr>
|
||
</template>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
</div><!-- /table wrapper -->
|
||
</div><!-- /#property-list-container -->
|
||
|
||
<!-- ============ 分页栏 ============ -->
|
||
<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">3,629</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">182</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="182"
|
||
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="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: 'grade', label: '等级' },
|
||
{ id: 'attribute', label: '属性' },
|
||
{ id: 'decoration', label: '装修' },
|
||
{ id: 'built_year', label: '建成年代' },
|
||
{ id: 'source', label: '来源' },
|
||
{ id: 'completeness', label: '维护完成度' },
|
||
{ id: 'seller_agent', label: '出售方' },
|
||
{ id: 'first_recorder', label: '首录方' }
|
||
],
|
||
selected: [
|
||
{ id: 'name', label: '房源名称', locked: true },
|
||
{ id: 'block_no', label: '楼栋', locked: false },
|
||
{ id: 'unit_no', label: '单元', locked: false },
|
||
{ id: 'room_no', label: '房号', locked: false },
|
||
{ id: 'district', label: '区域板块', locked: false },
|
||
{ id: 'status', label: '状态', locked: false },
|
||
{ id: 'sale_price', label: '售价(万)', locked: false },
|
||
{ id: 'sale_unit_price', label: '单价(元/m²)', locked: false },
|
||
{ id: 'rent_price', label: '租价(元/月)', locked: false },
|
||
{ id: 'area', label: '面积(m²)', locked: false },
|
||
{ id: 'layout', label: '户型', locked: false },
|
||
{ id: 'floor', label: '楼层', locked: false },
|
||
{ id: 'orientation', label: '朝向', locked: false },
|
||
{ id: 'listed_at', label: '挂牌日期', locked: false },
|
||
{ id: 'last_followed_at', 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);
|
||
}
|
||
}">
|
||
<!-- 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="w-5 h-5 flex items-center justify-center text-neutral-300 hover:text-danger-600 opacity-0 group-hover:opacity-100 transition-opacity 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>
|
||
</div>
|
||
<!-- Footer -->
|
||
<div class="flex items-center justify-between px-5 py-3 border-t border-neutral-200 bg-neutral-50">
|
||
<button class="text-sm text-neutral-500 hover:text-neutral-700">恢复默认</button>
|
||
<div class="flex items-center gap-2">
|
||
<button @click="showColumnModal = false" class="px-4 py-2 text-sm border border-neutral-300 rounded-lg hover:bg-white text-neutral-700">取消</button>
|
||
<button @click="showColumnModal = false" class="px-4 py-2 text-sm bg-primary-600 hover:bg-primary-700 text-white rounded-lg font-medium transition-colors">确定</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div><!-- /主容器 -->
|
||
|
||
<script>
|
||
// 静态原型串联:从登录页跳转后显示一次登录成功提示
|
||
(function () {
|
||
const params = new URLSearchParams(window.location.search);
|
||
if (params.get('from') === 'login' && params.get('login') === 'success') {
|
||
const displayName = params.get('name') || '经纪人';
|
||
const toast = document.createElement('div');
|
||
toast.className = 'fixed bottom-6 right-6 z-[70] w-80 bg-white rounded-lg shadow-lg border border-neutral-200 flex items-start gap-3 p-3';
|
||
toast.innerHTML = `
|
||
<svg class="w-5 h-5 text-success-600 mt-0.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24" aria-hidden="true">
|
||
<path stroke-linecap="round" stroke-linejoin="round" d="m4.5 12.75 6 6 9-13.5" />
|
||
</svg>
|
||
<div class="min-w-0">
|
||
<p class="text-sm font-medium text-neutral-800">登录成功</p>
|
||
<p class="text-xs text-neutral-500 mt-0.5">欢迎回来,${displayName}</p>
|
||
</div>
|
||
`;
|
||
document.body.appendChild(toast);
|
||
setTimeout(() => {
|
||
toast.style.transition = 'opacity .25s ease';
|
||
toast.style.opacity = '0';
|
||
setTimeout(() => toast.remove(), 260);
|
||
}, 2200);
|
||
}
|
||
})();
|
||
</script>
|
||
|
||
</body>
|
||
</html>
|