feat: prepare ARR for controlled public deployment

This commit is contained in:
Wyndham ARR
2026-07-29 16:38:05 +08:00
commit a701de9f0e
271 changed files with 48472 additions and 0 deletions

328
arr_web/static/index.html Normal file
View File

@@ -0,0 +1,328 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#f5f7fb" />
<title>ARR Report</title>
<link rel="stylesheet" href="/assets/styles.css" />
<script src="/assets/app.js" defer></script>
</head>
<body>
<a class="skip-link" href="#main-content">跳到主要内容</a>
<header class="masthead">
<div class="shell masthead-inner">
<a class="brand" href="#daily" aria-label="ARR Report 首页">
<span class="brand-mark" aria-hidden="true"><i></i><i></i><i></i></span>
<span><b>ARR</b><small>REPORT</small></span>
</a>
<div class="header-meta">
<span class="system-status" id="system-status"><i></i><span>正在连接数据服务</span></span>
<a class="h5-link" href="/h5">手机看板</a>
</div>
</div>
</header>
<nav class="tab-bar" aria-label="主要模块">
<div class="shell tabs" role="tablist">
<button class="tab is-active" type="button" role="tab" aria-selected="true" aria-controls="panel-daily" data-tab="daily">日报处理</button>
<button class="tab" type="button" role="tab" aria-selected="false" aria-controls="panel-monthly" data-tab="monthly">标准月报</button>
<button class="tab" type="button" role="tab" aria-selected="false" aria-controls="panel-bi" data-tab="bi">渠道BI</button>
<button class="tab" type="button" role="tab" aria-selected="false" aria-controls="panel-usage" data-tab="usage">公司渠道明细</button>
</div>
</nav>
<main class="shell page" id="main-content">
<section class="tabpanel is-active" id="panel-daily" role="tabpanel" data-panel="daily">
<div class="section-heading">
<div>
<p class="eyebrow">DAILY ARRIVAL</p>
<h1>日报处理</h1>
<p>上传 Opera ARR.XML处理结果验收通过后写入业务数据库。</p>
</div>
</div>
<div class="daily-layout">
<section class="panel upload-panel" aria-labelledby="upload-title">
<div class="panel-heading">
<div>
<span class="step-label">01 / UPLOAD</span>
<h2 id="upload-title">上传 ARR.XML</h2>
</div>
<span class="retention-note">本月留痕</span>
</div>
<label class="dropzone" id="dropzone" for="xml-file">
<input id="xml-file" type="file" accept=".xml,text/xml,application/xml" />
<span class="upload-glyph" aria-hidden="true">
<svg viewBox="0 0 24 24" focusable="false"><path d="M12 16V4m0 0L7.5 8.5M12 4l4.5 4.5M5 14v4a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-4"/></svg>
</span>
<strong>拖放 XML 文件到这里</strong>
<span>或点击选择文件,单个文件最大 25 MB</span>
<em id="selected-file">尚未选择文件</em>
</label>
<button class="primary-button" id="upload-button" type="button" disabled>开始处理</button>
<p class="service-hint" id="upload-hint" role="status"></p>
</section>
<section class="panel process-panel" aria-labelledby="process-title">
<div class="panel-heading">
<div>
<span class="step-label">02 / STATUS</span>
<h2 id="process-title">处理状态</h2>
</div>
</div>
<div class="process-state" id="process-state">
<div class="process-orbit" aria-hidden="true"><i></i></div>
<div>
<strong id="process-copy">等待上传 ARR.XML</strong>
<p id="process-detail">完成后将自动刷新日报记录。</p>
</div>
</div>
<ol class="pipeline" aria-label="处理流程">
<li><i>1</i><span>安全上传<small>私有对象存储</small></span></li>
<li><i>2</i><span>远端处理<small>确定性日报规则</small></span></li>
<li><i>3</i><span>结果验收<small>文件与数据复核</small></span></li>
<li><i>4</i><span>数据入库<small>原子提交</small></span></li>
</ol>
</section>
</div>
<section class="metric-grid daily-metrics" aria-label="最近一次处理结果">
<article class="metric-card">
<span>ARRIVAL DATE</span>
<strong id="metric-arrival"></strong>
<small>最近成功处理日期</small>
</article>
<article class="metric-card">
<span>处理耗时</span>
<strong id="metric-duration"></strong>
<small>从提交至完成</small>
</article>
<article class="metric-card accent-card">
<span>NO. OF ROOM</span>
<strong id="metric-rooms"></strong>
<small>保留记录的售出房数</small>
</article>
</section>
<section class="panel table-panel" aria-labelledby="daily-history-title">
<div class="panel-heading table-heading">
<div>
<span class="step-label">THIS MONTH</span>
<h2 id="daily-history-title">日报处理记录</h2>
</div>
<button class="text-button" id="refresh-jobs" type="button">刷新</button>
</div>
<div class="table-scroll">
<table>
<thead><tr><th>文件</th><th>状态</th><th>ARRIVAL DATE</th><th>NO. OF ROOM</th><th>处理耗时</th><th>提交时间</th><th>日报</th></tr></thead>
<tbody id="jobs-body"><tr><td class="empty-cell" colspan="7">正在读取本月记录…</td></tr></tbody>
</table>
</div>
</section>
</section>
<section class="tabpanel" id="panel-monthly" role="tabpanel" data-panel="monthly" hidden>
<div class="section-heading split-heading">
<div>
<p class="eyebrow">DATABASE REPORT</p>
<h1>标准月报</h1>
<p>按数据库中已验收的日报事实生成月报,版本与文件月内持续留痕。</p>
</div>
<div class="report-controls" aria-label="月报生成参数">
<label><span>月份</span><input id="monthly-month" type="month" /></label>
<label><span>更新至</span><input id="monthly-as-of" type="date" /></label>
<button class="primary-button compact" id="generate-monthly" type="button">生成标准月报</button>
</div>
</div>
<section class="panel table-panel" aria-labelledby="monthly-history-title">
<div class="panel-heading table-heading">
<div>
<span class="step-label">VERSION HISTORY</span>
<h2 id="monthly-history-title">标准月报版本记录</h2>
</div>
<button class="text-button" id="refresh-monthly" type="button">刷新</button>
</div>
<div class="table-scroll">
<table>
<thead><tr><th>版本</th><th>更新至</th><th>状态</th><th>数据行</th><th>公司数</th><th>生成时间</th><th>月报</th></tr></thead>
<tbody id="monthly-body"><tr><td class="empty-cell" colspan="7">正在读取月报记录…</td></tr></tbody>
</table>
</div>
</section>
</section>
<section class="tabpanel" id="panel-bi" role="tabpanel" data-panel="bi" hidden>
<div class="section-heading split-heading">
<div>
<p class="eyebrow">CHANNEL PERFORMANCE</p>
<h1>渠道BI</h1>
<p id="bi-subtitle">基于已发布月报快照。</p>
</div>
<label class="month-picker"><span>查看月份</span><select id="bi-month" aria-label="查看月份"></select></label>
</div>
<section class="metric-grid bi-metrics" aria-label="本月核心指标">
<article class="metric-card"><span>售出房数</span><strong id="bi-rooms"></strong><small>NO. OF ROOM 合计</small></article>
<article class="metric-card accent-card"><span>销售金额</span><strong id="bi-revenue"></strong><small>TOTAL PRICE 合计</small></article>
<article class="metric-card"><span>间夜</span><strong id="bi-nights"></strong><small>房数 × 入住晚数</small></article>
<article class="metric-card"><span>公司数</span><strong id="bi-channels"></strong><small>月报子表数量</small></article>
</section>
<section class="panel chart-panel" aria-labelledby="company-sales-title">
<div class="panel-heading">
<div>
<span class="step-label">TOTAL PRICE</span>
<h2 id="company-sales-title">各公司本月销售情况</h2>
</div>
</div>
<div class="company-chart-grid">
<div class="ranking-chart" id="company-ranking" aria-label="公司销售金额排名"></div>
<div class="donut-wrap">
<div class="donut" id="company-donut" role="img" aria-label="公司销售金额占比">
<div><strong id="donut-total"></strong><span>销售金额</span></div>
</div>
<div class="donut-legend" id="donut-legend"></div>
</div>
</div>
</section>
<section class="panel table-panel matrix-panel" aria-labelledby="matrix-title">
<div class="panel-heading table-heading">
<div>
<span class="step-label">ROOMS SOLD</span>
<h2 id="matrix-title">渠道 × 房型售出房数</h2>
</div>
</div>
<div class="table-scroll matrix-scroll" id="room-matrix"><p class="empty-state">正在读取看板数据…</p></div>
</section>
</section>
<section class="tabpanel usage-panel" id="panel-usage" role="tabpanel" data-panel="usage" hidden aria-label="公司渠道明细">
<div class="section-heading company-page-heading">
<div>
<p class="eyebrow">COMPANY DETAIL REPORTS</p>
<h1>公司渠道明细</h1>
<p>基于 finance 已校验数据,按 C/O离店日所属期间生成五家公司 Excel。</p>
</div>
<button class="text-button company-refresh" id="refresh-company-reports" type="button">刷新任务</button>
</div>
<div class="company-service-banner" id="company-report-unavailable" role="status" hidden>
<strong>公司渠道明细服务暂未就绪</strong>
<span>请检查本机数据库和 Excel 生成服务后刷新。</span>
</div>
<section class="panel company-report-setup" aria-labelledby="company-report-setup-title">
<div class="panel-heading">
<div>
<span class="step-label">FINANCE DATA</span>
<h2 id="company-report-setup-title">选择月份和本月生成期间</h2>
<p>点击任一期间后,一次固定生成 LianTai、QBD、DY-AI-Easy-KB、FengRun、HanaTour 五份工作簿。</p>
</div>
</div>
<div class="company-generator-grid">
<label class="company-month-field" for="company-report-month">
<span>报表月份</span>
<input id="company-report-month" type="month" min="2020-01" max="2099-12" autocomplete="off" />
<small>支持已开放期间重跑和历史月份补录。</small>
</label>
<div class="company-timezone" aria-label="业务时区:泰国曼谷 UTC+7">
<span>页面与期间时区</span>
<div class="company-timezone-value">
<i aria-hidden="true">BKK</i>
<span><strong>泰国曼谷</strong><small>UTC+7 · Asia/Bangkok</small></span>
</div>
</div>
<div class="company-scope" aria-label="固定生成公司">
<span>固定生成公司</span>
<div class="company-chip-list">
<span>LianTai</span><span>QBD</span><span>DY-AI-Easy-KB</span><span>FengRun</span><span>HanaTour</span>
</div>
</div>
</div>
<fieldset class="company-period-fieldset">
<legend>本月生成期间(一次生成五家公司)</legend>
<div class="company-period-actions">
<button class="company-period-button" type="button" data-company-period="01-10" aria-describedby="company-period-availability" disabled>
<span class="company-period-topline"><span class="company-period-index">第一期</span><span class="company-period-state" data-company-period-state>核对中</span></span>
<strong class="company-period-range" data-company-period-range>0110</strong>
<small class="company-period-detail"><span>C/O0110</span><span data-company-period-release>当月 11 日 00:00 开放</span></small>
<span class="company-period-cta"><span>生成截至 10 日</span><b aria-hidden="true"></b></span>
</button>
<button class="company-period-button" type="button" data-company-period="11-20" aria-describedby="company-period-availability" disabled>
<span class="company-period-topline"><span class="company-period-index">第二期</span><span class="company-period-state" data-company-period-state>核对中</span></span>
<strong class="company-period-range" data-company-period-range>1120</strong>
<small class="company-period-detail"><span>C/O1120</span><span data-company-period-release>当月 21 日 00:00 开放</span></small>
<span class="company-period-cta"><span>生成截至 20 日</span><b aria-hidden="true"></b></span>
</button>
<button class="company-period-button" type="button" data-company-period="21-month-end" aria-describedby="company-period-availability" disabled>
<span class="company-period-topline"><span class="company-period-index">第三期</span><span class="company-period-state" data-company-period-state>核对中</span></span>
<strong class="company-period-range" data-company-period-range>21月末</strong>
<small class="company-period-detail"><span data-company-period-co>C/O21月末</span><span data-company-period-release>次月 1 日 00:00 开放</span></small>
<span class="company-period-cta"><span>生成截至月末</span><b aria-hidden="true"></b></span>
</button>
</div>
<p class="company-period-availability" id="company-period-availability" aria-live="polite">正在核对期间开放日期…</p>
</fieldset>
<p class="company-report-error" id="company-report-error" role="alert" hidden></p>
<p class="company-generation-note">同月重跑会生成新的正式版本并保留历史归档;浏览器只提交月份和期间,不提交公司名单、数据库参数或文件路径。</p>
</section>
<section class="panel company-job-panel" id="company-report-job-panel" aria-labelledby="company-report-job-title" hidden>
<div class="company-job-header">
<div>
<span class="step-label" id="company-report-job-kicker">TASK STATUS</span>
<h2 id="company-report-job-title">正在准备公司渠道明细任务</h2>
<p id="company-report-job-message" aria-live="polite">正在读取任务状态。</p>
</div>
<div class="company-job-summary">
<span class="status-chip running" id="company-report-job-state">已排队</span>
<strong id="company-report-success-count">0 / 5</strong>
<small>公司已生成</small>
</div>
</div>
<div class="company-progress-wrap">
<div><span id="company-report-progress-label">等待生成</span><strong id="company-report-progress-percent">0%</strong></div>
<div class="company-progress-track" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" id="company-report-progress-track"><span id="company-report-progress-bar"></span></div>
</div>
<dl class="company-job-meta">
<div><dt>报表月份</dt><dd id="company-report-job-month"></dd></div>
<div><dt>截止日期</dt><dd id="company-report-job-as-of"></dd></div>
<div><dt>任务耗时</dt><dd id="company-report-job-duration"></dd></div>
<div><dt>需复核</dt><dd id="company-report-warning-count">0 项</dd></div>
</dl>
<div class="table-scroll company-result-scroll">
<table class="company-result-table">
<caption class="sr-only">本次任务中五家公司的生成结果</caption>
<thead><tr><th>公司</th><th class="company-period-column">0110</th><th class="company-period-column">1120</th><th class="company-period-column" id="company-result-month-end-header">21月末</th><th>合计</th><th>状态</th><th>复核 / 异常</th><th>版本</th><th>Excel</th></tr></thead>
<tbody id="company-report-result-rows"></tbody>
</table>
</div>
</section>
<section class="panel table-panel company-history-panel" aria-labelledby="company-history-title">
<div class="panel-heading table-heading">
<div>
<span class="step-label">TASK HISTORY</span>
<h2 id="company-history-title">公司渠道明细生成记录</h2>
</div>
<span class="company-history-count" id="company-history-count">0 条记录</span>
</div>
<div class="table-scroll">
<table class="company-history-table">
<thead><tr><th>提交时间(曼谷)</th><th>报表月份</th><th>截止期间</th><th>状态</th><th>已生成</th><th>需复核</th><th>详情</th></tr></thead>
<tbody id="company-history-rows"><tr><td class="empty-cell" colspan="7">正在读取公司渠道明细任务…</td></tr></tbody>
</table>
</div>
</section>
</section>
</main>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<footer class="page-footer"><span>页面日期时间统一按泰国曼谷UTC+7显示。</span><span>公司渠道明细按 C/O离店日所属期间分页。</span></footer>
</body>
</html>