# -*- coding: utf-8 -*-
"""
================================================================
酒店客房管理系统（酒店管理专业 AI 教学版）—— Web 网页版
================================================================
适用课程：酒店管理信息系统、酒店数字化运营、Python 程序设计（酒店专业方向）
运行环境：Python 3.8+，仅需安装 Flask（一个轻量 Web 框架）
教学目标：帮助酒店管理专业学生理解酒店客房核心业务流程，掌握
          数字化管理系统的设计逻辑，同时入门 Python Web 编程。

【与原桌面版（tkinter + pandas）的关系】
  本程序是将《酒店客房管理系统（酒店管理专业 AI 教学版）》桌面程序
  改写为「网页版」的完整教学程序：业务逻辑、房型、价格、会员折扣等
  数据完全一致，仅将 GUI 交互（tkinter 窗口）替换为浏览器网页（Flask）。
  为降低零基础学生的环境门槛，本网页版用 Python 内置列表/字典代替 pandas，
  数据分析逻辑等价，可对照原桌面版逐模块学习。

【如何运行】
  1) 安装依赖：  pip install flask
  2) 启动程序：  python hotel_room_web.py
  3) 打开浏览器访问： http://127.0.0.1:5000

【系统核心功能】
  1. 房态统计看板     —— 实时计算总客房数、可售房数、入住率、各类房态数量
  2. 空房智能推荐     —— 按预算 / 房型 / 楼层多条件筛选空闲客房
  3. 客房信息总览     —— 表格化展示全量客房（房号/房型/价格/楼层/状态）
  4. 入住登记办理     —— 录入信息、会员折扣自动计算、房态自动更新
  5. 退房办理         —— 结算、房态转「待清洁」、入住信息归档删除
  6. 入住客户管理     —— 表格展示所有在住客户与预估房费
  7. 运营数据分析     —— 入住率、可售房均价、会员等级分布
================================================================
"""

import os
import json

from flask import Flask, request, render_template_string, redirect, url_for, flash

# ------------------------------------------------------------------
# 一、应用与业务数据初始化（教学重点：酒店业务数据的结构化设计）
# ------------------------------------------------------------------
app = Flask(__name__)
app.secret_key = "hotel-room-teaching-demo"  # flash 消息需要

# 会员等级折扣配置（教学用，贴合酒店实际业务）
MEMBER_DISCOUNT = {
    "普通": 1.0,
    "银卡": 0.95,
    "金卡": 0.88,
    "钻石卡": 0.8,
}

# 房态种类（符合酒店行业通用分类）
ROOM_STATUS = ["空闲", "入住", "待清洁", "维修"]

# 数据文件：用于把内存数据持久化到本地，重启程序不丢失
DATA_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "hotel_data.json")


def init_rooms():
    """初始化 20 间客房基础数据（房号/房型/价格/楼层/状态）。
    完全对应原桌面版的数据：10 楼 101-110、20 楼 201-210。"""
    room_nos = [str(n) for n in range(101, 111)] + [str(n) for n in range(201, 211)]
    room_types = ["大床房", "双床房", "套房", "大床房", "双床房",
                  "大床房", "双床房", "套房", "大床房", "双床房",
                  "大床房", "双床房", "套房", "大床房", "双床房",
                  "大床房", "双床房", "套房", "大床房", "双床房"]
    prices = [398, 428, 888, 418, 438, 388, 418, 868, 378, 408,
              458, 488, 988, 438, 468, 428, 458, 968, 418, 448]
    floors = [10] * 10 + [20] * 10
    statuses = ["空闲", "空闲", "空闲", "空闲", "空闲",
                "空闲", "空闲", "待清洁", "空闲", "维修",
                "空闲", "入住", "待清洁", "空闲", "维修",
                "空闲", "入住", "待清洁", "入住", "维修"]
    rooms = []
    for i in range(20):
        rooms.append({
            "房号": room_nos[i],
            "房型": room_types[i],
            "价格(元)": prices[i],
            "楼层": floors[i],
            "状态": statuses[i],
        })
    return rooms


# 全局业务数据（内存中）
ROOMS = init_rooms()
CHECKINS = []  # 在住客户：房号/姓名/联系电话/入住天数/会员等级/预估房费(元)


