|
|
<!doctype html>
|
|
|
<html lang="zh-CN">
|
|
|
<head>
|
|
|
<meta charset="utf-8">
|
|
|
<title>宾馆信息管理系统</title>
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
|
|
|
|
<style>
|
|
|
:root{
|
|
|
--primary:#3f51b5;
|
|
|
--primary-dark:#303f9f;
|
|
|
--success:#4caf50;
|
|
|
--warning:#ff9800;
|
|
|
--danger:#f44336;
|
|
|
--bg:#f3f5fb;
|
|
|
--card:#ffffff;
|
|
|
--text:#2c2c2c;
|
|
|
--muted:#777;
|
|
|
}
|
|
|
*{box-sizing:border-box}
|
|
|
body{
|
|
|
margin:0;
|
|
|
font-family:"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif;
|
|
|
background:var(--bg);
|
|
|
color:var(--text);
|
|
|
}
|
|
|
|
|
|
#login{
|
|
|
height:100vh;
|
|
|
display:flex;
|
|
|
align-items:center;
|
|
|
justify-content:center;
|
|
|
background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);
|
|
|
}
|
|
|
.login-box{
|
|
|
width:400px;
|
|
|
background:#fff;
|
|
|
padding:40px;
|
|
|
border-radius:16px;
|
|
|
box-shadow:0 24px 48px rgba(0,0,0,.25);
|
|
|
}
|
|
|
.login-box h2{
|
|
|
text-align:center;
|
|
|
margin-bottom:8px;
|
|
|
color:#3f51b5;
|
|
|
}
|
|
|
.login-box .subtitle{
|
|
|
text-align:center;
|
|
|
color:#888;
|
|
|
margin-bottom:28px;
|
|
|
font-size:14px;
|
|
|
}
|
|
|
.login-box input{
|
|
|
width:100%;
|
|
|
padding:12px 16px;
|
|
|
margin-bottom:16px;
|
|
|
border:2px solid #e0e0e0;
|
|
|
border-radius:8px;
|
|
|
font-size:14px;
|
|
|
}
|
|
|
.login-box input:focus{
|
|
|
outline:none;
|
|
|
border-color:#3f51b5;
|
|
|
}
|
|
|
.login-btn{
|
|
|
width:100%;
|
|
|
padding:14px;
|
|
|
font-size:16px;
|
|
|
background:#3f51b5;
|
|
|
color:#fff;
|
|
|
border:none;
|
|
|
border-radius:8px;
|
|
|
cursor:pointer;
|
|
|
}
|
|
|
.login-btn:hover{
|
|
|
background:#303f9f;
|
|
|
}
|
|
|
|
|
|
#main{display:flex;height:100vh}
|
|
|
.sidebar{
|
|
|
width:260px;
|
|
|
background:linear-gradient(180deg,#3949ab,#1a237e);
|
|
|
color:#fff;
|
|
|
flex-shrink:0;
|
|
|
}
|
|
|
.sidebar h3{
|
|
|
padding:24px;
|
|
|
margin:0;
|
|
|
font-weight:500;
|
|
|
border-bottom:1px solid rgba(255,255,255,.15);
|
|
|
font-size:18px;
|
|
|
}
|
|
|
.sidebar ul{list-style:none;padding:0;margin:0}
|
|
|
.sidebar li{
|
|
|
padding:16px 24px;
|
|
|
cursor:pointer;
|
|
|
transition:background .2s;
|
|
|
}
|
|
|
.sidebar li.active,
|
|
|
.sidebar li:hover{
|
|
|
background:rgba(255,255,255,.15);
|
|
|
}
|
|
|
|
|
|
.content{
|
|
|
flex:1;
|
|
|
padding:28px;
|
|
|
overflow:auto;
|
|
|
background:#f8f9fc;
|
|
|
}
|
|
|
|
|
|
.card{
|
|
|
background:var(--card);
|
|
|
border-radius:14px;
|
|
|
padding:24px;
|
|
|
margin-bottom:24px;
|
|
|
box-shadow:0 4px 20px rgba(0,0,0,.06);
|
|
|
}
|
|
|
.card h3{margin:0 0 20px 0;color:#333}
|
|
|
.hidden{display:none}
|
|
|
|
|
|
.stats{
|
|
|
display:grid;
|
|
|
grid-template-columns:repeat(4,1fr);
|
|
|
gap:20px;
|
|
|
margin-bottom:24px;
|
|
|
}
|
|
|
.stat-card{
|
|
|
background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);
|
|
|
color:#fff;
|
|
|
padding:24px;
|
|
|
border-radius:14px;
|
|
|
box-shadow:0 8px 24px rgba(102,126,234,.3);
|
|
|
}
|
|
|
.stat-card:nth-child(2){background:linear-gradient(135deg,#f093fb 0%,#f5576c 100%)}
|
|
|
.stat-card:nth-child(3){background:linear-gradient(135deg,#4facfe 0%,#00f2fe 100%)}
|
|
|
.stat-card:nth-child(4){background:linear-gradient(135deg,#43e97b 0%,#38f9d7 100%)}
|
|
|
.stat-card .number{font-size:32px;font-weight:700}
|
|
|
.stat-card .label{opacity:.9;margin-top:6px}
|
|
|
|
|
|
.toolbar{
|
|
|
display:flex;
|
|
|
gap:12px;
|
|
|
margin-bottom:20px;
|
|
|
flex-wrap:wrap;
|
|
|
align-items:center;
|
|
|
}
|
|
|
.toolbar input,.toolbar select{
|
|
|
padding:10px 14px;
|
|
|
border:1px solid #ddd;
|
|
|
border-radius:8px;
|
|
|
font-size:14px;
|
|
|
}
|
|
|
|
|
|
.btn{
|
|
|
padding:10px 20px;
|
|
|
border:none;
|
|
|
border-radius:8px;
|
|
|
cursor:pointer;
|
|
|
font-size:14px;
|
|
|
transition:all .2s;
|
|
|
}
|
|
|
.btn-primary{background:#3f51b5;color:#fff}
|
|
|
.btn-primary:hover{background:#303f9f}
|
|
|
.btn-success{background:#4caf50;color:#fff}
|
|
|
.btn-warning{background:#ff9800;color:#fff}
|
|
|
.btn-danger{background:#f44336;color:#fff}
|
|
|
.btn-sm{padding:6px 12px;font-size:12px}
|
|
|
|
|
|
table{
|
|
|
width:100%;
|
|
|
border-collapse:collapse;
|
|
|
}
|
|
|
th,td{
|
|
|
padding:14px 12px;
|
|
|
border-bottom:1px solid #eee;
|
|
|
text-align:left;
|
|
|
}
|
|
|
th{
|
|
|
background:#f8f9fc;
|
|
|
font-weight:600;
|
|
|
color:#555;
|
|
|
font-size:13px;
|
|
|
}
|
|
|
tr:hover{background:#fafbff}
|
|
|
|
|
|
.status{
|
|
|
display:inline-block;
|
|
|
padding:4px 12px;
|
|
|
border-radius:20px;
|
|
|
font-size:12px;
|
|
|
font-weight:500;
|
|
|
}
|
|
|
.status-free{background:#e8f5e9;color:#2e7d32}
|
|
|
.status-booked{background:#fff3e0;color:#ef6c00}
|
|
|
.status-checkin{background:#e3f2fd;color:#1565c0}
|
|
|
.status-cleaning{background:#fce4ec;color:#c2185b}
|
|
|
.status-checkout{background:#f3e5f5;color:#7b1fa2}
|
|
|
|
|
|
.tag{
|
|
|
display:inline-block;
|
|
|
padding:3px 10px;
|
|
|
border-radius:12px;
|
|
|
font-size:12px;
|
|
|
background:#e8eaf6;
|
|
|
color:#303f9f;
|
|
|
margin:2px 4px 2px 0;
|
|
|
}
|
|
|
|
|
|
.mono{font-family:Consolas,monospace;font-size:13px;color:#555}
|
|
|
.muted{color:var(--muted)}
|
|
|
.text-success{color:#4caf50}
|
|
|
.text-warning{color:#ff9800}
|
|
|
.text-danger{color:#f44336}
|
|
|
|
|
|
.actions{display:flex;gap:6px}
|
|
|
|
|
|
.modal{
|
|
|
position:fixed;
|
|
|
top:0;left:0;right:0;bottom:0;
|
|
|
background:rgba(0,0,0,.5);
|
|
|
display:flex;
|
|
|
align-items:center;
|
|
|
justify-content:center;
|
|
|
z-index:1000;
|
|
|
}
|
|
|
.modal-content{
|
|
|
background:#fff;
|
|
|
padding:32px;
|
|
|
border-radius:16px;
|
|
|
width:500px;
|
|
|
max-width:90%;
|
|
|
}
|
|
|
.modal-content h3{margin:0 0 24px 0}
|
|
|
.form-group{margin-bottom:18px}
|
|
|
.form-group label{display:block;margin-bottom:6px;font-weight:500;color:#555}
|
|
|
.form-group input,.form-group select{
|
|
|
width:100%;
|
|
|
padding:10px 14px;
|
|
|
border:2px solid #e0e0e0;
|
|
|
border-radius:8px;
|
|
|
font-size:14px;
|
|
|
}
|
|
|
.form-actions{
|
|
|
display:flex;
|
|
|
gap:12px;
|
|
|
justify-content:flex-end;
|
|
|
margin-top:24px;
|
|
|
}
|
|
|
|
|
|
.report-grid{
|
|
|
display:grid;
|
|
|
grid-template-columns:repeat(3,1fr);
|
|
|
gap:20px;
|
|
|
margin-bottom:24px;
|
|
|
}
|
|
|
.report-card{
|
|
|
padding:24px;
|
|
|
color:#fff;
|
|
|
border-radius:14px;
|
|
|
}
|
|
|
.report-card .number{font-size:28px;font-weight:700}
|
|
|
.report-card .label{opacity:.9;margin-top:4px}
|
|
|
.report-card .trend{font-size:12px;margin-top:8px;opacity:.8}
|
|
|
|
|
|
.chart-bar{
|
|
|
display:flex;
|
|
|
align-items:center;
|
|
|
margin-bottom:12px;
|
|
|
}
|
|
|
.chart-bar-label{width:80px;font-size:13px}
|
|
|
.chart-bar-track{flex:1;height:24px;background:#e0e0e0;border-radius:12px;overflow:hidden}
|
|
|
.chart-bar-fill{height:100%;border-radius:12px;display:flex;align-items:center;justify-content:flex-end;padding-right:8px;color:#fff;font-size:12px;font-weight:500}
|
|
|
|
|
|
.summary-table{margin-top:20px}
|
|
|
.summary-table td{padding:12px 16px}
|
|
|
.summary-table tr:nth-child(odd){background:#f8f9fc}
|
|
|
</style>
|
|
|
</head>
|
|
|
|
|
|
<body>
|
|
|
|
|
|
<div id="login">
|
|
|
<div class="login-box">
|
|
|
<h2>🏨 宾馆信息管理系统</h2>
|
|
|
<p class="subtitle">Hotel Information Management System</p>
|
|
|
<input type="text" placeholder="用户名(任意输入)">
|
|
|
<input type="password" placeholder="密码(任意输入)">
|
|
|
<button class="login-btn" onclick="login()">登 录</button>
|
|
|
<p style="text-align:center;font-size:12px;color:#888;margin-top:18px">
|
|
|
提示:直接点击登录即可进入系统
|
|
|
</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div id="main" class="hidden">
|
|
|
<div class="sidebar">
|
|
|
<h3>🏨 宾馆管理系统</h3>
|
|
|
<ul>
|
|
|
<li class="active" onclick="show('home',this)">📊 系统首页</li>
|
|
|
<li onclick="show('room',this)">🛏️ 房间管理</li>
|
|
|
<li onclick="show('customer',this)">👥 客户管理</li>
|
|
|
<li onclick="show('reserve',this)">📅 预定管理</li>
|
|
|
<li onclick="show('checkin',this)">✅ 入住记录</li>
|
|
|
<li onclick="show('report',this)">📈 统计报表</li>
|
|
|
<li onclick="logout()" style="margin-top:20px;border-top:1px solid rgba(255,255,255,.1);padding-top:20px">🚪 退出系统</li>
|
|
|
</ul>
|
|
|
</div>
|
|
|
|
|
|
<div class="content">
|
|
|
|
|
|
<!-- 首页 -->
|
|
|
<div id="home" class="module">
|
|
|
<div class="stats">
|
|
|
<div class="stat-card">
|
|
|
<div class="number" id="statRooms">16</div>
|
|
|
<div class="label">总房间数</div>
|
|
|
</div>
|
|
|
<div class="stat-card">
|
|
|
<div class="number" id="statCustomers">26</div>
|
|
|
<div class="label">注册客户</div>
|
|
|
</div>
|
|
|
<div class="stat-card">
|
|
|
<div class="number" id="statCheckin">4</div>
|
|
|
<div class="label">今日在住</div>
|
|
|
</div>
|
|
|
<div class="stat-card">
|
|
|
<div class="number" id="statIncome">¥86,752</div>
|
|
|
<div class="label">本月营收</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="card">
|
|
|
<h3>📊 系统概览</h3>
|
|
|
<p>欢迎使用宾馆信息管理系统!当前系统运行正常,以下是今日运营概况。</p>
|
|
|
<div style="display:grid;grid-template-columns:repeat(2,1fr);gap:20px;margin-top:20px">
|
|
|
<div style="padding:20px;background:#f8f9fc;border-radius:12px">
|
|
|
<h4 style="margin:0 0 12px 0;color:#3f51b5">🛏️ 房间状态分布</h4>
|
|
|
<div id="roomStatusChart"></div>
|
|
|
</div>
|
|
|
<div style="padding:20px;background:#f8f9fc;border-radius:12px">
|
|
|
<h4 style="margin:0 0 12px 0;color:#3f51b5">📅 近期预定</h4>
|
|
|
<div id="recentOrders"></div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div style="display:grid;grid-template-columns:repeat(2,1fr);gap:20px;margin-top:20px">
|
|
|
<div style="padding:20px;background:#f8f9fc;border-radius:12px">
|
|
|
<h4 style="margin:0 0 12px 0;color:#3f51b5">💰 今日收入</h4>
|
|
|
<div id="todayIncome"></div>
|
|
|
</div>
|
|
|
<div style="padding:20px;background:#f8f9fc;border-radius:12px">
|
|
|
<h4 style="margin:0 0 12px 0;color:#3f51b5">🔔 待办事项</h4>
|
|
|
<div id="todoList"></div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 房间管理 -->
|
|
|
<div id="room" class="module hidden">
|
|
|
<div class="card">
|
|
|
<h3>🛏️ 房间管理</h3>
|
|
|
<div class="toolbar">
|
|
|
<input type="text" id="roomSearch" placeholder="搜索房间号/房型..." oninput="renderRooms()">
|
|
|
<select id="roomStatusFilter" onchange="renderRooms()">
|
|
|
<option value="">全部状态</option>
|
|
|
<option value="空闲">空闲</option>
|
|
|
<option value="已预定">已预定</option>
|
|
|
<option value="已入住">已入住</option>
|
|
|
<option value="清洁中">清洁中</option>
|
|
|
</select>
|
|
|
<button class="btn btn-primary" onclick="openRoomModal()">+ 添加房间</button>
|
|
|
</div>
|
|
|
<table>
|
|
|
<thead>
|
|
|
<tr>
|
|
|
<th>房间号</th>
|
|
|
<th>房型</th>
|
|
|
<th>楼层</th>
|
|
|
<th>朝向</th>
|
|
|
<th>面积</th>
|
|
|
<th>价格/晚</th>
|
|
|
<th>状态</th>
|
|
|
<th>操作</th>
|
|
|
</tr>
|
|
|
</thead>
|
|
|
<tbody id="roomList"></tbody>
|
|
|
</table>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 客户管理 -->
|
|
|
<div id="customer" class="module hidden">
|
|
|
<div class="card">
|
|
|
<h3>👥 客户档案管理</h3>
|
|
|
<div class="toolbar">
|
|
|
<input type="text" id="customerSearch" placeholder="搜索姓名/手机号..." oninput="renderCustomers()">
|
|
|
<select id="customerVipFilter" onchange="renderCustomers()">
|
|
|
<option value="">全部会员</option>
|
|
|
<option value="普通会员">普通会员</option>
|
|
|
<option value="银卡会员">银卡会员</option>
|
|
|
<option value="金卡会员">金卡会员</option>
|
|
|
<option value="钻石会员">钻石会员</option>
|
|
|
</select>
|
|
|
<button class="btn btn-primary" onclick="openCustomerModal()">+ 新增客户</button>
|
|
|
</div>
|
|
|
<table>
|
|
|
<thead>
|
|
|
<tr>
|
|
|
<th>姓名</th>
|
|
|
<th>性别</th>
|
|
|
<th>联系电话</th>
|
|
|
<th>身份证号</th>
|
|
|
<th>会员等级</th>
|
|
|
<th>累计消费</th>
|
|
|
<th>偏好标签</th>
|
|
|
<th>操作</th>
|
|
|
</tr>
|
|
|
</thead>
|
|
|
<tbody id="customerList"></tbody>
|
|
|
</table>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 预定管理 -->
|
|
|
<div id="reserve" class="module hidden">
|
|
|
<div class="card">
|
|
|
<h3>📅 预定管理</h3>
|
|
|
<div class="toolbar">
|
|
|
<input type="text" id="orderSearch" placeholder="搜索客户/房间..." oninput="renderOrders()">
|
|
|
<select id="orderStatusFilter" onchange="renderOrders()">
|
|
|
<option value="">全部状态</option>
|
|
|
<option value="待确认">待确认</option>
|
|
|
<option value="已确认">已确认</option>
|
|
|
<option value="已入住">已入住</option>
|
|
|
<option value="已退房">已退房</option>
|
|
|
<option value="已取消">已取消</option>
|
|
|
</select>
|
|
|
<button class="btn btn-primary" onclick="openOrderModal()">+ 新增预定</button>
|
|
|
</div>
|
|
|
<table>
|
|
|
<thead>
|
|
|
<tr>
|
|
|
<th>预定单号</th>
|
|
|
<th>客户姓名</th>
|
|
|
<th>房间号</th>
|
|
|
<th>房型</th>
|
|
|
<th>入住日期</th>
|
|
|
<th>离店日期</th>
|
|
|
<th>天数</th>
|
|
|
<th>总价</th>
|
|
|
<th>状态</th>
|
|
|
<th>操作</th>
|
|
|
</tr>
|
|
|
</thead>
|
|
|
<tbody id="orderList"></tbody>
|
|
|
</table>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 入住记录 -->
|
|
|
<div id="checkin" class="module hidden">
|
|
|
<div class="stats">
|
|
|
<div class="stat-card">
|
|
|
<div class="number" id="checkinTotal">35</div>
|
|
|
<div class="label">本月入住次数</div>
|
|
|
</div>
|
|
|
<div class="stat-card">
|
|
|
<div class="number" id="checkoutTotal">31</div>
|
|
|
<div class="label">本月退房次数</div>
|
|
|
</div>
|
|
|
<div class="stat-card">
|
|
|
<div class="number" id="avgStay">2.3</div>
|
|
|
<div class="label">平均入住天数</div>
|
|
|
</div>
|
|
|
<div class="stat-card">
|
|
|
<div class="number" id="totalRevenue">¥86,752</div>
|
|
|
<div class="label">本月总收入</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="card">
|
|
|
<h3>✅ 入住/退房记录</h3>
|
|
|
<div class="toolbar">
|
|
|
<input type="text" id="checkinSearch" placeholder="搜索客户/房间..." oninput="renderCheckins()">
|
|
|
<select id="checkinStatusFilter" onchange="renderCheckins()">
|
|
|
<option value="">全部状态</option>
|
|
|
<option value="在住">在住</option>
|
|
|
<option value="已退房">已退房</option>
|
|
|
</select>
|
|
|
<select id="checkinMonthFilter" onchange="renderCheckins()">
|
|
|
<option value="">全部月份</option>
|
|
|
<option value="2024-01">2024年1月</option>
|
|
|
<option value="2023-12">2023年12月</option>
|
|
|
<option value="2023-11">2023年11月</option>
|
|
|
</select>
|
|
|
<button class="btn btn-success" onclick="exportCheckins()">📥 导出记录</button>
|
|
|
</div>
|
|
|
<table>
|
|
|
<thead>
|
|
|
<tr>
|
|
|
<th>记录编号</th>
|
|
|
<th>客户姓名</th>
|
|
|
<th>联系电话</th>
|
|
|
<th>房间号</th>
|
|
|
<th>房型</th>
|
|
|
<th>入住时间</th>
|
|
|
<th>退房时间</th>
|
|
|
<th>天数</th>
|
|
|
<th>实付金额</th>
|
|
|
<th>支付方式</th>
|
|
|
<th>状态</th>
|
|
|
<th>备注</th>
|
|
|
</tr>
|
|
|
</thead>
|
|
|
<tbody id="checkinList"></tbody>
|
|
|
</table>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 统计报表 -->
|
|
|
<div id="report" class="module hidden">
|
|
|
<div class="report-grid">
|
|
|
<div class="report-card" style="background:linear-gradient(135deg,#667eea,#764ba2)">
|
|
|
<div class="number" id="reportOccupancy">68.5%</div>
|
|
|
<div class="label">本月入住率</div>
|
|
|
<div class="trend">↑ 较上月提升 5.2%</div>
|
|
|
</div>
|
|
|
<div class="report-card" style="background:linear-gradient(135deg,#f093fb,#f5576c)">
|
|
|
<div class="number" id="reportAvgPrice">¥486</div>
|
|
|
<div class="label">平均房价</div>
|
|
|
<div class="trend">↑ 较上月提升 ¥28</div>
|
|
|
</div>
|
|
|
<div class="report-card" style="background:linear-gradient(135deg,#4facfe,#00f2fe)">
|
|
|
<div class="number" id="reportRevenue">¥86,752</div>
|
|
|
<div class="label">本月总营收</div>
|
|
|
<div class="trend">↑ 较上月增长 12.8%</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div style="display:grid;grid-template-columns:1fr 1fr;gap:24px">
|
|
|
<div class="card">
|
|
|
<h3>📊 各房型入住率</h3>
|
|
|
<div id="roomTypeChart"></div>
|
|
|
</div>
|
|
|
<div class="card">
|
|
|
<h3>💳 支付方式分布</h3>
|
|
|
<div id="paymentChart"></div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="card">
|
|
|
<h3>📈 月度营收趋势</h3>
|
|
|
<div id="monthlyChart"></div>
|
|
|
</div>
|
|
|
|
|
|
<div class="card">
|
|
|
<h3>📋 各房型详细统计</h3>
|
|
|
<table>
|
|
|
<thead>
|
|
|
<tr>
|
|
|
<th>房型</th>
|
|
|
<th>房间数</th>
|
|
|
<th>本月入住次数</th>
|
|
|
<th>总入住天数</th>
|
|
|
<th>营收</th>
|
|
|
<th>入住率</th>
|
|
|
<th>平均房价</th>
|
|
|
</tr>
|
|
|
</thead>
|
|
|
<tbody id="reportList"></tbody>
|
|
|
</table>
|
|
|
</div>
|
|
|
|
|
|
<div class="card">
|
|
|
<h3>🏆 客户消费排行榜(本月TOP10)</h3>
|
|
|
<table>
|
|
|
<thead>
|
|
|
<tr>
|
|
|
<th>排名</th>
|
|
|
<th>客户姓名</th>
|
|
|
<th>会员等级</th>
|
|
|
<th>入住次数</th>
|
|
|
<th>入住天数</th>
|
|
|
<th>本月消费</th>
|
|
|
</tr>
|
|
|
</thead>
|
|
|
<tbody id="customerRankList"></tbody>
|
|
|
</table>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div id="modalContainer"></div>
|
|
|
|
|
|
<script>
|
|
|
// ==================== 数据定义 ====================
|
|
|
|
|
|
var rooms = [
|
|
|
{ id: "R001", roomNo: "3101", type: "经济单人间", floor: 3, direction: "北", area: 18, price: 168, status: "空闲" },
|
|
|
{ id: "R002", roomNo: "3102", type: "经济单人间", floor: 3, direction: "北", area: 18, price: 168, status: "已入住" },
|
|
|
{ id: "R003", roomNo: "3103", type: "标准单人间", floor: 3, direction: "南", area: 22, price: 218, status: "空闲" },
|
|
|
{ id: "R004", roomNo: "3105", type: "标准双人间", floor: 3, direction: "南", area: 28, price: 288, status: "已预定" },
|
|
|
{ id: "R005", roomNo: "5201", type: "标准双人间", floor: 5, direction: "东", area: 28, price: 298, status: "空闲" },
|
|
|
{ id: "R006", roomNo: "5202", type: "标准双人间", floor: 5, direction: "南", area: 28, price: 308, status: "已入住" },
|
|
|
{ id: "R007", roomNo: "5203", type: "豪华双人间", floor: 5, direction: "南", area: 35, price: 388, status: "清洁中" },
|
|
|
{ id: "R008", roomNo: "5205", type: "豪华双人间", floor: 5, direction: "东", area: 35, price: 398, status: "空闲" },
|
|
|
{ id: "R009", roomNo: "6301", type: "商务大床房", floor: 6, direction: "南", area: 38, price: 458, status: "已入住" },
|
|
|
{ id: "R010", roomNo: "6302", type: "商务大床房", floor: 6, direction: "南", area: 38, price: 458, status: "空闲" },
|
|
|
{ id: "R011", roomNo: "6303", type: "家庭亲子房", floor: 6, direction: "东", area: 45, price: 528, status: "已预定" },
|
|
|
{ id: "R012", roomNo: "6305", type: "家庭亲子房", floor: 6, direction: "南", area: 45, price: 538, status: "空闲" },
|
|
|
{ id: "R013", roomNo: "8801", type: "豪华套房", floor: 8, direction: "南", area: 65, price: 888, status: "空闲" },
|
|
|
{ id: "R014", roomNo: "8802", type: "豪华套房", floor: 8, direction: "东", area: 65, price: 888, status: "已入住" },
|
|
|
{ id: "R015", roomNo: "10001", type: "总统套房", floor: 10, direction: "南", area: 120, price: 1888, status: "空闲" },
|
|
|
{ id: "R016", roomNo: "12001", type: "总统套房", floor: 12, direction: "南", area: 120, price: 2088, status: "已预定" }
|
|
|
];
|
|
|
|
|
|
var customers = [
|
|
|
{ id: "C001", name: "张伟", gender: "男", phone: "13812345678", idCard: "110101199503156789", vip: "金卡会员", totalSpent: 12680, tags: ["南向", "高楼层", "安静"] },
|
|
|
{ id: "C002", name: "王芳", gender: "女", phone: "13923456789", idCard: "310104199208234567", vip: "钻石会员", totalSpent: 35600, tags: ["套房", "江景", "无烟"] },
|
|
|
{ id: "C003", name: "李强", gender: "男", phone: "15834567890", idCard: "440106199012123456", vip: "银卡会员", totalSpent: 5680, tags: ["电梯房", "靠窗"] },
|
|
|
{ id: "C004", name: "刘洋", gender: "男", phone: "13745678901", idCard: "320102198811056789", vip: "普通会员", totalSpent: 1280, tags: ["经济型"] },
|
|
|
{ id: "C005", name: "陈静", gender: "女", phone: "18656789012", idCard: "330106199306189012", vip: "金卡会员", totalSpent: 18900, tags: ["大床房", "浴缸"] },
|
|
|
{ id: "C006", name: "杨光", gender: "男", phone: "13567890123", idCard: "420102199107223456", vip: "普通会员", totalSpent: 856, tags: ["安静"] },
|
|
|
{ id: "C007", name: "赵雪", gender: "女", phone: "15878901234", idCard: "510104199505124567", vip: "银卡会员", totalSpent: 6800, tags: ["南向", "早餐"] },
|
|
|
{ id: "C008", name: "黄海", gender: "男", phone: "13789012345", idCard: "610103198908087890", vip: "钻石会员", totalSpent: 52800, tags: ["套房", "行政楼层"] },
|
|
|
{ id: "C009", name: "周婷", gender: "女", phone: "18890123456", idCard: "210102199204156789", vip: "金卡会员", totalSpent: 15600, tags: ["亲子房", "加床"] },
|
|
|
{ id: "C010", name: "吴明", gender: "男", phone: "13501234567", idCard: "120101199609234567", vip: "普通会员", totalSpent: 680, tags: ["靠近电梯"] },
|
|
|
{ id: "C011", name: "徐丽", gender: "女", phone: "15612345678", idCard: "370102199311123890", vip: "银卡会员", totalSpent: 8900, tags: ["无烟房", "南向"] },
|
|
|
{ id: "C012", name: "孙鹏", gender: "男", phone: "13823456789", idCard: "430102198712056123", vip: "金卡会员", totalSpent: 22800, tags: ["商务房", "办公桌"] },
|
|
|
{ id: "C013", name: "马云飞", gender: "男", phone: "18934567890", idCard: "340102199008189234", vip: "普通会员", totalSpent: 1560, tags: ["经济型", "安静"] },
|
|
|
{ id: "C014", name: "朱红", gender: "女", phone: "13645678901", idCard: "350102199406223456", vip: "银卡会员", totalSpent: 7200, tags: ["双床房"] },
|
|
|
{ id: "C015", name: "胡建国", gender: "男", phone: "15756789012", idCard: "410102197503124567", vip: "钻石会员", totalSpent: 68900, tags: ["总统套房", "接机"] },
|
|
|
{ id: "C016", name: "林小燕", gender: "女", phone: "13867890123", idCard: "450102199207056789", vip: "金卡会员", totalSpent: 16800, tags: ["靠窗", "高楼层"] },
|
|
|
{ id: "C017", name: "郭志远", gender: "男", phone: "18978901234", idCard: "500102199109187890", vip: "普通会员", totalSpent: 960, tags: ["临时住宿"] },
|
|
|
{ id: "C018", name: "何晓峰", gender: "男", phone: "13089012345", idCard: "530102198806123901", vip: "银卡会员", totalSpent: 5200, tags: ["安静", "南向"] },
|
|
|
{ id: "C019", name: "高圆圆", gender: "女", phone: "15190123456", idCard: "620102199404056234", vip: "金卡会员", totalSpent: 19800, tags: ["豪华房", "浴缸"] },
|
|
|
{ id: "C020", name: "郑成功", gender: "男", phone: "13201234567", idCard: "230102198211189567", vip: "钻石会员", totalSpent: 45600, tags: ["行政套房", "会议室"] },
|
|
|
{ id: "C021", name: "梁思思", gender: "女", phone: "18312345678", idCard: "360102199603223890", vip: "普通会员", totalSpent: 728, tags: ["标准间"] },
|
|
|
{ id: "C022", name: "谢天华", gender: "男", phone: "15423456789", idCard: "640102199001124123", vip: "银卡会员", totalSpent: 6100, tags: ["电梯房"] },
|
|
|
{ id: "C023", name: "宋佳", gender: "女", phone: "13534567890", idCard: "650102199708056456", vip: "普通会员", totalSpent: 580, tags: ["经济型"] },
|
|
|
{ id: "C024", name: "唐俊杰", gender: "男", phone: "18645678901", idCard: "140102198504187789", vip: "金卡会员", totalSpent: 21600, tags: ["商务房", "快速退房"] },
|
|
|
{ id: "C025", name: "许文强", gender: "男", phone: "13756789012", idCard: "150102197908124012", vip: "钻石会员", totalSpent: 88900, tags: ["贵宾服务", "专属管家"] },
|
|
|
{ id: "C026", name: "冯晓琳", gender: "女", phone: "15867890123", idCard: "220102199210053345", vip: "银卡会员", totalSpent: 7800, tags: ["亲子房", "加床"] }
|
|
|
];
|
|
|
|
|
|
var orders = [
|
|
|
{ id: "ORD20240115001", customerName: "张伟", roomNo: "3102", roomType: "经济单人间", checkIn: "2024-01-15", checkOut: "2024-01-17", days: 2, price: 336, status: "已入住" },
|
|
|
{ id: "ORD20240115002", customerName: "王芳", roomNo: "8802", roomType: "豪华套房", checkIn: "2024-01-14", checkOut: "2024-01-18", days: 4, price: 3552, status: "已入住" },
|
|
|
{ id: "ORD20240116001", customerName: "陈静", roomNo: "6301", roomType: "商务大床房", checkIn: "2024-01-16", checkOut: "2024-01-19", days: 3, price: 1374, status: "已入住" },
|
|
|
{ id: "ORD20240116002", customerName: "黄海", roomNo: "5202", roomType: "标准双人间", checkIn: "2024-01-16", checkOut: "2024-01-17", days: 1, price: 308, status: "已入住" },
|
|
|
{ id: "ORD20240117001", customerName: "李强", roomNo: "3105", roomType: "标准双人间", checkIn: "2024-01-18", checkOut: "2024-01-20", days: 2, price: 576, status: "已确认" },
|
|
|
{ id: "ORD20240117002", customerName: "徐丽", roomNo: "6303", roomType: "家庭亲子房", checkIn: "2024-01-19", checkOut: "2024-01-22", days: 3, price: 1584, status: "已确认" },
|
|
|
{ id: "ORD20240117003", customerName: "胡建国", roomNo: "12001", roomType: "总统套房", checkIn: "2024-01-20", checkOut: "2024-01-25", days: 5, price: 10440, status: "已确认" },
|
|
|
{ id: "ORD20240117004", customerName: "郑成功", roomNo: "8801", roomType: "豪华套房", checkIn: "2024-01-18", checkOut: "2024-01-21", days: 3, price: 2664, status: "待确认" },
|
|
|
{ id: "ORD20240117005", customerName: "周婷", roomNo: "6305", roomType: "家庭亲子房", checkIn: "2024-01-19", checkOut: "2024-01-21", days: 2, price: 1076, status: "待确认" },
|
|
|
{ id: "ORD20240110001", customerName: "刘洋", roomNo: "3101", roomType: "经济单人间", checkIn: "2024-01-10", checkOut: "2024-01-12", days: 2, price: 336, status: "已退房" },
|
|
|
{ id: "ORD20240108001", customerName: "赵雪", roomNo: "5201", roomType: "标准双人间", checkIn: "2024-01-08", checkOut: "2024-01-10", days: 2, price: 596, status: "已退房" },
|
|
|
{ id: "ORD20240105001", customerName: "孙鹏", roomNo: "6302", roomType: "商务大床房", checkIn: "2024-01-05", checkOut: "2024-01-08", days: 3, price: 1374, status: "已退房" },
|
|
|
{ id: "ORD20240103001", customerName: "高圆圆", roomNo: "5203", roomType: "豪华双人间", checkIn: "2024-01-03", checkOut: "2024-01-06", days: 3, price: 1164, status: "已退房" },
|
|
|
{ id: "ORD20240102001", customerName: "许文强", roomNo: "10001", roomType: "总统套房", checkIn: "2024-01-02", checkOut: "2024-01-05", days: 3, price: 5664, status: "已退房" },
|
|
|
{ id: "ORD20240101001", customerName: "林小燕", roomNo: "5205", roomType: "豪华双人间", checkIn: "2024-01-01", checkOut: "2024-01-03", days: 2, price: 796, status: "已退房" },
|
|
|
{ id: "ORD20240115003", customerName: "杨光", roomNo: "3103", roomType: "标准单人间", checkIn: "2024-01-15", checkOut: "2024-01-16", days: 1, price: 218, status: "已取消" }
|
|
|
];
|
|
|
|
|
|
// 扩展的入住记录数据
|
|
|
var checkins = [
|
|
|
// 2024年1月 - 在住
|
|
|
{ id: "CHK20240116004", customerName: "张伟", phone: "13812345678", roomNo: "3102", roomType: "经济单人间", checkInTime: "2024-01-15 15:23", checkOutTime: "-", days: 2, amount: 336, payMethod: "待结算", status: "在住", remark: "金卡会员,赠送早餐" },
|
|
|
{ id: "CHK20240116003", customerName: "王芳", phone: "13923456789", roomNo: "8802", roomType: "豪华套房", checkInTime: "2024-01-14 14:05", checkOutTime: "-", days: 4, amount: 3552, payMethod: "待结算", status: "在住", remark: "钻石会员,升级房型" },
|
|
|
{ id: "CHK20240116002", customerName: "陈静", phone: "18656789012", roomNo: "6301", roomType: "商务大床房", checkInTime: "2024-01-16 16:42", checkOutTime: "-", days: 3, amount: 1374, payMethod: "待结算", status: "在住", remark: "需要发票" },
|
|
|
{ id: "CHK20240116001", customerName: "黄海", phone: "13789012345", roomNo: "5202", roomType: "标准双人间", checkInTime: "2024-01-16 20:15", checkOutTime: "-", days: 1, amount: 308, payMethod: "待结算", status: "在住", remark: "商务出差" },
|
|
|
|
|
|
// 2024年1月 - 已退房
|
|
|
{ id: "CHK20240114001", customerName: "唐俊杰", phone: "18645678901", roomNo: "6302", roomType: "商务大床房", checkInTime: "2024-01-12 14:30", checkOutTime: "2024-01-14 11:20", days: 2, amount: 916, payMethod: "信用卡", status: "已退房", remark: "公司报销" },
|
|
|
{ id: "CHK20240113001", customerName: "马云飞", phone: "18934567890", roomNo: "3101", roomType: "经济单人间", checkInTime: "2024-01-11 18:45", checkOutTime: "2024-01-13 10:30", days: 2, amount: 336, payMethod: "微信支付", status: "已退房", remark: "正常退房" },
|
|
|
{ id: "CHK20240112001", customerName: "刘洋", phone: "13745678901", roomNo: "3101", roomType: "经济单人间", checkInTime: "2024-01-10 14:32", checkOutTime: "2024-01-12 11:05", days: 2, amount: 336, payMethod: "微信支付", status: "已退房", remark: "正常退房" },
|
|
|
{ id: "CHK20240111001", customerName: "朱红", phone: "13645678901", roomNo: "5201", roomType: "标准双人间", checkInTime: "2024-01-09 15:20", checkOutTime: "2024-01-11 10:45", days: 2, amount: 596, payMethod: "支付宝", status: "已退房", remark: "正常退房" },
|
|
|
{ id: "CHK20240110001", customerName: "赵雪", phone: "15878901234", roomNo: "5201", roomType: "标准双人间", checkInTime: "2024-01-08 15:20", checkOutTime: "2024-01-10 10:30", days: 2, amount: 596, payMethod: "支付宝", status: "已退房", remark: "正常退房" },
|
|
|
{ id: "CHK20240109001", customerName: "谢天华", phone: "15423456789", roomNo: "3103", roomType: "标准单人间", checkInTime: "2024-01-07 16:00", checkOutTime: "2024-01-09 09:30", days: 2, amount: 436, payMethod: "微信支付", status: "已退房", remark: "正常退房" },
|
|
|
{ id: "CHK20240108001", customerName: "孙鹏", phone: "13823456789", roomNo: "6302", roomType: "商务大床房", checkInTime: "2024-01-05 16:45", checkOutTime: "2024-01-08 12:00", days: 3, amount: 1374, payMethod: "信用卡", status: "已退房", remark: "公司报销" },
|
|
|
{ id: "CHK20240107001", customerName: "冯晓琳", phone: "15867890123", roomNo: "6303", roomType: "家庭亲子房", checkInTime: "2024-01-04 14:20", checkOutTime: "2024-01-07 11:00", days: 3, amount: 1584, payMethod: "支付宝", status: "已退房", remark: "带小孩入住" },
|
|
|
{ id: "CHK20240106001", customerName: "高圆圆", phone: "15190123456", roomNo: "5203", roomType: "豪华双人间", checkInTime: "2024-01-03 14:00", checkOutTime: "2024-01-06 11:20", days: 3, amount: 1164, payMethod: "微信支付", status: "已退房", remark: "正常退房" },
|
|
|
{ id: "CHK20240105001", customerName: "许文强", phone: "13756789012", roomNo: "10001", roomType: "总统套房", checkInTime: "2024-01-02 12:00", checkOutTime: "2024-01-05 14:00", days: 3, amount: 5664, payMethod: "现金", status: "已退房", remark: "VIP客户,延迟退房" },
|
|
|
{ id: "CHK20240104001", customerName: "何晓峰", phone: "13089012345", roomNo: "5205", roomType: "豪华双人间", checkInTime: "2024-01-02 15:30", checkOutTime: "2024-01-04 10:15", days: 2, amount: 796, payMethod: "微信支付", status: "已退房", remark: "正常退房" },
|
|
|
{ id: "CHK20240103001", customerName: "林小燕", phone: "13867890123", roomNo: "5205", roomType: "豪华双人间", checkInTime: "2024-01-01 18:30", checkOutTime: "2024-01-03 10:00", days: 2, amount: 796, payMethod: "支付宝", status: "已退房", remark: "新年入住" },
|
|
|
{ id: "CHK20240103002", customerName: "郑成功", phone: "13201234567", roomNo: "8801", roomType: "豪华套房", checkInTime: "2024-01-01 14:00", checkOutTime: "2024-01-03 12:00", days: 2, amount: 1776, payMethod: "信用卡", status: "已退房", remark: "商务会议" },
|
|
|
|
|
|
// 2023年12月
|
|
|
{ id: "CHK20231231001", customerName: "周婷", phone: "18890123456", roomNo: "6305", roomType: "家庭亲子房", checkInTime: "2023-12-29 14:00", checkOutTime: "2023-12-31 11:00", days: 2, amount: 1076, payMethod: "支付宝", status: "已退房", remark: "跨年入住" },
|
|
|
{ id: "CHK20231230001", customerName: "吴明", phone: "13501234567", roomNo: "3101", roomType: "经济单人间", checkInTime: "2023-12-28 16:30", checkOutTime: "2023-12-30 10:00", days: 2, amount: 336, payMethod: "微信支付", status: "已退房", remark: "正常退房" },
|
|
|
{ id: "CHK20231229001", customerName: "李强", phone: "15834567890", roomNo: "5201", roomType: "标准双人间", checkInTime: "2023-12-26 15:00", checkOutTime: "2023-12-29 11:30", days: 3, amount: 894, payMethod: "支付宝", status: "已退房", remark: "正常退房" },
|
|
|
{ id: "CHK20231228001", customerName: "徐丽", phone: "15612345678", roomNo: "3103", roomType: "标准单人间", checkInTime: "2023-12-25 14:20", checkOutTime: "2023-12-28 10:45", days: 3, amount: 654, payMethod: "微信支付", status: "已退房", remark: "圣诞入住" },
|
|
|
{ id: "CHK20231227001", customerName: "胡建国", phone: "15756789012", roomNo: "12001", roomType: "总统套房", checkInTime: "2023-12-22 10:00", checkOutTime: "2023-12-27 14:00", days: 5, amount: 10440, payMethod: "银行转账", status: "已退房", remark: "VIP客户,接机送机" },
|
|
|
{ id: "CHK20231225001", customerName: "张伟", phone: "13812345678", roomNo: "3102", roomType: "经济单人间", checkInTime: "2023-12-23 15:30", checkOutTime: "2023-12-25 11:00", days: 2, amount: 336, payMethod: "会员积分", status: "已退房", remark: "积分兑换" },
|
|
|
{ id: "CHK20231224001", customerName: "王芳", phone: "13923456789", roomNo: "8802", roomType: "豪华套房", checkInTime: "2023-12-20 14:00", checkOutTime: "2023-12-24 12:00", days: 4, amount: 3552, payMethod: "信用卡", status: "已退房", remark: "圣诞假期" },
|
|
|
{ id: "CHK20231222001", customerName: "陈静", phone: "18656789012", roomNo: "6301", roomType: "商务大床房", checkInTime: "2023-12-19 16:00", checkOutTime: "2023-12-22 11:30", days: 3, amount: 1374, payMethod: "微信支付", status: "已退房", remark: "商务出差" },
|
|
|
{ id: "CHK20231220001", customerName: "黄海", phone: "13789012345", roomNo: "8801", roomType: "豪华套房", checkInTime: "2023-12-17 14:30", checkOutTime: "2023-12-20 10:00", days: 3, amount: 2664, payMethod: "信用卡", status: "已退房", remark: "公司年会" },
|
|
|
{ id: "CHK20231218001", customerName: "杨光", phone: "13567890123", roomNo: "3101", roomType: "经济单人间", checkInTime: "2023-12-16 18:00", checkOutTime: "2023-12-18 09:30", days: 2, amount: 336, payMethod: "现金", status: "已退房", remark: "正常退房" },
|
|
|
{ id: "CHK20231215001", customerName: "宋佳", phone: "13534567890", roomNo: "3103", roomType: "标准单人间", checkInTime: "2023-12-13 15:45", checkOutTime: "2023-12-15 10:20", days: 2, amount: 436, payMethod: "微信支付", status: "已退房", remark: "正常退房" },
|
|
|
{ id: "CHK20231212001", customerName: "梁思思", phone: "18312345678", roomNo: "5202", roomType: "标准双人间", checkInTime: "2023-12-10 14:00", checkOutTime: "2023-12-12 11:00", days: 2, amount: 616, payMethod: "支付宝", status: "已退房", remark: "正常退房" },
|
|
|
{ id: "CHK20231210001", customerName: "郭志远", phone: "18978901234", roomNo: "3101", roomType: "经济单人间", checkInTime: "2023-12-08 17:30", checkOutTime: "2023-12-10 10:00", days: 2, amount: 336, payMethod: "微信支付", status: "已退房", remark: "临时住宿" },
|
|
|
|
|
|
// 2023年11月
|
|
|
{ id: "CHK20231130001", customerName: "许文强", phone: "13756789012", roomNo: "10001", roomType: "总统套房", checkInTime: "2023-11-26 11:00", checkOutTime: "2023-11-30 15:00", days: 4, amount: 7552, payMethod: "银行转账", status: "已退房", remark: "VIP客户" },
|
|
|
{ id: "CHK20231128001", customerName: "孙鹏", phone: "13823456789", roomNo: "6302", roomType: "商务大床房", checkInTime: "2023-11-25 14:30", checkOutTime: "2023-11-28 11:00", days: 3, amount: 1374, payMethod: "信用卡", status: "已退房", remark: "商务出差" },
|
|
|
{ id: "CHK20231125001", customerName: "高圆圆", phone: "15190123456", roomNo: "5203", roomType: "豪华双人间", checkInTime: "2023-11-22 15:00", checkOutTime: "2023-11-25 10:30", days: 3, amount: 1164, payMethod: "微信支付", status: "已退房", remark: "正常退房" },
|
|
|
{ id: "CHK20231122001", customerName: "唐俊杰", phone: "18645678901", roomNo: "6301", roomType: "商务大床房", checkInTime: "2023-11-19 16:20", checkOutTime: "2023-11-22 12:00", days: 3, amount: 1374, payMethod: "信用卡", status: "已退房", remark: "公司报销" },
|
|
|
{ id: "CHK20231120001", customerName: "周婷", phone: "18890123456", roomNo: "6303", roomType: "家庭亲子房", checkInTime: "2023-11-17 14:00", checkOutTime: "2023-11-20 11:00", days: 3, amount: 1584, payMethod: "支付宝", status: "已退房", remark: "周末家庭游" }
|
|
|
];
|
|
|
|
|
|
var roomTypes = [
|
|
|
{ name: "经济单人间", basePrice: 168 },
|
|
|
{ name: "标准单人间", basePrice: 218 },
|
|
|
{ name: "标准双人间", basePrice: 288 },
|
|
|
{ name: "豪华双人间", basePrice: 388 },
|
|
|
{ name: "商务大床房", basePrice: 458 },
|
|
|
{ name: "家庭亲子房", basePrice: 528 },
|
|
|
{ name: "豪华套房", basePrice: 888 },
|
|
|
{ name: "总统套房", basePrice: 1888 }
|
|
|
];
|
|
|
|
|
|
// 月度营收数据
|
|
|
var monthlyRevenue = [
|
|
|
{ month: "2023-07", revenue: 52680, orders: 28 },
|
|
|
{ month: "2023-08", revenue: 68450, orders: 35 },
|
|
|
{ month: "2023-09", revenue: 58920, orders: 31 },
|
|
|
{ month: "2023-10", revenue: 72350, orders: 38 },
|
|
|
{ month: "2023-11", revenue: 65800, orders: 33 },
|
|
|
{ month: "2023-12", revenue: 76920, orders: 42 },
|
|
|
{ month: "2024-01", revenue: 86752, orders: 35 }
|
|
|
];
|
|
|
|
|
|
// 客户消费排行
|
|
|
var customerRanking = [
|
|
|
{ name: "许文强", vip: "钻石会员", times: 3, days: 10, spent: 18880 },
|
|
|
{ name: "胡建国", vip: "钻石会员", times: 2, days: 10, spent: 20880 },
|
|
|
{ name: "王芳", vip: "钻石会员", times: 2, days: 8, spent: 7104 },
|
|
|
{ name: "黄海", vip: "钻石会员", times: 2, days: 4, spent: 2972 },
|
|
|
{ name: "孙鹏", vip: "金卡会员", times: 3, days: 9, spent: 4122 },
|
|
|
{ name: "陈静", vip: "金卡会员", times: 2, days: 6, spent: 2748 },
|
|
|
{ name: "唐俊杰", vip: "金卡会员", times: 2, days: 5, spent: 2290 },
|
|
|
{ name: "郑成功", vip: "钻石会员", times: 1, days: 2, spent: 1776 },
|
|
|
{ name: "周婷", vip: "金卡会员", times: 2, days: 5, spent: 2660 },
|
|
|
{ name: "高圆圆", vip: "金卡会员", times: 2, days: 6, spent: 2328 }
|
|
|
];
|
|
|
|
|
|
// ==================== 登录和导航 ====================
|
|
|
|
|
|
function login() {
|
|
|
document.getElementById("login").classList.add("hidden");
|
|
|
document.getElementById("main").classList.remove("hidden");
|
|
|
render();
|
|
|
}
|
|
|
|
|
|
function logout() {
|
|
|
if(confirm("确定要退出系统吗?")) {
|
|
|
location.reload();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
function show(id, el) {
|
|
|
var modules = document.querySelectorAll(".module");
|
|
|
for(var i = 0; i < modules.length; i++) {
|
|
|
modules[i].classList.add("hidden");
|
|
|
}
|
|
|
document.getElementById(id).classList.remove("hidden");
|
|
|
|
|
|
var items = document.querySelectorAll(".sidebar li");
|
|
|
for(var j = 0; j < items.length; j++) {
|
|
|
items[j].classList.remove("active");
|
|
|
}
|
|
|
el.classList.add("active");
|
|
|
}
|
|
|
|
|
|
// ==================== 渲染函数 ====================
|
|
|
|
|
|
function render() {
|
|
|
renderRooms();
|
|
|
renderCustomers();
|
|
|
renderOrders();
|
|
|
renderCheckins();
|
|
|
renderReport();
|
|
|
renderHomeCharts();
|
|
|
}
|
|
|
|
|
|
function renderHomeCharts() {
|
|
|
var freeCount = 0, bookedCount = 0, checkinCount = 0, cleaningCount = 0;
|
|
|
for(var i = 0; i < rooms.length; i++) {
|
|
|
if(rooms[i].status === "空闲") freeCount++;
|
|
|
else if(rooms[i].status === "已预定") bookedCount++;
|
|
|
else if(rooms[i].status === "已入住") checkinCount++;
|
|
|
else if(rooms[i].status === "清洁中") cleaningCount++;
|
|
|
}
|
|
|
|
|
|
document.getElementById("roomStatusChart").innerHTML =
|
|
|
'<div style="display:flex;gap:30px">' +
|
|
|
'<div style="text-align:center"><div style="font-size:28px;font-weight:700;color:#4caf50">' + freeCount + '</div><div style="font-size:12px;color:#666">空闲</div></div>' +
|
|
|
'<div style="text-align:center"><div style="font-size:28px;font-weight:700;color:#ff9800">' + bookedCount + '</div><div style="font-size:12px;color:#666">已预定</div></div>' +
|
|
|
'<div style="text-align:center"><div style="font-size:28px;font-weight:700;color:#2196f3">' + checkinCount + '</div><div style="font-size:12px;color:#666">已入住</div></div>' +
|
|
|
'<div style="text-align:center"><div style="font-size:28px;font-weight:700;color:#e91e63">' + cleaningCount + '</div><div style="font-size:12px;color:#666">清洁中</div></div>' +
|
|
|
'</div>';
|
|
|
|
|
|
var recentHtml = '';
|
|
|
var count = 0;
|
|
|
for(var j = 0; j < orders.length && count < 4; j++) {
|
|
|
if(orders[j].status === "待确认" || orders[j].status === "已确认") {
|
|
|
recentHtml += '<div style="display:flex;justify-content:space-between;padding:8px 0;border-bottom:1px solid #eee">' +
|
|
|
'<span>' + orders[j].customerName + ' - ' + orders[j].roomNo + '</span>' +
|
|
|
'<span class="status status-booked">' + orders[j].status + '</span></div>';
|
|
|
count++;
|
|
|
}
|
|
|
}
|
|
|
document.getElementById("recentOrders").innerHTML = recentHtml || '<div style="color:#999">暂无近期预定</div>';
|
|
|
|
|
|
// 今日收入
|
|
|
document.getElementById("todayIncome").innerHTML =
|
|
|
'<div style="display:flex;justify-content:space-between;margin-bottom:12px">' +
|
|
|
'<span>今日入住收入</span><span style="color:#4caf50;font-weight:600">¥5,570</span></div>' +
|
|
|
'<div style="display:flex;justify-content:space-between;margin-bottom:12px">' +
|
|
|
'<span>今日退房结算</span><span style="color:#2196f3;font-weight:600">¥2,328</span></div>' +
|
|
|
'<div style="display:flex;justify-content:space-between;font-weight:600;border-top:1px solid #ddd;padding-top:12px">' +
|
|
|
'<span>今日总收入</span><span style="color:#ff9800">¥7,898</span></div>';
|
|
|
|
|
|
// 待办事项
|
|
|
document.getElementById("todoList").innerHTML =
|
|
|
'<div style="display:flex;align-items:center;padding:8px 0;border-bottom:1px solid #eee">' +
|
|
|
'<span style="background:#ff9800;color:#fff;padding:2px 8px;border-radius:10px;font-size:11px;margin-right:10px">待确认</span>' +
|
|
|
'<span>2条预定待确认</span></div>' +
|
|
|
'<div style="display:flex;align-items:center;padding:8px 0;border-bottom:1px solid #eee">' +
|
|
|
'<span style="background:#e91e63;color:#fff;padding:2px 8px;border-radius:10px;font-size:11px;margin-right:10px">清洁</span>' +
|
|
|
'<span>5203房间待清洁</span></div>' +
|
|
|
'<div style="display:flex;align-items:center;padding:8px 0">' +
|
|
|
'<span style="background:#2196f3;color:#fff;padding:2px 8px;border-radius:10px;font-size:11px;margin-right:10px">退房</span>' +
|
|
|
'<span>4间房间今日预计退房</span></div>';
|
|
|
}
|
|
|
|
|
|
function renderRooms() {
|
|
|
var search = document.getElementById("roomSearch") ? document.getElementById("roomSearch").value.toLowerCase() : "";
|
|
|
var statusFilter = document.getElementById("roomStatusFilter") ? document.getElementById("roomStatusFilter").value : "";
|
|
|
|
|
|
var html = '';
|
|
|
for(var i = 0; i < rooms.length; i++) {
|
|
|
var r = rooms[i];
|
|
|
var matchSearch = r.roomNo.toLowerCase().indexOf(search) >= 0 || r.type.toLowerCase().indexOf(search) >= 0;
|
|
|
var matchStatus = !statusFilter || r.status === statusFilter;
|
|
|
|
|
|
if(matchSearch && matchStatus) {
|
|
|
html += '<tr>' +
|
|
|
'<td><strong>' + r.roomNo + '</strong></td>' +
|
|
|
'<td>' + r.type + '</td>' +
|
|
|
'<td>' + r.floor + '楼</td>' +
|
|
|
'<td>' + r.direction + '向</td>' +
|
|
|
'<td>' + r.area + '㎡</td>' +
|
|
|
'<td style="color:#ff9800"><strong>¥' + r.price + '</strong></td>' +
|
|
|
'<td><span class="status status-' + getStatusClass(r.status) + '">' + r.status + '</span></td>' +
|
|
|
'<td class="actions">' +
|
|
|
'<button class="btn btn-primary btn-sm" onclick="editRoom(\'' + r.id + '\')">编辑</button> ' +
|
|
|
'<button class="btn btn-danger btn-sm" onclick="deleteRoom(\'' + r.id + '\')">删除</button>' +
|
|
|
'</td></tr>';
|
|
|
}
|
|
|
}
|
|
|
document.getElementById("roomList").innerHTML = html;
|
|
|
}
|
|
|
|
|
|
function renderCustomers() {
|
|
|
var search = document.getElementById("customerSearch") ? document.getElementById("customerSearch").value.toLowerCase() : "";
|
|
|
var vipFilter = document.getElementById("customerVipFilter") ? document.getElementById("customerVipFilter").value : "";
|
|
|
|
|
|
var html = '';
|
|
|
for(var i = 0; i < customers.length; i++) {
|
|
|
var c = customers[i];
|
|
|
var matchSearch = c.name.indexOf(search) >= 0 || c.phone.indexOf(search) >= 0;
|
|
|
var matchVip = !vipFilter || c.vip === vipFilter;
|
|
|
|
|
|
if(matchSearch && matchVip) {
|
|
|
var tagsHtml = '';
|
|
|
for(var j = 0; j < c.tags.length; j++) {
|
|
|
tagsHtml += '<span class="tag">' + c.tags[j] + '</span>';
|
|
|
}
|
|
|
|
|
|
html += '<tr>' +
|
|
|
'<td><strong>' + c.name + '</strong></td>' +
|
|
|
'<td>' + c.gender + '</td>' +
|
|
|
'<td class="mono">' + c.phone + '</td>' +
|
|
|
'<td class="mono">' + maskIdCard(c.idCard) + '</td>' +
|
|
|
'<td><span class="tag" style="background:' + getVipColor(c.vip) + ';color:#fff">' + c.vip + '</span></td>' +
|
|
|
'<td style="color:#4caf50"><strong>¥' + c.totalSpent.toLocaleString() + '</strong></td>' +
|
|
|
'<td>' + tagsHtml + '</td>' +
|
|
|
'<td class="actions">' +
|
|
|
'<button class="btn btn-primary btn-sm" onclick="editCustomer(\'' + c.id + '\')">编辑</button> ' +
|
|
|
'<button class="btn btn-danger btn-sm" onclick="deleteCustomer(\'' + c.id + '\')">删除</button>' +
|
|
|
'</td></tr>';
|
|
|
}
|
|
|
}
|
|
|
document.getElementById("customerList").innerHTML = html;
|
|
|
}
|
|
|
|
|
|
function renderOrders() {
|
|
|
var search = document.getElementById("orderSearch") ? document.getElementById("orderSearch").value.toLowerCase() : "";
|
|
|
var statusFilter = document.getElementById("orderStatusFilter") ? document.getElementById("orderStatusFilter").value : "";
|
|
|
|
|
|
var html = '';
|
|
|
for(var i = 0; i < orders.length; i++) {
|
|
|
var o = orders[i];
|
|
|
var matchSearch = o.customerName.indexOf(search) >= 0 || o.roomNo.indexOf(search) >= 0;
|
|
|
var matchStatus = !statusFilter || o.status === statusFilter;
|
|
|
|
|
|
if(matchSearch && matchStatus) {
|
|
|
var actionsHtml = '';
|
|
|
if(o.status === '待确认') actionsHtml += '<button class="btn btn-success btn-sm" onclick="confirmOrder(\'' + o.id + '\')">确认</button> ';
|
|
|
if(o.status === '已确认') actionsHtml += '<button class="btn btn-primary btn-sm" onclick="checkinOrder(\'' + o.id + '\')">入住</button> ';
|
|
|
if(o.status === '已入住') actionsHtml += '<button class="btn btn-warning btn-sm" onclick="checkoutOrder(\'' + o.id + '\')">退房</button> ';
|
|
|
if(o.status !== '已退房' && o.status !== '已取消') actionsHtml += '<button class="btn btn-danger btn-sm" onclick="cancelOrder(\'' + o.id + '\')">取消</button>';
|
|
|
|
|
|
html += '<tr>' +
|
|
|
'<td class="mono" style="font-size:12px">' + o.id + '</td>' +
|
|
|
'<td><strong>' + o.customerName + '</strong></td>' +
|
|
|
'<td>' + o.roomNo + '</td>' +
|
|
|
'<td>' + o.roomType + '</td>' +
|
|
|
'<td>' + o.checkIn + '</td>' +
|
|
|
'<td>' + o.checkOut + '</td>' +
|
|
|
'<td>' + o.days + '晚</td>' +
|
|
|
'<td style="color:#ff9800"><strong>¥' + o.price + '</strong></td>' +
|
|
|
'<td><span class="status status-' + getOrderStatusClass(o.status) + '">' + o.status + '</span></td>' +
|
|
|
'<td class="actions">' + actionsHtml + '</td></tr>';
|
|
|
}
|
|
|
}
|
|
|
document.getElementById("orderList").innerHTML = html;
|
|
|
}
|
|
|
|
|
|
function renderCheckins() {
|
|
|
var search = document.getElementById("checkinSearch") ? document.getElementById("checkinSearch").value.toLowerCase() : "";
|
|
|
var statusFilter = document.getElementById("checkinStatusFilter") ? document.getElementById("checkinStatusFilter").value : "";
|
|
|
var monthFilter = document.getElementById("checkinMonthFilter") ? document.getElementById("checkinMonthFilter").value : "";
|
|
|
|
|
|
var html = '';
|
|
|
var totalAmount = 0;
|
|
|
var inCount = 0;
|
|
|
var outCount = 0;
|
|
|
var totalDays = 0;
|
|
|
|
|
|
for(var i = 0; i < checkins.length; i++) {
|
|
|
var c = checkins[i];
|
|
|
var matchSearch = c.customerName.indexOf(search) >= 0 || c.roomNo.indexOf(search) >= 0;
|
|
|
var matchStatus = !statusFilter || c.status === statusFilter;
|
|
|
var matchMonth = !monthFilter || c.checkInTime.indexOf(monthFilter) >= 0;
|
|
|
|
|
|
// 统计数据
|
|
|
if(c.checkInTime.indexOf("2024-01") >= 0) {
|
|
|
if(c.status === "在住") inCount++;
|
|
|
else outCount++;
|
|
|
totalAmount += c.amount;
|
|
|
totalDays += c.days;
|
|
|
}
|
|
|
|
|
|
if(matchSearch && matchStatus && matchMonth) {
|
|
|
var statusClass = c.status === "在住" ? "checkin" : "checkout";
|
|
|
html += '<tr>' +
|
|
|
'<td class="mono" style="font-size:12px">' + c.id + '</td>' +
|
|
|
'<td><strong>' + c.customerName + '</strong></td>' +
|
|
|
'<td class="mono">' + c.phone + '</td>' +
|
|
|
'<td>' + c.roomNo + '</td>' +
|
|
|
'<td>' + c.roomType + '</td>' +
|
|
|
'<td class="mono">' + c.checkInTime + '</td>' +
|
|
|
'<td class="mono">' + c.checkOutTime + '</td>' +
|
|
|
'<td>' + c.days + '晚</td>' +
|
|
|
'<td style="color:#ff9800"><strong>¥' + c.amount.toLocaleString() + '</strong></td>' +
|
|
|
'<td>' + c.payMethod + '</td>' +
|
|
|
'<td><span class="status status-' + statusClass + '">' + c.status + '</span></td>' +
|
|
|
'<td class="muted">' + c.remark + '</td></tr>';
|
|
|
}
|
|
|
}
|
|
|
document.getElementById("checkinList").innerHTML = html;
|
|
|
|
|
|
// 更新统计
|
|
|
document.getElementById("checkinTotal").textContent = inCount + outCount;
|
|
|
document.getElementById("checkoutTotal").textContent = outCount;
|
|
|
document.getElementById("avgStay").textContent = (totalDays / (inCount + outCount)).toFixed(1);
|
|
|
document.getElementById("totalRevenue").textContent = "¥" + totalAmount.toLocaleString();
|
|
|
}
|
|
|
|
|
|
function renderReport() {
|
|
|
// 房型入住率图表
|
|
|
var roomTypeHtml = '';
|
|
|
var typeData = [
|
|
|
{ name: "经济单人间", rate: 72, color: "#4caf50" },
|
|
|
{ name: "标准单人间", rate: 65, color: "#2196f3" },
|
|
|
{ name: "标准双人间", rate: 78, color: "#ff9800" },
|
|
|
{ name: "豪华双人间", rate: 58, color: "#9c27b0" },
|
|
|
{ name: "商务大床房", rate: 82, color: "#f44336" },
|
|
|
{ name: "家庭亲子房", rate: 55, color: "#00bcd4" },
|
|
|
{ name: "豪华套房", rate: 45, color: "#795548" },
|
|
|
{ name: "总统套房", rate: 35, color: "#607d8b" }
|
|
|
];
|
|
|
for(var t = 0; t < typeData.length; t++) {
|
|
|
roomTypeHtml += '<div class="chart-bar">' +
|
|
|
'<div class="chart-bar-label">' + typeData[t].name.substring(0, 4) + '</div>' +
|
|
|
'<div class="chart-bar-track"><div class="chart-bar-fill" style="width:' + typeData[t].rate + '%;background:' + typeData[t].color + '">' + typeData[t].rate + '%</div></div>' +
|
|
|
'</div>';
|
|
|
}
|
|
|
document.getElementById("roomTypeChart").innerHTML = roomTypeHtml;
|
|
|
|
|
|
// 支付方式分布
|
|
|
var paymentData = [
|
|
|
{ name: "微信支付", percent: 42, color: "#4caf50" },
|
|
|
{ name: "支付宝", percent: 28, color: "#2196f3" },
|
|
|
{ name: "信用卡", percent: 18, color: "#ff9800" },
|
|
|
{ name: "现金", percent: 8, color: "#9c27b0" },
|
|
|
{ name: "其他", percent: 4, color: "#607d8b" }
|
|
|
];
|
|
|
var paymentHtml = '';
|
|
|
for(var p = 0; p < paymentData.length; p++) {
|
|
|
paymentHtml += '<div class="chart-bar">' +
|
|
|
'<div class="chart-bar-label">' + paymentData[p].name + '</div>' +
|
|
|
'<div class="chart-bar-track"><div class="chart-bar-fill" style="width:' + paymentData[p].percent + '%;background:' + paymentData[p].color + '">' + paymentData[p].percent + '%</div></div>' +
|
|
|
'</div>';
|
|
|
}
|
|
|
document.getElementById("paymentChart").innerHTML = paymentHtml;
|
|
|
|
|
|
// 月度营收趋势
|
|
|
var maxRevenue = 100000;
|
|
|
var monthlyHtml = '<div style="display:flex;align-items:flex-end;height:200px;gap:20px;padding:20px 0">';
|
|
|
for(var m = 0; m < monthlyRevenue.length; m++) {
|
|
|
var mr = monthlyRevenue[m];
|
|
|
var height = (mr.revenue / maxRevenue) * 160;
|
|
|
var isCurrentMonth = mr.month === "2024-01";
|
|
|
monthlyHtml += '<div style="flex:1;text-align:center">' +
|
|
|
'<div style="height:' + height + 'px;background:' + (isCurrentMonth ? 'linear-gradient(180deg,#667eea,#764ba2)' : '#e0e0e0') + ';border-radius:8px 8px 0 0;margin-bottom:8px;display:flex;align-items:flex-start;justify-content:center;padding-top:8px">' +
|
|
|
'<span style="color:' + (isCurrentMonth ? '#fff' : '#666') + ';font-size:11px;font-weight:600">¥' + (mr.revenue/10000).toFixed(1) + 'w</span></div>' +
|
|
|
'<div style="font-size:12px;color:#666">' + mr.month.substring(5) + '月</div>' +
|
|
|
'</div>';
|
|
|
}
|
|
|
monthlyHtml += '</div>';
|
|
|
document.getElementById("monthlyChart").innerHTML = monthlyHtml;
|
|
|
|
|
|
// 房型详细统计表格
|
|
|
var reportHtml = '';
|
|
|
var reportData = [
|
|
|
{ name: "经济单人间", count: 2, orders: 8, days: 16, revenue: 2688, rate: 72, avgPrice: 168 },
|
|
|
{ name: "标准单人间", count: 1, orders: 4, days: 9, revenue: 1962, rate: 65, avgPrice: 218 },
|
|
|
{ name: "标准双人间", count: 3, orders: 12, days: 26, revenue: 7748, rate: 78, avgPrice: 298 },
|
|
|
{ name: "豪华双人间", count: 2, orders: 6, days: 14, revenue: 5432, rate: 58, avgPrice: 388 },
|
|
|
{ name: "商务大床房", count: 2, orders: 8, days: 22, revenue: 10076, rate: 82, avgPrice: 458 },
|
|
|
{ name: "家庭亲子房", count: 2, orders: 5, days: 13, revenue: 6868, rate: 55, avgPrice: 528 },
|
|
|
{ name: "豪华套房", count: 2, orders: 4, days: 11, revenue: 9768, rate: 45, avgPrice: 888 },
|
|
|
{ name: "总统套房", count: 2, orders: 3, days: 12, revenue: 23656, rate: 35, avgPrice: 1972 }
|
|
|
];
|
|
|
for(var r = 0; r < reportData.length; r++) {
|
|
|
var rd = reportData[r];
|
|
|
reportHtml += '<tr>' +
|
|
|
'<td><strong>' + rd.name + '</strong></td>' +
|
|
|
'<td>' + rd.count + '间</td>' +
|
|
|
'<td>' + rd.orders + '次</td>' +
|
|
|
'<td>' + rd.days + '天</td>' +
|
|
|
'<td style="color:#ff9800"><strong>¥' + rd.revenue.toLocaleString() + '</strong></td>' +
|
|
|
'<td><div style="display:flex;align-items:center;gap:8px">' +
|
|
|
'<div style="background:#e0e0e0;border-radius:10px;height:8px;width:80px">' +
|
|
|
'<div style="background:#4caf50;border-radius:10px;height:8px;width:' + rd.rate + '%"></div>' +
|
|
|
'</div>' +
|
|
|
'<span>' + rd.rate + '%</span>' +
|
|
|
'</div></td>' +
|
|
|
'<td>¥' + rd.avgPrice + '</td></tr>';
|
|
|
}
|
|
|
document.getElementById("reportList").innerHTML = reportHtml;
|
|
|
|
|
|
// 客户消费排行
|
|
|
var rankHtml = '';
|
|
|
for(var k = 0; k < customerRanking.length; k++) {
|
|
|
var cr = customerRanking[k];
|
|
|
var rankBadge = '';
|
|
|
if(k === 0) rankBadge = '<span style="background:#ffd700;color:#fff;padding:2px 8px;border-radius:10px">🥇</span>';
|
|
|
else if(k === 1) rankBadge = '<span style="background:#c0c0c0;color:#fff;padding:2px 8px;border-radius:10px">🥈</span>';
|
|
|
else if(k === 2) rankBadge = '<span style="background:#cd7f32;color:#fff;padding:2px 8px;border-radius:10px">🥉</span>';
|
|
|
else rankBadge = '<span style="background:#e0e0e0;padding:2px 10px;border-radius:10px">' + (k+1) + '</span>';
|
|
|
|
|
|
rankHtml += '<tr>' +
|
|
|
'<td>' + rankBadge + '</td>' +
|
|
|
'<td><strong>' + cr.name + '</strong></td>' +
|
|
|
'<td><span class="tag" style="background:' + getVipColor(cr.vip) + ';color:#fff">' + cr.vip + '</span></td>' +
|
|
|
'<td>' + cr.times + '次</td>' +
|
|
|
'<td>' + cr.days + '天</td>' +
|
|
|
'<td style="color:#ff9800"><strong>¥' + cr.spent.toLocaleString() + '</strong></td></tr>';
|
|
|
}
|
|
|
document.getElementById("customerRankList").innerHTML = rankHtml;
|
|
|
}
|
|
|
|
|
|
// ==================== 辅助函数 ====================
|
|
|
|
|
|
function getStatusClass(status) {
|
|
|
if(status === "空闲") return "free";
|
|
|
if(status === "已预定") return "booked";
|
|
|
if(status === "已入住") return "checkin";
|
|
|
if(status === "清洁中") return "cleaning";
|
|
|
return "free";
|
|
|
}
|
|
|
|
|
|
function getOrderStatusClass(status) {
|
|
|
if(status === "待确认") return "booked";
|
|
|
if(status === "已确认") return "checkin";
|
|
|
if(status === "已入住") return "checkin";
|
|
|
if(status === "已退房") return "free";
|
|
|
if(status === "已取消") return "cleaning";
|
|
|
return "free";
|
|
|
}
|
|
|
|
|
|
function getVipColor(vip) {
|
|
|
if(vip === "普通会员") return "#9e9e9e";
|
|
|
if(vip === "银卡会员") return "#78909c";
|
|
|
if(vip === "金卡会员") return "#ffa000";
|
|
|
if(vip === "钻石会员") return "#7c4dff";
|
|
|
return "#9e9e9e";
|
|
|
}
|
|
|
|
|
|
function maskIdCard(id) {
|
|
|
return id.substring(0, 6) + "********" + id.substring(14);
|
|
|
}
|
|
|
|
|
|
function exportCheckins() {
|
|
|
alert("入住记录已导出为Excel文件!(前端演示)");
|
|
|
}
|
|
|
|
|
|
// ==================== 模态框 ====================
|
|
|
|
|
|
function openRoomModal() {
|
|
|
document.getElementById("modalContainer").innerHTML =
|
|
|
'<div class="modal" onclick="closeModal(event)">' +
|
|
|
'<div class="modal-content" onclick="event.stopPropagation()">' +
|
|
|
'<h3>添加房间</h3>' +
|
|
|
'<div class="form-group"><label>房间号</label><input placeholder="如:3101"></div>' +
|
|
|
'<div class="form-group"><label>房型</label><select>' +
|
|
|
'<option>经济单人间</option><option>标准单人间</option><option>标准双人间</option>' +
|
|
|
'<option>豪华双人间</option><option>商务大床房</option><option>家庭亲子房</option>' +
|
|
|
'<option>豪华套房</option><option>总统套房</option></select></div>' +
|
|
|
'<div class="form-group"><label>楼层</label><input type="number" placeholder="如:3"></div>' +
|
|
|
'<div class="form-group"><label>价格(元/晚)</label><input type="number" placeholder="如:288"></div>' +
|
|
|
'<div class="form-actions">' +
|
|
|
'<button class="btn" onclick="closeModal()">取消</button>' +
|
|
|
'<button class="btn btn-primary" onclick="saveRoom()">保存</button>' +
|
|
|
'</div>' +
|
|
|
'</div>' +
|
|
|
'</div>';
|
|
|
}
|
|
|
|
|
|
function openCustomerModal() {
|
|
|
document.getElementById("modalContainer").innerHTML =
|
|
|
'<div class="modal" onclick="closeModal(event)">' +
|
|
|
'<div class="modal-content" onclick="event.stopPropagation()">' +
|
|
|
'<h3>新增客户</h3>' +
|
|
|
'<div class="form-group"><label>姓名</label><input placeholder="请输入姓名"></div>' +
|
|
|
'<div class="form-group"><label>性别</label><select><option>男</option><option>女</option></select></div>' +
|
|
|
'<div class="form-group"><label>手机号</label><input placeholder="请输入手机号"></div>' +
|
|
|
'<div class="form-group"><label>身份证号</label><input placeholder="请输入身份证号"></div>' +
|
|
|
'<div class="form-actions">' +
|
|
|
'<button class="btn" onclick="closeModal()">取消</button>' +
|
|
|
'<button class="btn btn-primary" onclick="saveCustomer()">保存</button>' +
|
|
|
'</div>' +
|
|
|
'</div>' +
|
|
|
'</div>';
|
|
|
}
|
|
|
|
|
|
function openOrderModal() {
|
|
|
var customerOptions = '';
|
|
|
for(var i = 0; i < customers.length; i++) {
|
|
|
customerOptions += '<option>' + customers[i].name + ' (' + customers[i].phone + ')</option>';
|
|
|
}
|
|
|
var roomOptions = '';
|
|
|
for(var j = 0; j < rooms.length; j++) {
|
|
|
if(rooms[j].status === "空闲") {
|
|
|
roomOptions += '<option>' + rooms[j].roomNo + ' - ' + rooms[j].type + ' (¥' + rooms[j].price + '/晚)</option>';
|
|
|
}
|
|
|
}
|
|
|
|
|
|
document.getElementById("modalContainer").innerHTML =
|
|
|
'<div class="modal" onclick="closeModal(event)">' +
|
|
|
'<div class="modal-content" onclick="event.stopPropagation()">' +
|
|
|
'<h3>新增预定</h3>' +
|
|
|
'<div class="form-group"><label>选择客户</label><select>' + customerOptions + '</select></div>' +
|
|
|
'<div class="form-group"><label>选择房间</label><select>' + roomOptions + '</select></div>' +
|
|
|
'<div class="form-group"><label>入住日期</label><input type="date"></div>' +
|
|
|
'<div class="form-group"><label>离店日期</label><input type="date"></div>' +
|
|
|
'<div class="form-actions">' +
|
|
|
'<button class="btn" onclick="closeModal()">取消</button>' +
|
|
|
'<button class="btn btn-primary" onclick="saveOrder()">保存</button>' +
|
|
|
'</div>' +
|
|
|
'</div>' +
|
|
|
'</div>';
|
|
|
}
|
|
|
|
|
|
function closeModal(event) {
|
|
|
if(!event || event.target.className === 'modal') {
|
|
|
document.getElementById("modalContainer").innerHTML = "";
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// ==================== 操作函数 ====================
|
|
|
|
|
|
function saveRoom() { alert("房间信息已保存!(前端演示)"); closeModal(); }
|
|
|
function saveCustomer() { alert("客户信息已保存!(前端演示)"); closeModal(); }
|
|
|
function saveOrder() { alert("预定已创建!(前端演示)"); closeModal(); }
|
|
|
function editRoom(id) { alert("编辑房间:" + id + "(前端演示)"); }
|
|
|
function deleteRoom(id) { if(confirm("确定删除?")) alert("已删除(前端演示)"); }
|
|
|
function editCustomer(id) { alert("编辑客户:" + id + "(前端演示)"); }
|
|
|
function deleteCustomer(id) { if(confirm("确定删除?")) alert("已删除(前端演示)"); }
|
|
|
function confirmOrder(id) { alert("预定已确认!(前端演示)"); }
|
|
|
function checkinOrder(id) { alert("已办理入住!(前端演示)"); }
|
|
|
function checkoutOrder(id) { alert("已办理退房!(前端演示)"); }
|
|
|
function cancelOrder(id) { if(confirm("确定取消?")) alert("已取消(前端演示)"); }
|
|
|
</script>
|
|
|
|
|
|
</body>
|
|
|
</html> |