Show durable reservation acquisition progress in download tasks
This commit is contained in:
1 parent
698d91367c
commit
db42a5e087
16 files changed
+757
-23
No files matched your search
@@ -437,6 +437,55 @@
|
||||
scheduleARRDownloadPoll();
|
||||
}
|
||||
|
||||
function renderARRAcquisitionProgress(task = state.arrDownloadTask) {
|
||||
const panel = $("#arr-acquisition-progress");
|
||||
const raw = task?.acquisition_progress;
|
||||
const phases = ["queued", "searching", "fetching", "verifying", "completed", "failed", "interrupted"];
|
||||
const progress = raw && phases.includes(raw.phase) ? raw : null;
|
||||
const completedStatuses = ["processing", "needs_data_review", "needs_review", "succeeded"];
|
||||
const phase = progress?.phase || (completedStatuses.includes(task?.status) ? "completed"
|
||||
: task?.status === "downloading" ? "fetching" : ["queued", "failed", "interrupted"].includes(task?.status) ? task.status : "");
|
||||
panel.hidden = !phase || !task || task.report_date !== $("#arr-download-date").value;
|
||||
if (panel.hidden) return;
|
||||
const complete = phase === "completed";
|
||||
const failed = ["failed", "interrupted"].includes(phase);
|
||||
const completed = Number.isInteger(progress?.completed) && progress.completed >= 0 ? progress.completed : null;
|
||||
const total = completed !== null && Number.isInteger(progress?.total) && progress.total >= completed ? progress.total : null;
|
||||
// Only server-reported percentages with a known total are determinate.
|
||||
// All records fetched still means at most 99% until completeness is verified.
|
||||
const percent = total !== null && Number.isInteger(progress?.percent) && progress.percent >= 0 && progress.percent <= 100
|
||||
? Math.min(progress.percent, complete ? 100 : 99) : null;
|
||||
const statusKey = ["queued", "completed", "failed", "interrupted"].includes(phase) ? phase : "active";
|
||||
const status = I18N.t(`arr_acquisition.${statusKey}`);
|
||||
const counts = total !== null ? I18N.t("arr_acquisition.counts", { completed: formatInteger(completed), total: formatInteger(total) }) : "";
|
||||
let detail;
|
||||
if (phase === "queued") detail = I18N.t("arr_acquisition.waiting");
|
||||
else if (phase === "verifying") detail = total !== null
|
||||
? I18N.t("arr_acquisition.verifying_counts", { completed: formatInteger(completed), total: formatInteger(total) })
|
||||
: I18N.t("arr_acquisition.verifying");
|
||||
else if (complete) detail = counts || I18N.t("arr_acquisition.legacy_completed");
|
||||
else if (failed) detail = [counts, I18N.t(`arr_acquisition.${phase}_detail`)].filter(Boolean).join(" · ");
|
||||
else if (counts) detail = counts;
|
||||
else if (phase === "searching") detail = I18N.t("arr_acquisition.searching");
|
||||
else detail = completed !== null ? I18N.t("arr_acquisition.count_unknown", { completed: formatInteger(completed) })
|
||||
: I18N.t("arr_acquisition.fetching");
|
||||
panel.classList.toggle("is-completed", complete);
|
||||
panel.classList.toggle("is-error", failed);
|
||||
$("#arr-acquisition-label").textContent = I18N.t("arr_acquisition.label");
|
||||
$("#arr-acquisition-status").textContent = status;
|
||||
$("#arr-acquisition-detail").textContent = detail;
|
||||
$("#arr-acquisition-percent").hidden = percent === null;
|
||||
$("#arr-acquisition-percent").textContent = percent === null ? "" : `${percent}%`;
|
||||
const track = $("#arr-acquisition-track");
|
||||
const indeterminate = percent === null && !complete && !failed;
|
||||
track.hidden = percent === null && !indeterminate;
|
||||
track.classList.toggle("is-indeterminate", indeterminate);
|
||||
track.setAttribute("aria-valuetext", `${status} · ${detail}${percent === null ? "" : ` · ${percent}%`}`);
|
||||
if (percent === null) track.removeAttribute("aria-valuenow");
|
||||
else track.setAttribute("aria-valuenow", String(percent));
|
||||
$("#arr-acquisition-bar").style.width = percent === null ? "" : `${percent}%`;
|
||||
}
|
||||
|
||||
function renderARRDownload() {
|
||||
const task = state.arrDownloadTask;
|
||||
const pending = Boolean(state.arrDownloadIntent && !task);
|
||||
@@ -481,6 +530,7 @@
|
||||
$("#arr-download-review").hidden = task?.status !== "needs_review" || !task.job_id;
|
||||
$("#arr-download-data-review").hidden = !arrDownloadNeedsDataReview();
|
||||
$("#arr-download-data-review").disabled = locked;
|
||||
renderARRAcquisitionProgress(task);
|
||||
renderARRPendingReviews();
|
||||
}
|
||||
|
||||
|
||||
@@ -113,6 +113,22 @@
|
||||
"arr_download.date_resume": ["可先选择日期;请先确认或继续 {date} 的原任务。", "You can choose a date. First check or resume the original task for {date}.", "เลือกวันที่ได้ แต่โปรดตรวจสอบหรือดำเนินงานเดิมของวันที่ {date} ต่อก่อน"],
|
||||
"arr_download.help": ["选择一天,自动获取到店数据并生成报表。", "Choose one day to fetch arrivals and generate reports.", "เลือกหนึ่งวันเพื่อดาวน์โหลดและประมวลผลรายงานผู้เข้าพัก"],
|
||||
"arr_download.start": ["下载并处理", "Download & process", "ดาวน์โหลดและประมวลผล"],
|
||||
"arr_acquisition.label": ["取数状态", "Data retrieval", "สถานะการดึงข้อมูล"],
|
||||
"arr_acquisition.queued": ["等待取数", "Queued", "รอดึงข้อมูล"],
|
||||
"arr_acquisition.active": ["取数中", "Retrieving", "กำลังดึงข้อมูล"],
|
||||
"arr_acquisition.completed": ["已完成", "Completed", "เสร็จแล้ว"],
|
||||
"arr_acquisition.failed": ["取数失败", "Retrieval failed", "ดึงข้อมูลไม่สำเร็จ"],
|
||||
"arr_acquisition.interrupted": ["取数中断", "Retrieval interrupted", "การดึงข้อมูลขัดจังหวะ"],
|
||||
"arr_acquisition.waiting": ["正在等待取数…", "Waiting to retrieve data…", "กำลังรอดึงข้อมูล…"],
|
||||
"arr_acquisition.searching": ["正在确认预订总数…", "Determining the reservation total…", "กำลังตรวจสอบจำนวนการจองทั้งหมด…"],
|
||||
"arr_acquisition.fetching": ["正在获取预订数据…", "Retrieving reservation data…", "กำลังดึงข้อมูลการจอง…"],
|
||||
"arr_acquisition.counts": ["已获取 {completed} / {total} 笔", "Retrieved {completed} / {total} reservations", "ดึงข้อมูลแล้ว {completed} / {total} การจอง"],
|
||||
"arr_acquisition.count_unknown": ["已获取 {completed} 笔 · 总数尚未确定", "Retrieved {completed} reservations · total not yet known", "ดึงข้อมูลแล้ว {completed} การจอง · ยังไม่ทราบจำนวนทั้งหมด"],
|
||||
"arr_acquisition.verifying": ["正在校验完整性…", "Verifying completeness…", "กำลังตรวจสอบความครบถ้วน…"],
|
||||
"arr_acquisition.verifying_counts": ["已获取 {completed} / {total} 笔 · 正在校验完整性", "Retrieved {completed} / {total} reservations · verifying completeness", "ดึงข้อมูลแล้ว {completed} / {total} การจอง · กำลังตรวจสอบความครบถ้วน"],
|
||||
"arr_acquisition.legacy_completed": ["该任务未记录取数笔数。", "Retrieval counts were not recorded for this task.", "งานนี้ไม่ได้บันทึกจำนวนการจองที่ดึงข้อมูล"],
|
||||
"arr_acquisition.failed_detail": ["取数未完成,请查看任务提示。", "Data retrieval did not complete. Check the task message.", "การดึงข้อมูลยังไม่เสร็จ โปรดดูข้อความของงาน"],
|
||||
"arr_acquisition.interrupted_detail": ["取数已中断,请继续原任务。", "Data retrieval was interrupted. Resume the original task.", "การดึงข้อมูลขัดจังหวะ โปรดดำเนินงานเดิมต่อ"],
|
||||
"arr_download.connecting": ["正在连接下载服务…", "Connecting to download service…", "กำลังเชื่อมต่อบริการดาวน์โหลด…"],
|
||||
"arr_download.service_reconnecting": ["下载服务连接中断,正在重新连接…", "Download service disconnected. Reconnecting…", "การเชื่อมต่อบริการดาวน์โหลดขัดข้อง กำลังเชื่อมต่อใหม่…"],
|
||||
"arr_download.unavailable": ["自动下载服务暂未就绪", "Automatic download is not yet available", "บริการดาวน์โหลดอัตโนมัติยังไม่พร้อมใช้งาน"],
|
||||
|
||||
@@ -74,6 +74,16 @@
|
||||
<span class="arr-download-indicator" aria-hidden="true"></span>
|
||||
<span id="arr-download-status">正在连接下载服务…</span>
|
||||
</div>
|
||||
<div class="arr-acquisition-progress" id="arr-acquisition-progress" hidden>
|
||||
<div class="arr-acquisition-meta">
|
||||
<span><span id="arr-acquisition-label">取数状态</span><strong id="arr-acquisition-status" role="status" aria-live="polite"></strong></span>
|
||||
<strong id="arr-acquisition-percent" hidden></strong>
|
||||
</div>
|
||||
<div class="arr-acquisition-track" id="arr-acquisition-track" role="progressbar" aria-labelledby="arr-acquisition-label" aria-describedby="arr-acquisition-detail" aria-valuemin="0" aria-valuemax="100">
|
||||
<span id="arr-acquisition-bar"></span>
|
||||
</div>
|
||||
<p id="arr-acquisition-detail"></p>
|
||||
</div>
|
||||
<div class="arr-download-actions">
|
||||
<button class="arr-download-review" id="arr-download-data-review" type="button" hidden>完善报表字段</button>
|
||||
<button class="arr-download-review" id="arr-download-review" type="button" hidden>查看价格复核</button>
|
||||
|
||||
@@ -197,6 +197,25 @@ button { color: inherit; }
|
||||
.arr-download-feedback.is-success { color: #087a55; }
|
||||
.arr-download-feedback.is-review { color: var(--amber); }
|
||||
.arr-download-feedback.is-error { color: #b42318; }
|
||||
.arr-acquisition-progress { min-width: 0; margin: 0 0 12px; }
|
||||
.arr-acquisition-progress[hidden], .arr-acquisition-track[hidden] { display: none; }
|
||||
.arr-acquisition-meta { display: flex; align-items: baseline; justify-content: space-between; flex-wrap: wrap; gap: 4px 10px; color: var(--muted); font-size: 10px; line-height: 1.5; }
|
||||
.arr-acquisition-meta > span { display: flex; flex-wrap: wrap; gap: 7px; }
|
||||
#arr-acquisition-status { color: var(--blue-dark); font-weight: 650; }
|
||||
#arr-acquisition-percent { color: var(--blue-dark); font-variant-numeric: tabular-nums; }
|
||||
.arr-acquisition-track { height: 5px; margin-top: 6px; overflow: hidden; border-radius: 999px; background: #e8eef9; }
|
||||
.arr-acquisition-track > span { display: block; height: 100%; border-radius: inherit; background: var(--blue); transition: width .25s ease; }
|
||||
.arr-acquisition-track.is-indeterminate > span { width: 32%; animation: arr-acquisition-pulse 1.7s ease-in-out infinite; }
|
||||
.arr-acquisition-progress.is-completed #arr-acquisition-status { color: #087a55; }
|
||||
.arr-acquisition-progress.is-completed .arr-acquisition-track > span { background: #087a55; }
|
||||
.arr-acquisition-progress.is-error #arr-acquisition-status { color: #b42318; }
|
||||
.arr-acquisition-progress.is-error .arr-acquisition-track > span { background: #b42318; }
|
||||
#arr-acquisition-detail { margin: 6px 0 0; color: var(--muted); font-size: 10px; line-height: 1.5; overflow-wrap: anywhere; font-variant-numeric: tabular-nums; }
|
||||
@keyframes arr-acquisition-pulse { from { transform: translateX(-100%); } to { transform: translateX(350%); } }
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.arr-acquisition-track > span { transition: none; }
|
||||
.arr-acquisition-track.is-indeterminate > span { animation: none; }
|
||||
}
|
||||
.arr-download-actions { display: flex; align-items: center; justify-content: flex-end; flex-wrap: wrap; gap: 8px; }
|
||||
.arr-download-actions .primary-button { min-height: 34px; margin: 0; padding: 0 12px; border-radius: 8px; font-size: 11px; }
|
||||
.arr-download-review { padding: 4px 0; border: 0; color: var(--blue-dark); background: transparent; font-size: 11px; font-weight: 650; cursor: pointer; text-decoration: underline; text-underline-offset: 3px; }
|
||||
|
||||
Reference in new issue
Block a user