# ------------------------------------------------------------------
# 二、数据持久化（教学重点：内存数据如何落盘保存）
# ------------------------------------------------------------------
def save_data():
    """把当前业务数据保存到本地 JSON 文件。"""
    with open(DATA_FILE, "w", encoding="utf-8") as f:
        json.dump({"rooms": ROOMS, "checkins": CHECKINS}, f, ensure_ascii=False, indent=2)


def load_data():
    """启动时尝试从 JSON 文件恢复数据（若存在）。"""
    global ROOMS, CHECKINS
    if os.path.exists(DATA_FILE):
        try:
            with open(DATA_FILE, "r", encoding="utf-8") as f:
                data = json.load(f)
            ROOMS = data.get("rooms", ROOMS)
            CHECKINS = data.get("checkins", [])
        except Exception:
            pass  # 数据文件损坏时回退到初始数据


def reset_data():
    """恢复初始数据（对应原桌面版「刷新所有数据」）。"""
    global ROOMS, CHECKINS
    ROOMS = init_rooms()
    CHECKINS = []
    save_data()


# ------------------------------------------------------------------
# 三、核心业务逻辑函数（教学重点：酒店业务逻辑的代码实现）
# ------------------------------------------------------------------
def find_room(room_no):
    """按房号查找客房，找不到返回 None。"""
    for r in ROOMS:
        if r["房号"] == room_no:
            return r
    return None


def room_stats():
    """房态统计：总客房数、各类房态数量、入住率、可售房均价。

    核心教学公式：入住率 = 已入住房间数 / 酒店总客房数 * 100%
    """
    total = len(ROOMS)
    counts = {s: 0 for s in ROOM_STATUS}
    for r in ROOMS:
        counts[r["状态"]] = counts.get(r["状态"], 0) + 1

    occupied = counts["入住"]
    occupancy_rate = round(occupied / total * 100, 1) if total else 0.0

    # 可售房 = 状态为「空闲」的客房
    sellable = [r for r in ROOMS if r["状态"] == "空闲"]
    avg_price = round(sum(r["价格(元)"] for r in sellable) / len(sellable), 2) if sellable else 0.0

    return {
        "total": total,
        "counts": counts,
        "sellable": len(sellable),
        "occupancy_rate": occupancy_rate,
        "avg_price": avg_price,
    }


def recommend_rooms(budget, room_type, floor):
    """空房智能推荐：从空闲房中按预算/房型/楼层筛选。"""
    result = []
    for r in ROOMS:
        if r["状态"] != "空闲":
            continue
        if budget is not None and r["价格(元)"] > budget:
            continue
        if room_type and r["房型"] != room_type:
            continue
        if floor is not None and r["楼层"] != floor:
            continue
        result.append(r)
    return result


def check_in(room_no, name, phone, days, member):
    """入住登记：校验 → 计算折扣房费 → 更新房态 → 写入客户信息。
    返回 (是否成功, 提示信息)。"""
    room = find_room(room_no)
    if room is None:
        return False, "房号不存在，请核对后重新输入。"
    if room["状态"] != "空闲":
        return False, "房间「%s」当前状态为「%s」，不可入住。" % (room_no, room["状态"])

    # 会员折扣计算：预估房费 = 房价 × 入住天数 × 折扣
    discount = MEMBER_DISCOUNT.get(member, 1.0)
    fee = round(room["价格(元)"] * days * discount, 2)

    room["状态"] = "入住"
    CHECKINS.append({
        "房号": room_no,
        "姓名": name,
        "联系电话": phone,
        "入住天数": days,
        "会员等级": member,
        "预估房费(元)": fee,
    })
    save_data()
    return True, "入住登记成功：房号 %s，预估房费 ¥%.2f（%s 折扣 %.0f%%）" % (
        room_no, fee, member, discount * 100)


def check_out(room_no):
    """退房办理：校验 → 结算 → 房态转「待清洁」→ 删除入住信息。
    返回 (是否成功, 提示信息, 结算信息或None)。"""
    room = find_room(room_no)
    if room is None:
        return False, "房号不存在，请核对后重新输入。", None
    if room["状态"] != "入住":
        return False, "房间「%s」当前状态为「%s」，不是入住状态，无法退房。" % (room_no, room["状态"]), None

    settled = None
    for i, c in enumerate(CHECKINS):
        if c["房号"] == room_no:
            settled = c
            del CHECKINS[i]
            break

    room["状态"] = "待清洁"
    save_data()
    if settled:
        return True, "退房办理成功：房号 %s，应收房费 ¥%.2f。" % (room_no, settled["预估房费(元)"]), settled
    return True, "退房办理成功：房号 %s，已转为「待清洁」。" % room_no, settled


