875 lines
50 KiB
HTML
875 lines
50 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=1280" />
|
||
<title>Fonrey 楼盘详情 · 静态原型</title>
|
||
<script src="https://cdn.tailwindcss.com"></script>
|
||
<script src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js" defer></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)'
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
<style>
|
||
:root {
|
||
--bg-page: #F8FAFC;
|
||
--bg-card: #FFFFFF;
|
||
--bg-subtle: #F1F5F9;
|
||
--text-primary: #0F172A;
|
||
--text-secondary: #64748B;
|
||
--border: #E2E8F0;
|
||
}
|
||
|
||
html { scroll-behavior: smooth; }
|
||
body {
|
||
background: var(--bg-page);
|
||
color: var(--text-primary);
|
||
font-family: Inter, 'PingFang SC', 'Microsoft YaHei', sans-serif;
|
||
}
|
||
|
||
[x-cloak] { display: none !important; }
|
||
.tabular-nums { font-variant-numeric: tabular-nums; }
|
||
.bg-surface { background: var(--bg-card); }
|
||
.bg-subtle { background: var(--bg-subtle); }
|
||
.border-surface { border-color: var(--border); }
|
||
.text-surface { color: var(--text-primary); }
|
||
.text-muted { color: var(--text-secondary); }
|
||
|
||
.tab-btn {
|
||
color: #64748B;
|
||
border-bottom: 2px solid transparent;
|
||
}
|
||
.tab-btn.active {
|
||
color: #0F766E;
|
||
border-bottom-color: #0F766E;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.badge-lock {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
font-size: 12px;
|
||
line-height: 1;
|
||
padding: 4px 8px;
|
||
border-radius: 999px;
|
||
border: 1px solid #DC2626;
|
||
color: #DC2626;
|
||
background: #FEF2F2;
|
||
}
|
||
|
||
.subtab-pill {
|
||
border: 1px solid #E2E8F0;
|
||
background: #FFFFFF;
|
||
color: #64748B;
|
||
}
|
||
.subtab-pill.active {
|
||
border-color: #0F766E;
|
||
color: #0F766E;
|
||
background: #F0FDFA;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.left-item {
|
||
border: 1px solid #E2E8F0;
|
||
background: #FFFFFF;
|
||
color: #334155;
|
||
}
|
||
.left-item.active {
|
||
border-color: #0F766E;
|
||
background: #F0FDFA;
|
||
color: #0F766E;
|
||
}
|
||
|
||
::-webkit-scrollbar { width: 8px; height: 8px; }
|
||
::-webkit-scrollbar-thumb { background: #CBD5E1; border-radius: 4px; }
|
||
::-webkit-scrollbar-thumb:hover { background: #94A3B8; }
|
||
</style>
|
||
</head>
|
||
<body class="text-sm antialiased" x-data="complexDetailPage()" x-init="init()">
|
||
<!-- Top Bar -->
|
||
<header class="fixed top-0 left-0 right-0 h-14 z-20 bg-primary-800 flex items-center justify-between">
|
||
<div class="flex items-center gap-2 px-4 w-60 shrink-0">
|
||
<div class="w-7 h-7 rounded-md bg-primary-500 flex items-center justify-center text-white text-sm font-semibold">F</div>
|
||
<span class="text-base font-semibold text-white">Fonrey</span>
|
||
</div>
|
||
<nav class="flex items-center gap-1 flex-1 px-2" aria-label="主导航">
|
||
<a class="px-3 py-1.5 text-sm rounded-md text-primary-100 hover:bg-primary-700 hover:text-white">工作台</a>
|
||
<a class="px-3 py-1.5 text-sm rounded-md bg-primary-600 text-white font-medium">房源</a>
|
||
<a class="px-3 py-1.5 text-sm rounded-md text-primary-100 hover:bg-primary-700 hover:text-white">客源</a>
|
||
<a class="px-3 py-1.5 text-sm rounded-md text-primary-100 hover:bg-primary-700 hover:text-white">营销</a>
|
||
<a class="px-3 py-1.5 text-sm rounded-md text-primary-100 hover:bg-primary-700 hover:text-white">交易</a>
|
||
<a class="px-3 py-1.5 text-sm rounded-md text-primary-100 hover:bg-primary-700 hover:text-white">数据</a>
|
||
<a class="px-3 py-1.5 text-sm rounded-md text-primary-100 hover:bg-primary-700 hover:text-white">人事</a>
|
||
<a class="px-3 py-1.5 text-sm rounded-md text-primary-100 hover:bg-primary-700 hover:text-white">系统</a>
|
||
</nav>
|
||
<div class="flex items-center gap-1 px-4 shrink-0">
|
||
<button class="p-1.5 text-primary-200 hover:bg-primary-700 hover:text-white rounded-md" aria-label="消息">
|
||
<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>
|
||
</button>
|
||
<div class="flex items-center gap-2 pl-3 ml-1 border-l border-primary-700">
|
||
<div class="w-8 h-8 rounded-full bg-primary-600 text-white flex items-center justify-center text-sm font-semibold">魏</div>
|
||
<span class="text-sm font-medium text-primary-100">魏深</span>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
|
||
<!-- Sidebar -->
|
||
<aside class="fixed left-0 top-14 h-[calc(100vh-56px)] w-60 z-20 border-r border-surface bg-surface overflow-y-auto">
|
||
<nav class="p-3 space-y-0.5">
|
||
<div class="px-2 pt-2 pb-1 text-xs font-medium text-muted 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">楼盘管理</a>
|
||
<a class="flex items-center gap-2 px-2 py-1.5 rounded-md text-neutral-700 hover:bg-neutral-100">房源列表</a>
|
||
<a class="flex items-center gap-2 px-2 py-1.5 rounded-md text-neutral-700 hover:bg-neutral-100">新增房源</a>
|
||
<a class="flex items-center gap-2 px-2 py-1.5 rounded-md text-neutral-700 hover:bg-neutral-100">成交房源</a>
|
||
<a class="flex items-center gap-2 px-2 py-1.5 rounded-md text-neutral-700 hover:bg-neutral-100">已删房源</a>
|
||
</nav>
|
||
</aside>
|
||
|
||
<!-- Main -->
|
||
<main class="ml-60 pt-[72px] min-h-screen px-6 py-5">
|
||
<div class="mx-auto max-w-[1680px] space-y-4">
|
||
<!-- Header Card -->
|
||
<section class="bg-surface border border-surface rounded-lg p-4 space-y-3">
|
||
<nav class="flex items-center gap-1 text-xs text-muted" aria-label="面包屑">
|
||
<a href="#" class="hover:text-neutral-700">房源</a>
|
||
<span>/</span>
|
||
<a href="#" class="hover:text-neutral-700">小区</a>
|
||
<span>/</span>
|
||
<a href="#" class="hover:text-neutral-700">楼盘管理系统-楼盘管理</a>
|
||
<span>/</span>
|
||
<span class="text-surface">楼盘详情</span>
|
||
</nav>
|
||
|
||
<div class="flex items-start justify-between gap-4">
|
||
<div class="space-y-2">
|
||
<h1 class="text-xl font-semibold text-surface">阳光威尼斯四期(别墅)</h1>
|
||
<p class="text-xs text-muted">恒盛提香湾 / 璟聚人生 / 祁连山南路2727弄 / 金鼎路1600弄</p>
|
||
<div class="flex items-center gap-2 flex-wrap">
|
||
<span class="badge-lock">
|
||
<svg class="w-3.5 h-3.5" 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-3 0h15a1.5 1.5 0 0 1 1.5 1.5v7.5a1.5 1.5 0 0 1-1.5 1.5h-15A1.5 1.5 0 0 1 3 19.5V12a1.5 1.5 0 0 1 1.5-1.5Z"/></svg>
|
||
楼栋锁
|
||
</span>
|
||
<span class="badge-lock"><svg class="w-3.5 h-3.5" 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-3 0h15a1.5 1.5 0 0 1 1.5 1.5v7.5a1.5 1.5 0 0 1-1.5 1.5h-15A1.5 1.5 0 0 1 3 19.5V12a1.5 1.5 0 0 1 1.5-1.5Z"/></svg>房号</span>
|
||
<span class="badge-lock"><svg class="w-3.5 h-3.5" 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-3 0h15a1.5 1.5 0 0 1 1.5 1.5v7.5a1.5 1.5 0 0 1-1.5 1.5h-15A1.5 1.5 0 0 1 3 19.5V12a1.5 1.5 0 0 1 1.5-1.5Z"/></svg>信息</span>
|
||
<span class="badge-lock"><svg class="w-3.5 h-3.5" 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-3 0h15a1.5 1.5 0 0 1 1.5 1.5v7.5a1.5 1.5 0 0 1-1.5 1.5h-15A1.5 1.5 0 0 1 3 19.5V12a1.5 1.5 0 0 1 1.5-1.5Z"/></svg>标准房号</span>
|
||
</div>
|
||
</div>
|
||
<div class="flex items-center gap-2">
|
||
<button class="px-3 py-1.5 rounded-md border border-neutral-300 text-neutral-700 hover:bg-neutral-50" @click="notify('已触发楼盘解锁流程(原型)')">解锁楼盘</button>
|
||
<button class="px-3 py-1.5 rounded-md bg-primary-600 text-white hover:bg-primary-700" @click="openEditDrawer()">编辑楼盘信息</button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Tabs -->
|
||
<section class="bg-surface border border-surface rounded-lg px-4">
|
||
<nav class="flex items-center gap-6 overflow-x-auto" aria-label="楼盘详情分区导航">
|
||
<template x-for="item in tabs" :key="item.key">
|
||
<button class="tab-btn py-3 whitespace-nowrap" :class="{ 'active': activeTab === item.key }" @click="activeTab = item.key" x-text="item.label"></button>
|
||
</template>
|
||
</nav>
|
||
</section>
|
||
|
||
<!-- 楼盘信息 -->
|
||
<section x-show="activeTab === 'info'" x-cloak class="grid grid-cols-12 gap-6 items-start">
|
||
<div class="col-span-8 space-y-4">
|
||
<article class="bg-surface border border-surface rounded-lg p-4">
|
||
<div class="flex items-center justify-between mb-3">
|
||
<h2 class="text-base font-semibold">基本信息</h2>
|
||
<p class="text-xs text-info-600">楼盘地址有误?点此【纠错】</p>
|
||
</div>
|
||
<dl class="grid grid-cols-2 gap-x-8 gap-y-3 text-sm">
|
||
<div><dt class="text-xs text-muted">城区商圈</dt><dd class="mt-0.5">普陀-真光</dd></div>
|
||
<div><dt class="text-xs text-muted">小区地址</dt><dd class="mt-0.5">上海普陀金鼎路1600弄,祁连山南路2727弄</dd></div>
|
||
<div><dt class="text-xs text-muted">楼栋结构</dt><dd class="mt-0.5">单元-房号</dd></div>
|
||
<div><dt class="text-xs text-muted">概要地址</dt><dd class="mt-0.5">金鼎路1600弄,祁连山南路2727弄</dd></div>
|
||
<div><dt class="text-xs text-muted">小区别名</dt><dd class="mt-0.5">恒盛提香湾,璟聚人生,阳光建华城</dd></div>
|
||
<div><dt class="text-xs text-muted">建筑类型</dt><dd class="mt-0.5">板塔结合</dd></div>
|
||
<div><dt class="text-xs text-muted">物业类型</dt><dd class="mt-0.5">别墅</dd></div>
|
||
<div><dt class="text-xs text-muted">土地使用年限</dt><dd class="mt-0.5">70年</dd></div>
|
||
<div><dt class="text-xs text-muted">竣工年限</dt><dd class="mt-0.5">2009</dd></div>
|
||
<div><dt class="text-xs text-muted">权属类别</dt><dd class="mt-0.5">商品房住宅</dd></div>
|
||
<div><dt class="text-xs text-muted">单元总数</dt><dd class="mt-0.5">96栋</dd></div>
|
||
<div><dt class="text-xs text-muted">总户数</dt><dd class="mt-0.5">96户</dd></div>
|
||
<div class="col-span-2"><dt class="text-xs text-muted">小区坐标</dt><dd class="mt-0.5 tabular-nums">31.264564,121.376238</dd></div>
|
||
</dl>
|
||
</article>
|
||
|
||
<article class="bg-surface border border-surface rounded-lg p-4">
|
||
<div class="flex items-center justify-between mb-3">
|
||
<h2 class="text-base font-semibold">对口学校</h2>
|
||
<button class="px-3 py-1.5 rounded-md border border-neutral-300 hover:bg-neutral-50" @click="notify('打开学校关联弹窗(原型)')">+ 添加学校</button>
|
||
</div>
|
||
<div class="overflow-x-auto">
|
||
<table class="min-w-full text-sm">
|
||
<thead class="bg-subtle border-y border-surface">
|
||
<tr>
|
||
<th scope="col" class="px-3 py-2 text-left">学校名称</th>
|
||
<th scope="col" class="px-3 py-2 text-left">学校类型</th>
|
||
<th scope="col" class="px-3 py-2 text-left">学校性质</th>
|
||
<th scope="col" class="px-3 py-2 text-left">学校等级</th>
|
||
<th scope="col" class="px-3 py-2 text-left">操作</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<template x-if="schools.length === 0">
|
||
<tr><td colspan="5" class="px-3 py-8 text-center text-muted">暂无数据</td></tr>
|
||
</template>
|
||
<template x-for="row in schools" :key="row.name">
|
||
<tr class="border-b border-surface">
|
||
<td class="px-3 py-2" x-text="row.name"></td>
|
||
<td class="px-3 py-2" x-text="row.type"></td>
|
||
<td class="px-3 py-2" x-text="row.nature"></td>
|
||
<td class="px-3 py-2" x-text="row.level"></td>
|
||
<td class="px-3 py-2"><button class="text-danger-600 hover:underline" @click="notify('删除学校关联(原型)')">删除</button></td>
|
||
</tr>
|
||
</template>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</article>
|
||
|
||
<article class="bg-surface border border-surface rounded-lg p-4">
|
||
<h2 class="text-base font-semibold mb-3">其他信息</h2>
|
||
<dl class="grid grid-cols-2 gap-x-8 gap-y-3 text-sm">
|
||
<div><dt class="text-xs text-muted">小区总建筑面积</dt><dd class="mt-0.5 tabular-nums">80000㎡</dd></div>
|
||
<div><dt class="text-xs text-muted">小区占地面积</dt><dd class="mt-0.5 tabular-nums">50000㎡</dd></div>
|
||
<div><dt class="text-xs text-muted">容积率</dt><dd class="mt-0.5 tabular-nums">1.60</dd></div>
|
||
<div><dt class="text-xs text-muted">绿化率</dt><dd class="mt-0.5 tabular-nums">45%</dd></div>
|
||
<div><dt class="text-xs text-muted">物业公司</dt><dd class="mt-0.5">阳光物业有限公司</dd></div>
|
||
<div><dt class="text-xs text-muted">物业费</dt><dd class="mt-0.5 tabular-nums">1.45 元/㎡/月</dd></div>
|
||
<div><dt class="text-xs text-muted">物业电话</dt><dd class="mt-0.5">-</dd></div>
|
||
<div><dt class="text-xs text-muted">开发商</dt><dd class="mt-0.5">上海意景房产开发有限公司</dd></div>
|
||
<div><dt class="text-xs text-muted">车位数(总)</dt><dd class="mt-0.5 tabular-nums">800 个</dd></div>
|
||
<div><dt class="text-xs text-muted">车位数(地下)</dt><dd class="mt-0.5">-</dd></div>
|
||
<div><dt class="text-xs text-muted">停车位配比</dt><dd class="mt-0.5">100:63</dd></div>
|
||
<div><dt class="text-xs text-muted">供水 / 供电</dt><dd class="mt-0.5">民水 / 民电</dd></div>
|
||
<div><dt class="text-xs text-muted">统一供暖</dt><dd class="mt-0.5">无</dd></div>
|
||
<div><dt class="text-xs text-muted">有无燃气</dt><dd class="mt-0.5">有</dd></div>
|
||
<div class="col-span-2"><dt class="text-xs text-muted">备注</dt><dd class="mt-0.5">本楼盘别墅区产品为主,房号结构基本标准化。</dd></div>
|
||
</dl>
|
||
</article>
|
||
</div>
|
||
|
||
<aside class="col-span-4 space-y-4 sticky top-[88px]">
|
||
<article class="bg-surface border border-surface rounded-lg p-4">
|
||
<h3 class="text-sm font-semibold mb-3">维护完成度</h3>
|
||
<div class="w-full h-2 rounded-full bg-neutral-200 overflow-hidden">
|
||
<div class="h-full bg-primary-600" style="width: 72%"></div>
|
||
</div>
|
||
<p class="text-xs text-muted mt-2">当前维护度 72%,建议补全学校和附件信息。</p>
|
||
</article>
|
||
|
||
<article class="bg-surface border border-surface rounded-lg p-4">
|
||
<h3 class="text-sm font-semibold mb-3">相关员工</h3>
|
||
<ul class="space-y-2 text-sm">
|
||
<li class="flex items-center justify-between"><span class="text-muted">首录人</span><span>李晨(普陀真光)</span></li>
|
||
<li class="flex items-center justify-between"><span class="text-muted">归属人</span><span>杜利强(运营)</span></li>
|
||
<li class="flex items-center justify-between"><span class="text-muted">最近更新</span><span class="tabular-nums">2026-04-28 15:20</span></li>
|
||
</ul>
|
||
</article>
|
||
|
||
<article class="bg-surface border border-surface rounded-lg p-4 space-y-2">
|
||
<button class="w-full px-3 py-2 rounded-md bg-primary-600 text-white hover:bg-primary-700" @click="openEditDrawer()">编辑楼盘信息</button>
|
||
<button class="w-full px-3 py-2 rounded-md border border-surface hover:bg-neutral-50" @click="notify('打开楼盘附件上传(原型)')">上传附件</button>
|
||
<button class="w-full px-3 py-2 rounded-md border border-surface hover:bg-neutral-50" @click="notify('查看楼盘操作日志(原型)')">查看操作日志</button>
|
||
</article>
|
||
</aside>
|
||
</section>
|
||
|
||
<!-- 楼栋管理 -->
|
||
<section x-show="activeTab === 'buildings'" x-cloak class="bg-surface border border-surface rounded-lg p-4 space-y-3">
|
||
<div class="flex items-center justify-between gap-3">
|
||
<div class="flex items-center gap-2">
|
||
<input x-model.trim="buildingKeyword" type="text" placeholder="单元" class="w-56 px-3 py-2 rounded-md border border-surface bg-white focus:outline-none focus:ring-2 focus:ring-primary-600/40" />
|
||
<button class="px-3 py-2 rounded-md bg-primary-600 text-white hover:bg-primary-700" @click="applyBuildingFilter()">搜索</button>
|
||
</div>
|
||
<p class="text-xs text-muted">本楼盘还有 <span class="text-danger-600 font-medium">0</span> 个非标准结构,<button class="text-primary-600 hover:underline" @click="notify('查看非标明细(原型)')">查看明细</button></p>
|
||
</div>
|
||
|
||
<div class="flex items-center gap-2 flex-wrap">
|
||
<button class="px-3 py-1.5 rounded-md border border-surface" :disabled="selectedBuildingCount===0" :class="selectedBuildingCount===0 ? 'opacity-50 cursor-not-allowed' : 'hover:bg-neutral-50'">批量设置单元信息</button>
|
||
<button class="px-3 py-1.5 rounded-md border border-surface" :disabled="selectedBuildingCount===0" :class="selectedBuildingCount===0 ? 'opacity-50 cursor-not-allowed' : 'hover:bg-neutral-50'">合并单元</button>
|
||
<button class="px-3 py-1.5 rounded-md border border-surface" :disabled="selectedBuildingCount===0" :class="selectedBuildingCount===0 ? 'opacity-50 cursor-not-allowed' : 'hover:bg-neutral-50'">移动单元</button>
|
||
<span class="text-xs text-muted" x-text="selectedBuildingCount > 0 ? '已选 ' + selectedBuildingCount + ' 条' : '未选中单元'"></span>
|
||
</div>
|
||
|
||
<div class="overflow-x-auto border border-surface rounded-lg">
|
||
<table class="min-w-full text-sm">
|
||
<thead class="bg-subtle border-b border-surface">
|
||
<tr>
|
||
<th scope="col" class="px-3 py-2 w-10"><input type="checkbox" aria-label="全选单元" class="rounded border-surface" :checked="allBuildingsOnPage" @click.prevent="toggleBuildingSelectPage(!allBuildingsOnPage)" /></th>
|
||
<th scope="col" class="px-3 py-2 text-left">单元名</th>
|
||
<th scope="col" class="px-3 py-2 text-left">物业类型</th>
|
||
<th scope="col" class="px-3 py-2 text-left">竣工年限</th>
|
||
<th scope="col" class="px-3 py-2 text-left">总层数</th>
|
||
<th scope="col" class="px-3 py-2 text-left">土地使用年限</th>
|
||
<th scope="col" class="px-3 py-2 text-left">电梯</th>
|
||
<th scope="col" class="px-3 py-2 text-left">关联学校</th>
|
||
<th scope="col" class="px-3 py-2 text-left">操作</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<template x-for="row in filteredBuildings" :key="row.id">
|
||
<tr class="border-b border-surface hover:bg-neutral-50/70">
|
||
<td class="px-3 py-2">
|
||
<input type="checkbox" class="rounded border-surface" :checked="selectedBuildingIds.includes(row.id)" @change="toggleBuildingSelect(row.id, $event.target.checked)" />
|
||
</td>
|
||
<td class="px-3 py-2">
|
||
<button class="text-primary-600 hover:underline" @click="notify('进入单元详情(原型)')" x-text="row.name"></button>
|
||
<span class="ml-2 inline-flex px-1.5 py-0.5 rounded text-xs bg-info-50 text-info-600 border border-info-600/20">标准</span>
|
||
</td>
|
||
<td class="px-3 py-2" x-text="row.usage"></td>
|
||
<td class="px-3 py-2 tabular-nums" x-text="row.year"></td>
|
||
<td class="px-3 py-2" x-text="row.floors"></td>
|
||
<td class="px-3 py-2" x-text="row.landYears"></td>
|
||
<td class="px-3 py-2" x-text="row.elevator"></td>
|
||
<td class="px-3 py-2" x-text="row.school"></td>
|
||
<td class="px-3 py-2">
|
||
<button class="text-primary-600 hover:underline mr-3" @click="notify('编辑楼栋(原型)')">编辑</button>
|
||
<button class="text-primary-600 hover:underline" @click="switchToStructure(row.name)">结构管理</button>
|
||
</td>
|
||
</tr>
|
||
</template>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<div class="flex items-center justify-between text-xs text-muted px-1">
|
||
<span>共 <span x-text="filteredBuildings.length"></span> 条</span>
|
||
<span>每页 20 条(原型占位)</span>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 结构管理 -->
|
||
<section x-show="activeTab === 'structure'" x-cloak class="bg-surface border border-surface rounded-lg p-4">
|
||
<div class="grid grid-cols-12 gap-4 min-h-[520px]">
|
||
<aside class="col-span-4 border border-surface rounded-lg p-3 flex flex-col">
|
||
<div class="flex items-center gap-2 mb-3">
|
||
<select class="px-2.5 py-2 rounded-md border border-surface bg-white text-sm">
|
||
<option>单元</option>
|
||
</select>
|
||
<button class="px-3 py-2 rounded-md border border-surface hover:bg-neutral-50 text-sm">设置单元信息</button>
|
||
</div>
|
||
<div class="space-y-1.5 overflow-y-auto pr-1">
|
||
<template x-for="item in units" :key="item.id">
|
||
<button class="left-item w-full text-left px-3 py-2 rounded-md text-sm" :class="{ 'active': currentUnitId === item.id }" @click="currentUnitId = item.id">
|
||
<span x-text="item.name"></span>
|
||
<span class="ml-2 inline-flex px-1.5 py-0.5 rounded text-xs bg-info-50 text-info-600 border border-info-600/20">标准</span>
|
||
</button>
|
||
</template>
|
||
</div>
|
||
</aside>
|
||
|
||
<div class="col-span-8 border border-surface rounded-lg p-3 flex flex-col">
|
||
<div class="flex items-center justify-between gap-3 mb-3">
|
||
<h3 class="text-sm font-semibold" x-text="currentUnitName"></h3>
|
||
<p class="text-xs text-muted">本楼盘还有 0 个房号无法关联结构,<button class="text-primary-600 hover:underline" @click="notify('查看无法关联明细(原型)')">查看明细</button></p>
|
||
</div>
|
||
|
||
<div class="flex items-center gap-2 mb-3">
|
||
<button class="px-3 py-1.5 rounded-md border border-surface" :disabled="selectedRoomCount===0" :class="selectedRoomCount===0 ? 'opacity-50 cursor-not-allowed' : 'hover:bg-neutral-50'">批量编辑房号</button>
|
||
<button class="px-3 py-1.5 rounded-md border border-surface" :disabled="selectedRoomCount===0" :class="selectedRoomCount===0 ? 'opacity-50 cursor-not-allowed' : 'hover:bg-neutral-50'">合并房号</button>
|
||
<span class="text-xs text-muted" x-text="'已选 ' + selectedRoomCount + ' 条'">已选 0 条</span>
|
||
<span class="text-xs text-muted">找不到房号?<button class="text-primary-600 hover:underline" @click="notify('申请新增房号(原型)')">点此申请新增</button></span>
|
||
</div>
|
||
|
||
<div class="overflow-auto border border-surface rounded-lg flex-1">
|
||
<table class="min-w-full text-sm">
|
||
<thead class="bg-subtle border-b border-surface">
|
||
<tr>
|
||
<th scope="col" class="px-3 py-2 w-10"><input type="checkbox" class="rounded border-surface" :checked="allRoomsSelected" @click.prevent="toggleAllRooms(!allRoomsSelected)" /></th>
|
||
<th scope="col" class="px-3 py-2 text-left">楼层名(实际层)</th>
|
||
<th scope="col" class="px-3 py-2 text-left">房号</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<template x-for="room in currentRooms" :key="room.id">
|
||
<tr class="border-b border-surface hover:bg-neutral-50/70">
|
||
<td class="px-3 py-2"><input type="checkbox" class="rounded border-surface" :checked="selectedRoomIds.includes(room.id)" @change="toggleRoom(room.id, $event.target.checked)" /></td>
|
||
<td class="px-3 py-2" x-text="room.floorName"></td>
|
||
<td class="px-3 py-2">
|
||
<span x-text="room.roomNo"></span>
|
||
<span class="ml-2 inline-flex px-1.5 py-0.5 rounded text-xs bg-info-50 text-info-600 border border-info-600/20">标准</span>
|
||
</td>
|
||
</tr>
|
||
</template>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 楼盘照片 -->
|
||
<section x-show="activeTab === 'photos'" x-cloak class="bg-surface border border-surface rounded-lg p-4 space-y-4">
|
||
<div class="flex items-center justify-between">
|
||
<div class="flex items-center gap-2">
|
||
<button class="subtab-pill px-3 py-1.5 rounded-md" :class="{ 'active': photoType === 'complex' }" @click="photoType='complex'">楼盘图片(12)</button>
|
||
<button class="subtab-pill px-3 py-1.5 rounded-md" :class="{ 'active': photoType === 'layout' }" @click="photoType='layout'">户型图(8)</button>
|
||
<button class="subtab-pill px-3 py-1.5 rounded-md" :class="{ 'active': photoType === 'vr' }" @click="photoType='vr'">楼盘VR(2)</button>
|
||
</div>
|
||
<button class="px-3 py-2 rounded-md bg-primary-600 text-white hover:bg-primary-700" @click="notify('上传图片(原型)')">上传图片</button>
|
||
</div>
|
||
|
||
<div x-show="photoType === 'layout'" class="flex items-center gap-2">
|
||
<span class="text-xs text-muted">户型:</span>
|
||
<button class="subtab-pill px-2 py-1 rounded-full text-xs active">全部</button>
|
||
<button class="subtab-pill px-2 py-1 rounded-full text-xs">1室</button>
|
||
<button class="subtab-pill px-2 py-1 rounded-full text-xs">2室</button>
|
||
<button class="subtab-pill px-2 py-1 rounded-full text-xs">3室</button>
|
||
<button class="subtab-pill px-2 py-1 rounded-full text-xs">4室+</button>
|
||
</div>
|
||
|
||
<div class="grid grid-cols-6 gap-3">
|
||
<template x-for="card in 12" :key="card">
|
||
<div class="border border-surface rounded-lg overflow-hidden bg-white">
|
||
<div class="aspect-[4/3] bg-neutral-200 flex items-center justify-center text-neutral-500 text-xs">图片占位</div>
|
||
<div class="px-2 py-1.5 text-xs text-neutral-600">1室2厅1卫 · 朝南</div>
|
||
</div>
|
||
</template>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 楼盘附件 -->
|
||
<section x-show="activeTab === 'attachments'" x-cloak class="bg-surface border border-surface rounded-lg p-4 space-y-3">
|
||
<div class="flex items-center justify-between">
|
||
<h2 class="text-base font-semibold">楼盘附件</h2>
|
||
<button class="px-3 py-2 rounded-md bg-primary-600 text-white hover:bg-primary-700" @click="notify('上传附件(原型)')">上传附件</button>
|
||
</div>
|
||
<div class="overflow-x-auto border border-surface rounded-lg">
|
||
<table class="min-w-full text-sm">
|
||
<thead class="bg-subtle border-b border-surface">
|
||
<tr>
|
||
<th scope="col" class="px-3 py-2 text-left">附件名称</th>
|
||
<th scope="col" class="px-3 py-2 text-left">类型</th>
|
||
<th scope="col" class="px-3 py-2 text-left">大小</th>
|
||
<th scope="col" class="px-3 py-2 text-left">上传人</th>
|
||
<th scope="col" class="px-3 py-2 text-left">上传时间</th>
|
||
<th scope="col" class="px-3 py-2 text-left">操作</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="border-b border-surface"><td class="px-3 py-2">小区总平图.pdf</td><td class="px-3 py-2">PDF</td><td class="px-3 py-2">1.2MB</td><td class="px-3 py-2">杜利强</td><td class="px-3 py-2 tabular-nums">2026-04-25 11:20</td><td class="px-3 py-2"><button class="text-primary-600 hover:underline">下载</button></td></tr>
|
||
<tr><td class="px-3 py-2">物业合同扫描件.zip</td><td class="px-3 py-2">ZIP</td><td class="px-3 py-2">3.8MB</td><td class="px-3 py-2">杜利强</td><td class="px-3 py-2 tabular-nums">2026-04-26 09:30</td><td class="px-3 py-2"><button class="text-primary-600 hover:underline">下载</button></td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 周边配套 -->
|
||
<section x-show="activeTab === 'facility'" x-cloak class="bg-surface border border-surface rounded-lg p-4">
|
||
<div class="grid grid-cols-12 gap-4">
|
||
<div class="col-span-8 border border-surface rounded-lg overflow-hidden">
|
||
<div class="h-[420px] bg-neutral-200 flex items-center justify-center text-neutral-500">地图区域占位(楼盘点位 + 周边 POI)</div>
|
||
</div>
|
||
<aside class="col-span-4 border border-surface rounded-lg p-3 space-y-3">
|
||
<div class="flex items-center gap-1 flex-wrap">
|
||
<button class="subtab-pill px-2 py-1 rounded-full text-xs active">交通</button>
|
||
<button class="subtab-pill px-2 py-1 rounded-full text-xs">教育</button>
|
||
<button class="subtab-pill px-2 py-1 rounded-full text-xs">医疗</button>
|
||
<button class="subtab-pill px-2 py-1 rounded-full text-xs">购物</button>
|
||
<button class="subtab-pill px-2 py-1 rounded-full text-xs">生活</button>
|
||
<button class="subtab-pill px-2 py-1 rounded-full text-xs">娱乐</button>
|
||
</div>
|
||
<ul class="space-y-2 text-sm">
|
||
<li class="border border-surface rounded-md p-2"><p class="font-medium">地铁13号线 · 金运路站</p><p class="text-xs text-muted mt-0.5">距楼盘 1227 米</p></li>
|
||
<li class="border border-surface rounded-md p-2"><p class="font-medium">公交站 · 祁连山南路金鼎路</p><p class="text-xs text-muted mt-0.5">距楼盘 356 米</p></li>
|
||
<li class="border border-surface rounded-md p-2"><p class="font-medium">公交站 · 金鼎路定边路</p><p class="text-xs text-muted mt-0.5">距楼盘 412 米</p></li>
|
||
</ul>
|
||
</aside>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 价格走势 -->
|
||
<section x-show="activeTab === 'price'" x-cloak class="bg-surface border border-surface rounded-lg p-4 space-y-4">
|
||
<div class="flex items-center justify-between">
|
||
<div class="flex items-center gap-2">
|
||
<button class="subtab-pill px-3 py-1.5 rounded-md" :class="{ 'active': priceView === 'internal' }" @click="priceView='internal'">司内数据</button>
|
||
<button class="subtab-pill px-3 py-1.5 rounded-md" :class="{ 'active': priceView === 'market' }" @click="priceView='market'">市场数据</button>
|
||
</div>
|
||
<p class="text-xs text-muted">以下数据按照 T+1 更新,市场与网签数据仅供参考</p>
|
||
</div>
|
||
|
||
<div class="grid grid-cols-4 gap-3">
|
||
<div class="border border-surface rounded-lg p-3"><p class="text-xs text-muted">本周挂牌均价</p><p class="text-xl font-semibold tabular-nums mt-1">57,800 元/㎡</p></div>
|
||
<div class="border border-surface rounded-lg p-3"><p class="text-xs text-muted">近一年成交均价</p><p class="text-xl font-semibold tabular-nums mt-1">55,200 元/㎡</p></div>
|
||
<div class="border border-surface rounded-lg p-3"><p class="text-xs text-muted">挂牌套数</p><p class="text-xl font-semibold tabular-nums mt-1">38 套</p></div>
|
||
<div class="border border-surface rounded-lg p-3"><p class="text-xs text-muted">近一年成交套数</p><p class="text-xl font-semibold tabular-nums mt-1">26 套</p></div>
|
||
</div>
|
||
|
||
<div class="grid grid-cols-2 gap-4">
|
||
<div class="border border-surface rounded-lg p-3">
|
||
<div class="flex items-center justify-between mb-2"><h3 class="font-medium">挂牌均价趋势</h3><div class="flex gap-1"><button class="subtab-pill px-2 py-0.5 rounded text-xs active">按周</button><button class="subtab-pill px-2 py-0.5 rounded text-xs">按月</button></div></div>
|
||
<div class="h-56 bg-neutral-100 rounded-md flex items-center justify-center text-neutral-500">折线图占位</div>
|
||
</div>
|
||
<div class="border border-surface rounded-lg p-3">
|
||
<h3 class="font-medium mb-2">成交均价趋势</h3>
|
||
<div class="h-56 bg-neutral-100 rounded-md flex items-center justify-center text-neutral-500">折线图占位</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="border border-surface rounded-lg overflow-hidden">
|
||
<div class="px-3 py-2 bg-subtle border-b border-surface text-sm font-medium">本小区成交数据明细(近一年)</div>
|
||
<div class="overflow-x-auto">
|
||
<table class="min-w-full text-xs">
|
||
<thead class="bg-subtle/60 border-b border-surface">
|
||
<tr>
|
||
<th scope="col" class="px-3 py-2 text-left">房源编号</th>
|
||
<th scope="col" class="px-3 py-2 text-left">挂牌价格(万)</th>
|
||
<th scope="col" class="px-3 py-2 text-left">成交价格(万)</th>
|
||
<th scope="col" class="px-3 py-2 text-left">成交单价(元/㎡)</th>
|
||
<th scope="col" class="px-3 py-2 text-left">成交日期</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="border-b border-surface"><td class="px-3 py-2">01DS016848</td><td class="px-3 py-2 tabular-nums">678</td><td class="px-3 py-2 tabular-nums">650</td><td class="px-3 py-2 tabular-nums">59215</td><td class="px-3 py-2 tabular-nums">2026-03-18</td></tr>
|
||
<tr><td class="px-3 py-2">01DS015902</td><td class="px-3 py-2 tabular-nums">620</td><td class="px-3 py-2 tabular-nums">598</td><td class="px-3 py-2 tabular-nums">56612</td><td class="px-3 py-2 tabular-nums">2026-02-03</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 销控盘 -->
|
||
<section x-show="activeTab === 'sales'" x-cloak class="bg-surface border border-surface rounded-lg p-8 text-center">
|
||
<h2 class="text-lg font-semibold text-surface">销控盘(后续版本)</h2>
|
||
<p class="text-sm text-muted mt-2">本模块用于新房/一手楼盘销控,当前在 P0 阶段保留占位。</p>
|
||
</section>
|
||
</div>
|
||
</main>
|
||
|
||
<!-- Edit Drawer -->
|
||
<div x-cloak x-show="editDrawerOpen" class="fixed inset-0 z-40">
|
||
<div class="absolute inset-0 bg-neutral-900/30" @click="closeEditDrawer()" aria-hidden="true"></div>
|
||
<aside class="absolute right-0 top-0 h-full w-[560px] bg-white border-l border-surface shadow-xl flex flex-col">
|
||
<header class="px-4 py-3 border-b border-surface flex items-center justify-between">
|
||
<div>
|
||
<h3 class="text-base font-semibold">编辑楼盘信息</h3>
|
||
<p class="text-xs text-muted mt-0.5">部分信息修改会影响房源,请确认后保存</p>
|
||
</div>
|
||
<button class="p-1.5 rounded-md hover:bg-neutral-100" aria-label="关闭编辑抽屉" @click="closeEditDrawer()">
|
||
<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="M6 18 18 6M6 6l12 12"/></svg>
|
||
</button>
|
||
</header>
|
||
|
||
<div class="flex-1 overflow-y-auto p-4 space-y-5">
|
||
<section class="space-y-3">
|
||
<h4 class="text-sm font-semibold">基本信息</h4>
|
||
<div>
|
||
<label class="block text-xs font-medium text-neutral-700 mb-1">小区名称 <span class="text-danger-600">*</span></label>
|
||
<input type="text" class="w-full px-3 py-2 rounded-md border border-surface bg-neutral-100 text-neutral-500" x-model="editForm.name" readonly />
|
||
</div>
|
||
<div>
|
||
<label class="block text-xs font-medium text-neutral-700 mb-1">小区地址 <span class="text-danger-600">*</span></label>
|
||
<input type="text" class="w-full px-3 py-2 rounded-md border border-surface bg-neutral-100 text-neutral-500" x-model="editForm.address" readonly />
|
||
</div>
|
||
<div>
|
||
<label class="block text-xs font-medium text-neutral-700 mb-1">物业类型 <span class="text-danger-600">*</span></label>
|
||
<select x-model="editForm.propertyUsage" class="w-full px-3 py-2 rounded-md border bg-white focus:outline-none focus:ring-2 focus:ring-primary-600/40" :class="editErrors.propertyUsage ? 'border-danger-600' : 'border-surface'">
|
||
<option value="">请选择物业类型</option>
|
||
<option value="residential">住宅</option>
|
||
<option value="villa">别墅</option>
|
||
<option value="commercial_residential">商住</option>
|
||
<option value="commercial">商业</option>
|
||
<option value="office">写字楼</option>
|
||
</select>
|
||
<p class="text-xs text-danger-600 mt-1" x-show="editErrors.propertyUsage" x-text="editErrors.propertyUsage"></p>
|
||
</div>
|
||
<div>
|
||
<label class="block text-xs font-medium text-neutral-700 mb-1">楼栋结构 <span class="text-danger-600">*</span></label>
|
||
<select x-model="editForm.buildingStructure" class="w-full px-3 py-2 rounded-md border bg-white focus:outline-none focus:ring-2 focus:ring-primary-600/40" :class="editErrors.buildingStructure ? 'border-danger-600' : 'border-surface'">
|
||
<option value="">请选择楼栋结构</option>
|
||
<option value="unit_room">单元-房号</option>
|
||
<option value="other">其他</option>
|
||
</select>
|
||
<p class="text-xs text-danger-600 mt-1" x-show="editErrors.buildingStructure" x-text="editErrors.buildingStructure"></p>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="space-y-2">
|
||
<h4 class="text-sm font-semibold">学校信息</h4>
|
||
<p class="text-xs text-warning-600">删除学校,所有房源下关联该学校将会被删除(原型说明)</p>
|
||
<div class="flex items-center justify-between border border-surface rounded-md px-3 py-2">
|
||
<span>真光小学(公立 · 重点)</span>
|
||
<button class="text-danger-600 hover:underline" @click="notify('删除学校(原型)')">删除</button>
|
||
</div>
|
||
<button class="px-3 py-1.5 rounded-md border border-surface hover:bg-neutral-50" @click="notify('新增学校(原型)')">+ 添加</button>
|
||
</section>
|
||
|
||
<section class="space-y-3 pb-24">
|
||
<h4 class="text-sm font-semibold">其他信息</h4>
|
||
<div class="grid grid-cols-2 gap-3">
|
||
<div>
|
||
<label class="block text-xs font-medium text-neutral-700 mb-1">容积率</label>
|
||
<input type="number" step="0.01" x-model="editForm.plotRatio" class="w-full px-3 py-2 rounded-md border border-surface bg-white focus:outline-none focus:ring-2 focus:ring-primary-600/40" />
|
||
</div>
|
||
<div>
|
||
<label class="block text-xs font-medium text-neutral-700 mb-1">绿化率(%)</label>
|
||
<input type="number" step="0.01" x-model="editForm.greenRate" class="w-full px-3 py-2 rounded-md border border-surface bg-white focus:outline-none focus:ring-2 focus:ring-primary-600/40" />
|
||
</div>
|
||
<div>
|
||
<label class="block text-xs font-medium text-neutral-700 mb-1">物业费(元/㎡/月)</label>
|
||
<input type="number" step="0.01" x-model="editForm.propertyFee" class="w-full px-3 py-2 rounded-md border border-surface bg-white focus:outline-none focus:ring-2 focus:ring-primary-600/40" />
|
||
</div>
|
||
<div>
|
||
<label class="block text-xs font-medium text-neutral-700 mb-1">停车位配比</label>
|
||
<input type="text" x-model="editForm.parkingRatio" class="w-full px-3 py-2 rounded-md border border-surface bg-white focus:outline-none focus:ring-2 focus:ring-primary-600/40" />
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<label class="block text-xs font-medium text-neutral-700 mb-1">备注</label>
|
||
<textarea rows="3" x-model="editForm.remarks" class="w-full px-3 py-2 rounded-md border border-surface bg-white focus:outline-none focus:ring-2 focus:ring-primary-600/40"></textarea>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
|
||
<!-- Fixed Footer: right aligned -->
|
||
<footer class="absolute bottom-0 left-0 right-0 border-t border-surface bg-white px-4 py-3">
|
||
<div class="flex items-center justify-end gap-3">
|
||
<button class="inline-flex items-center px-5 py-2 text-sm font-medium rounded-md border border-neutral-300 text-neutral-700 hover:bg-neutral-50" @click="closeEditDrawer()">取消</button>
|
||
<button class="inline-flex items-center gap-1.5 px-6 py-2 text-sm font-medium rounded-md bg-primary-600 text-white hover:bg-primary-700 active:bg-primary-800 focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-600/40 disabled:opacity-70 disabled:cursor-wait" :disabled="editSubmitting" @click="saveEdit()">
|
||
<svg x-show="editSubmitting" class="w-4 h-4 animate-spin" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 0 1 8-8v4a4 4 0 0 0-4 4H4z"></path></svg>
|
||
<span x-text="editSubmitting ? '保存中...' : '保存'"></span>
|
||
</button>
|
||
</div>
|
||
</footer>
|
||
</aside>
|
||
</div>
|
||
|
||
<!-- Toast -->
|
||
<div x-cloak x-show="toast.show" class="fixed bottom-6 right-6 z-50" x-transition>
|
||
<div class="bg-surface border border-surface shadow-lg rounded-lg px-4 py-3 min-w-[260px]">
|
||
<p class="text-sm font-medium" x-text="toast.title"></p>
|
||
<p class="text-xs text-muted mt-1" x-text="toast.message"></p>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
function complexDetailPage() {
|
||
return {
|
||
activeTab: 'info',
|
||
tabs: [
|
||
{ key: 'info', label: '楼盘信息' },
|
||
{ key: 'buildings', label: '楼栋管理' },
|
||
{ key: 'structure', label: '结构管理' },
|
||
{ key: 'photos', label: '楼盘照片' },
|
||
{ key: 'attachments', label: '楼盘附件' },
|
||
{ key: 'facility', label: '周边配套' },
|
||
{ key: 'price', label: '楼盘价格走势' },
|
||
{ key: 'sales', label: '销控盘' }
|
||
],
|
||
|
||
schools: [
|
||
{ name: '真光小学', type: '小学', nature: '公立', level: '重点' },
|
||
{ name: '真光中学', type: '中学', nature: '公立', level: '区重点' }
|
||
],
|
||
|
||
buildingKeyword: '',
|
||
buildings: [
|
||
{ id: 'b1', name: '祁连山南路2727弄101单元', usage: '别墅', year: 2009, floors: '1层', landYears: '70年', elevator: '无', school: '-' },
|
||
{ id: 'b2', name: '祁连山南路2727弄57单元', usage: '别墅', year: 2009, floors: '1层', landYears: '70年', elevator: '无', school: '-' },
|
||
{ id: 'b3', name: '祁连山南路2727弄59单元', usage: '别墅', year: 2009, floors: '1层', landYears: '70年', elevator: '无', school: '-' },
|
||
{ id: 'b4', name: '祁连山南路2727弄61单元', usage: '别墅', year: 2009, floors: '1层', landYears: '70年', elevator: '无', school: '-' },
|
||
{ id: 'b5', name: '祁连山南路2727弄63单元', usage: '别墅', year: 2009, floors: '1层', landYears: '70年', elevator: '无', school: '-' }
|
||
],
|
||
filteredBuildings: [],
|
||
selectedBuildingIds: [],
|
||
|
||
units: [
|
||
{ id: 'u1', name: '祁连山南路2727弄101单元' },
|
||
{ id: 'u2', name: '祁连山南路2727弄57单元' },
|
||
{ id: 'u3', name: '祁连山南路2727弄59单元' },
|
||
{ id: 'u4', name: '祁连山南路2727弄61单元' }
|
||
],
|
||
currentUnitId: 'u2',
|
||
roomMap: {
|
||
u1: [
|
||
{ id: 'r1', floorName: '1(1层)', roomNo: '101' },
|
||
{ id: 'r2', floorName: '1(1层)', roomNo: '102' }
|
||
],
|
||
u2: [
|
||
{ id: 'r3', floorName: '1(1层)', roomNo: '57-1' },
|
||
{ id: 'r4', floorName: '1(1层)', roomNo: '57-2' }
|
||
],
|
||
u3: [
|
||
{ id: 'r5', floorName: '1(1层)', roomNo: '59-1' }
|
||
],
|
||
u4: [
|
||
{ id: 'r6', floorName: '1(1层)', roomNo: '61-1' }
|
||
]
|
||
},
|
||
selectedRoomIds: [],
|
||
|
||
photoType: 'complex',
|
||
priceView: 'internal',
|
||
|
||
editDrawerOpen: false,
|
||
editSubmitting: false,
|
||
editErrors: {},
|
||
editForm: {
|
||
name: '阳光威尼斯四期(别墅)',
|
||
address: '上海普陀金鼎路1600弄,祁连山南路2727弄',
|
||
propertyUsage: 'villa',
|
||
buildingStructure: 'unit_room',
|
||
plotRatio: '1.60',
|
||
greenRate: '45',
|
||
propertyFee: '1.45',
|
||
parkingRatio: '100:63',
|
||
remarks: '别墅区结构完整,建议补全学校关系。'
|
||
},
|
||
|
||
toast: {
|
||
show: false,
|
||
title: '',
|
||
message: ''
|
||
},
|
||
|
||
init() {
|
||
this.filteredBuildings = [...this.buildings];
|
||
},
|
||
|
||
get selectedBuildingCount() {
|
||
return this.selectedBuildingIds.length;
|
||
},
|
||
|
||
get allBuildingsOnPage() {
|
||
return this.filteredBuildings.length > 0 && this.filteredBuildings.every(row => this.selectedBuildingIds.includes(row.id));
|
||
},
|
||
|
||
toggleBuildingSelect(id, checked) {
|
||
if (checked) {
|
||
if (!this.selectedBuildingIds.includes(id)) this.selectedBuildingIds.push(id);
|
||
} else {
|
||
this.selectedBuildingIds = this.selectedBuildingIds.filter(x => x !== id);
|
||
}
|
||
},
|
||
|
||
toggleBuildingSelectPage(checked) {
|
||
const ids = this.filteredBuildings.map(r => r.id);
|
||
if (checked) {
|
||
this.selectedBuildingIds = Array.from(new Set([...this.selectedBuildingIds, ...ids]));
|
||
} else {
|
||
this.selectedBuildingIds = this.selectedBuildingIds.filter(id => !ids.includes(id));
|
||
}
|
||
},
|
||
|
||
applyBuildingFilter() {
|
||
const kw = this.buildingKeyword.toLowerCase();
|
||
this.filteredBuildings = this.buildings.filter(row => !kw || row.name.toLowerCase().includes(kw));
|
||
this.selectedBuildingIds = this.selectedBuildingIds.filter(id => this.filteredBuildings.some(r => r.id === id));
|
||
},
|
||
|
||
switchToStructure(unitName) {
|
||
const target = this.units.find(u => u.name === unitName);
|
||
if (target) this.currentUnitId = target.id;
|
||
this.activeTab = 'structure';
|
||
this.notify('已切换到结构管理分区');
|
||
},
|
||
|
||
get currentUnitName() {
|
||
const row = this.units.find(u => u.id === this.currentUnitId);
|
||
return row ? row.name : '-';
|
||
},
|
||
|
||
get currentRooms() {
|
||
return this.roomMap[this.currentUnitId] || [];
|
||
},
|
||
|
||
get selectedRoomCount() {
|
||
return this.selectedRoomIds.length;
|
||
},
|
||
|
||
get allRoomsSelected() {
|
||
return this.currentRooms.length > 0 && this.currentRooms.every(r => this.selectedRoomIds.includes(r.id));
|
||
},
|
||
|
||
toggleRoom(id, checked) {
|
||
if (checked) {
|
||
if (!this.selectedRoomIds.includes(id)) this.selectedRoomIds.push(id);
|
||
} else {
|
||
this.selectedRoomIds = this.selectedRoomIds.filter(x => x !== id);
|
||
}
|
||
},
|
||
|
||
toggleAllRooms(checked) {
|
||
const ids = this.currentRooms.map(r => r.id);
|
||
if (checked) {
|
||
this.selectedRoomIds = Array.from(new Set([...this.selectedRoomIds, ...ids]));
|
||
} else {
|
||
this.selectedRoomIds = this.selectedRoomIds.filter(id => !ids.includes(id));
|
||
}
|
||
},
|
||
|
||
openEditDrawer() {
|
||
this.editDrawerOpen = true;
|
||
this.editErrors = {};
|
||
},
|
||
|
||
closeEditDrawer() {
|
||
this.editDrawerOpen = false;
|
||
this.editErrors = {};
|
||
this.editSubmitting = false;
|
||
},
|
||
|
||
saveEdit() {
|
||
this.editErrors = {};
|
||
if (!this.editForm.propertyUsage) this.editErrors.propertyUsage = '请选择物业类型';
|
||
if (!this.editForm.buildingStructure) this.editErrors.buildingStructure = '请选择楼栋结构';
|
||
if (Object.keys(this.editErrors).length > 0) return;
|
||
|
||
this.editSubmitting = true;
|
||
setTimeout(() => {
|
||
this.editSubmitting = false;
|
||
this.editDrawerOpen = false;
|
||
this.notify('楼盘信息已保存(原型)');
|
||
}, 550);
|
||
},
|
||
|
||
notify(message) {
|
||
this.toast.title = '操作反馈';
|
||
this.toast.message = message;
|
||
this.toast.show = true;
|
||
clearTimeout(this.__toastTimer);
|
||
this.__toastTimer = setTimeout(() => (this.toast.show = false), 1800);
|
||
}
|
||
};
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|