def occupancy_analysis():
    """运营数据分析：入住率、可售房均价。"""
    stats = room_stats()
    return {
        "total": stats["total"],
        "occupied": stats["counts"]["入住"],
        "occupancy_rate": stats["occupancy_rate"],
        "avg_price": stats["avg_price"],
    }


def member_distribution():
    """会员等级分布：统计在住客户各会员等级人数。"""
    dist = {}
    for c in CHECKINS:
        m = c["会员等级"]
        dist[m] = dist.get(m, 0) + 1
    return dist


# ------------------------------------------------------------------
# 四、网页样式与布局（教学重点：Web 页面的 HTML/CSS 基础）
# ------------------------------------------------------------------
CSS = """
* { box-sizing: border-box; }
body { margin: 0; font-family: -apple-system, "Segoe UI", "PingFang SC",
  "Microsoft YaHei", sans-serif; background: #f5f6f8; color: #1a1d24; line-height: 1.6; }
header { background: #fff; border-bottom: 1px solid #e6e8ec; position: sticky; top: 0; z-index: 10; }
.nav { max-width: 1080px; margin: 0 auto; padding: 0 20px; display: flex;
  align-items: center; height: 60px; gap: 4px; flex-wrap: wrap; }
.brand { font-weight: 700; font-size: 17px; margin-right: 16px; color: #1d4ed8; }
.nav a { color: #4a5160; text-decoration: none; padding: 7px 13px; border-radius: 8px;
  font-size: 14px; }
.nav a:hover { background: #eef2ff; color: #1d4ed8; }
.nav a.on { background: #1d4ed8; color: #fff; }
main { max-width: 1080px; margin: 24px auto 60px; padding: 0 20px; }
h1 { font-size: 22px; margin: 0 0 4px; }
h2 { font-size: 17px; margin: 0 0 14px; }
.sub { color: #8a919e; font-size: 13px; margin: 0 0 20px; }
.flash { padding: 10px 14px; border-radius: 8px; margin-bottom: 16px; font-size: 14px; }
.flash.ok { background: #e7f6ec; color: #157347; border: 1px solid #b7e4c7; }
.flash.err { background: #fdecec; color: #b3261e; border: 1px solid #f3c1c1; }
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 14px; margin-bottom: 24px; }
.card { background: #fff; border: 1px solid #e6e8ec; border-radius: 12px; padding: 16px 18px; }
.card .k { font-size: 13px; color: #8a919e; }
.card .v { font-size: 26px; font-weight: 700; margin-top: 4px; }
.card .v.big { color: #1d4ed8; }
.panel { background: #fff; border: 1px solid #e6e8ec; border-radius: 12px; padding: 20px 22px; margin-bottom: 20px; }
table { width: 100%; border-collapse: collapse; font-size: 14px; }
th, td { padding: 10px 12px; text-align: left; border-bottom: 1px solid #eef0f3; }
th { background: #fafbfc; color: #4a5160; font-weight: 600; white-space: nowrap; }
tr:hover td { background: #fafbff; }
.badge { display: inline-block; padding: 2px 10px; border-radius: 999px; font-size: 12px; }
.badge.空闲 { background: #e7f6ec; color: #157347; }
.badge.入住 { background: #eef2ff; color: #1d4ed8; }
.badge.待清洁 { background: #fff4e5; color: #b45309; }
.badge.维修 { background: #fdecec; color: #b3261e; }
form.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 14px; }
label { font-size: 13px; color: #4a5160; display: block; margin-bottom: 6px; }
input, select { width: 100%; padding: 9px 12px; border: 1px solid #d6dae1; border-radius: 8px;
  font-size: 14px; }
input:focus, select:focus { outline: none; border-color: #1d4ed8; }
.btn { display: inline-block; border: none; background: #1d4ed8; color: #fff; padding: 10px 20px;
  border-radius: 8px; font-size: 14px; cursor: pointer; text-decoration: none; }
.btn:hover { background: #1e40af; }
.btn.ghost { background: #fff; color: #4a5160; border: 1px solid #d6dae1; }
.mt { margin-top: 16px; }
.muted { color: #8a919e; }
.foot { text-align: center; color: #b0b6c0; font-size: 12px; margin-top: 40px; }
"""


def base(title, body_html):
    """渲染基础页面骨架（导航 + 内容）。"""
    nav_items = [
        ("/", "房态看板"),
        ("/rooms", "客房总览"),
        ("/recommend", "空房推荐"),
        ("/checkin", "入住登记"),
        ("/checkout", "退房办理"),
        ("/customers", "客户管理"),
        ("/analytics", "数据分析"),
    ]
    nav = "".join(
        '<a href="%s"%s>%s</a>' % (url, ' class="on"' if request.path == url else "", text)
        for url, text in nav_items
    )
    return """<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>%s - 酒店客房管理系统</title>
<style>%s</style>
</head>
<body>
<header><nav class="nav"><span class="brand">🏨 酒店客房管理系统</span>%s</nav></header>
<main>%s</main>
<div class="foot">酒店客房管理系统（酒店管理专业 AI 教学版）· 网页版教学程序</div>
</body>
</html>""" % (title, CSS, nav, body_html)


def render_flashes():
    """渲染 flash 消息（成功绿色 / 失败红色）。"""
    html = ""
    for category, message in (getattr(request, "_flashes", None) or []):
        cls = "ok" if category == "ok" else "err"
        html += '<div class="flash %s">%s</div>' % (cls, message)
    return html


# ------------------------------------------------------------------
# 五、路由（教学重点：Web 请求如何映射到业务逻辑）
# ------------------------------------------------------------------
@app.route("/")
def index():
    stats = room_stats()
    body = render_flashes() + render_template_string("""
<h1>房态看板</h1>
<p class="sub">酒店前台实时房态全局概览 · 数据更新时间：{{ now }}</p>
<div class="cards">
  <div class="card"><div class="k">总客房数</div><div class="v">{{ stats.total }}</div></div>
  <div class="card"><div class="k">可售房数</div><div class="v big">{{ stats.sellable }}</div></div>
  <div class="card"><div class="k">实时入住率</div><div class="v">{{ stats.occupancy_rate }}%</div></div>
  <div class="card"><div class="k">空房</div><div class="v">{{ stats.counts["空闲"] }}</div></div>
  <div class="card"><div class="k">入住</div><div class="v">{{ stats.counts["入住"] }}</div></div>
  <div class="card"><div class="k">待清洁</div><div class="v">{{ stats.counts["待清洁"] }}</div></div>
  <div class="card"><div class="k">维修</div><div class="v">{{ stats.counts["维修"] }}</div></div>
</div>
<div class="panel">
  <h2>快捷操作</h2>
  <a class="btn" href="/recommend">空房推荐</a>
  <a class="btn" href="/checkin">入住登记</a>
  <a class="btn" href="/checkout">退房办理</a>
  <a class="btn ghost" href="/analytics">运营分析</a>
</div>
""", stats=stats, now=__import__("datetime").datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
    return base("房态看板", body)


@app.route("/rooms")
def rooms():
    body = render_flashes() + render_template_string("""
<h1>客房信息总览</h1>
<p class="sub">全量客房档案与实时状态 · 房态流转规则：空闲 → 入住 → 待清洁 → 空闲</p>
<div class="panel">
<table>
<thead><tr><th>房号</th><th>房型</th><th>价格(元)</th><th>楼层</th><th>状态</th></tr></thead>
<tbody>
{% for r in rooms %}
<tr><td>{{ r["房号"] }}</td><td>{{ r["房型"] }}</td><td>{{ r["价格(元)"] }}</td>
<td>{{ r["楼层"] }}楼</td><td><span class="badge {{ r['状态'] }}">{{ r["状态"] }}</span></td></tr>
{% endfor %}
</tbody></table>
</div>
""", rooms=ROOMS)
    return base("客房总览", body)


@app.route("/recommend", methods=["GET", "POST"])
def recommend():
    results = None
    cond = {}
    if request.method == "POST":
        try:
            budget = request.form.get("budget", "").strip()
            budget = int(budget) if budget else None
        except ValueError:
            budget = None
        room_type = request.form.get("room_type", "").strip() or None
        floor_raw = request.form.get("floor", "").strip()
        floor = int(floor_raw) if floor_raw else None
        cond = {"budget": budget, "room_type": room_type, "floor": floor}
        results = recommend_rooms(budget, room_type, floor)

    room_types = sorted({r["房型"] for r in ROOMS})
    floors = sorted({r["楼层"] for r in ROOMS})
    body = render_flashes() + render_template_string("""
<h1>空房智能推荐</h1>
<p class="sub">按客户预算、房型、楼层多条件筛选空闲客房（收益管理与需求匹配）</p>
<div class="panel">
<form method="post" class="grid">
  <div><label>最高预算（元，可留空）</label><input type="number" name="budget"
    value="{{ cond.budget if cond.budget is not none else '' }}"></div>
  <div><label>需求房型（可选）</label>
    <select name="room_type"><option value="">不限</option>
    {% for t in room_types %}<option value="{{ t }}" {{ 'selected' if cond.room_type == t }}>{{ t }}</option>{% endfor %}
    </select></div>
  <div><label>目标楼层（可选）</label>
    <select name="floor"><option value="">不限</option>
    {% for f in floors %}<option value="{{ f }}" {{ 'selected' if cond.floor == f }}>{{ f }}楼</option>{% endfor %}
    </select></div>
  <div><label>&nbsp;</label><button class="btn" type="submit">一键推荐空房</button></div>
</form>
</div>
{% if results is not none %}
<div class="panel">
<h2>推荐结果（共 {{ results|length }} 间）</h2>
{% if results %}
<table><thead><tr><th>房号</th><th>房型</th><th>价格(元)</th><th>楼层</th><th>状态</th></tr></thead>
<tbody>{% for r in results %}
<tr><td>{{ r["房号"] }}</td><td>{{ r["房型"] }}</td><td>{{ r["价格(元)"] }}</td>
<td>{{ r["楼层"] }}楼</td><td><span class="badge 空闲">空闲</span></td></tr>
{% endfor %}</tbody></table>
{% else %}<p class="muted">没有符合条件的空闲客房，请放宽筛选条件。</p>{% endif %}
</div>
{% endif %}
""", cond=cond, room_types=room_types, floors=floors, results=results)
    return base("空房推荐", body)


@app.route("/checkin", methods=["GET", "POST"])
def checkin():
    if request.method == "POST":
        room_no = request.form.get("room_no", "").strip()
        name = request.form.get("name", "").strip()
        phone = request.form.get("phone", "").strip()
        days_raw = request.form.get("days", "").strip()
        member = request.form.get("member", "普通")

        if not room_no or not name or not phone or not days_raw:
            flash("请完整填写房号、姓名、联系电话和入住天数。", "err")
            return redirect(url_for("checkin"))
        try:
            days = int(days_raw)
            if days <= 0:
                raise ValueError
        except ValueError:
            flash("入住天数必须为正整数。", "err")
            return redirect(url_for("checkin"))

        ok, msg = check_in(room_no, name, phone, days, member)
        flash(msg, "ok" if ok else "err")
        return redirect(url_for("checkin"))

    body = render_flashes() + render_template_string("""
<h1>入住登记办理</h1>
<p class="sub">录入客户信息，系统自动校验房态并按会员等级计算折扣房费</p>
<div class="panel">
<form method="post" class="grid">
  <div><label>房号</label><input name="room_no" placeholder="如 101"></div>
  <div><label>姓名</label><input name="name" placeholder="客户姓名"></div>
  <div><label>联系电话</label><input name="phone" placeholder="手机号"></div>
  <div><label>入住天数</label><input type="number" name="days" value="1" min="1"></div>
  <div><label>会员等级</label>
    <select name="member">{% for m, d in discounts.items() %}
      <option value="{{ m }}">{{ m }}（{{ '{:.0f}'.format(d*100) }}% 折扣）</option>{% endfor %}
    </select></div>
  <div><label>&nbsp;</label><button class="btn" type="submit">办理入住</button></div>
</form>
</div>
""", discounts=MEMBER_DISCOUNT)
    return base("入住登记", body)


@app.route("/checkout", methods=["GET", "POST"])
def checkout():
    if request.method == "POST":
        room_no = request.form.get("room_no", "").strip()
        if not room_no:
            flash("请输入退房房号。", "err")
            return redirect(url_for("checkout"))
        ok, msg, _ = check_out(room_no)
        flash(msg, "ok" if ok else "err")
        return redirect(url_for("checkout"))

    body = render_flashes() + render_template_string("""
<h1>退房办理</h1>
<p class="sub">输入退房房号，系统自动校验、结算，并将房态转为「待清洁」</p>
<div class="panel">
<form method="post" class="grid">
  <div><label>退房房号</label><input name="room_no" placeholder="如 202"></div>
  <div><label>&nbsp;</label><button class="btn" type="submit">办理退房</button></div>
</form>
</div>
<div class="panel">
<h2>当前在住客户</h2>
{% if checkins %}
<table><thead><tr><th>房号</th><th>姓名</th><th>联系电话</th><th>入住天数</th>
<th>会员等级</th><th>预估房费(元)</th></tr></thead>
<tbody>{% for c in checkins %}
<tr><td>{{ c["房号"] }}</td><td>{{ c["姓名"] }}</td><td>{{ c["联系电话"] }}</td>
<td>{{ c["入住天数"] }}</td><td>{{ c["会员等级"] }}</td><td>{{ c["预估房费(元)"] }}</td></tr>
{% endfor %}</tbody></table>
{% else %}<p class="muted">暂无在住客户。</p>{% endif %}
</div>
""", checkins=CHECKINS)
    return base("退房办理", body)


@app.route("/customers")
def customers():
    body = render_flashes() + render_template_string("""
<h1>入住客户管理</h1>
<p class="sub">集中管理所有在住客户信息，方便前台快速查询与核对</p>
<div class="panel">
{% if checkins %}
<table><thead><tr><th>房号</th><th>姓名</th><th>联系电话</th><th>入住天数</th>
<th>会员等级</th><th>预估房费(元)</th></tr></thead>
<tbody>{% for c in checkins %}
<tr><td>{{ c["房号"] }}</td><td>{{ c["姓名"] }}</td><td>{{ c["联系电话"] }}</td>
<td>{{ c["入住天数"] }}</td><td>{{ c["会员等级"] }}</td><td>{{ c["预估房费(元)"] }}</td></tr>
{% endfor %}</tbody></table>
{% else %}<p class="muted">暂无在住客户。</p>{% endif %}
</div>
""", checkins=CHECKINS)
    return base("客户管理", body)


@app.route("/analytics")
def analytics():
    occ = occupancy_analysis()
    dist = member_distribution()
    body = render_flashes() + render_template_string("""
<h1>运营数据分析</h1>
<p class="sub">酒店运营核心 KPI 与客户结构分析</p>
<div class="cards">
  <div class="card"><div class="k">总客房数</div><div class="v">{{ occ.total }}</div></div>
  <div class="card"><div class="k">入住房间数</div><div class="v">{{ occ.occupied }}</div></div>
  <div class="card"><div class="k">入住率</div><div class="v big">{{ occ.occupancy_rate }}%</div></div>
  <div class="card"><div class="k">可售房均价(元)</div><div class="v">{{ occ.avg_price }}</div></div>
</div>
<div class="panel">
<h2>会员等级分布</h2>
{% if dist %}
<table><thead><tr><th>会员等级</th><th>在住人数</th><th>占比</th></tr></thead>
<tbody>{% for m, n in dist.items() %}
<tr><td>{{ m }}</td><td>{{ n }}</td><td>{{ '%.1f'|format(n / dist.values()|sum * 100) }}%</td></tr>
{% endfor %}</tbody></table>
{% else %}<p class="muted">暂无在住客户，无法统计会员分布。</p>{% endif %}
</div>
<form method="post" action="/reset" class="mt">
  <button class="btn ghost" type="submit" onclick="return confirm('确定要重置所有数据吗？');">重置所有数据</button>
</form>
""", occ=occ, dist=dist)
    return base("数据分析", body)


@app.route("/reset", methods=["POST"])
def reset():
    reset_data()
    flash("已重置所有数据，恢复初始房态。", "ok")
    return redirect(url_for("index"))


# ------------------------------------------------------------------
# 六、启动入口
# ------------------------------------------------------------------
if __name__ == "__main__":
    load_data()
    print("=" * 50)
    print("酒店客房管理系统（网页版）已启动")
    print("请在浏览器打开： http://127.0.0.1:5000")
    print("=" * 50)
    # host=0.0.0.0 允许局域网/其他设备访问；debug=True 便于教学调试
    app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 5000)), debug=True)
