Combine report field and price checks into one review workspace
This commit is contained in:
1 parent
2888d6edbc
commit
698d91367c
8 files changed
+273
-87
No files matched your search
+45
-10
@@ -26,6 +26,7 @@
|
||||
arrDownloadUsername: "",
|
||||
arrDownloadContextId: "",
|
||||
arrDownloadPendingReviews: [],
|
||||
manualReviewMode: "",
|
||||
arrDataReview: null,
|
||||
arrDataReviewRequestId: "",
|
||||
arrDataReviewLoading: false,
|
||||
@@ -391,10 +392,12 @@
|
||||
$("#arr-download-date").value = task.report_date;
|
||||
await acceptARRDownloadTask(task, { sync: false });
|
||||
if (arrDownloadNeedsDataReview()) {
|
||||
state.manualReviewMode = "fields";
|
||||
state.dailyPriceReview = null;
|
||||
state.dailyPriceReviewJobId = "";
|
||||
renderARRDataReview();
|
||||
renderDailyPriceReview(null);
|
||||
$("#arr-data-review-panel").scrollIntoView({ behavior: "smooth", block: "start" });
|
||||
$("#manual-review-workspace").scrollIntoView({ behavior: "smooth", block: "start" });
|
||||
$("#arr-data-review-panel").focus({ preventScroll: true });
|
||||
} else if (task.job_id && ["needs_review", "succeeded", "failed"].includes(task.status)) {
|
||||
state.jobsMonth = task.report_date.slice(0, 7);
|
||||
@@ -577,7 +580,13 @@
|
||||
state.arrDownloadDisconnected = false;
|
||||
state.arrDownloadSynced = "";
|
||||
state.arrDownloadPendingReviews = [];
|
||||
state.manualReviewMode = "";
|
||||
state.dailyPriceReview = null;
|
||||
state.dailyPriceReviewJobId = "";
|
||||
state.dailyPriceReviewOffset = 0;
|
||||
state.dailyPriceReviewLoading = false;
|
||||
resetARRDataReview({ clearDrafts: true });
|
||||
renderDailyPriceReview(null);
|
||||
}
|
||||
const authoritativePendingReviews = Array.isArray(config.pending_reviews);
|
||||
const pendingReviews = authoritativePendingReviews ? config.pending_reviews : config.pending_data_reviews;
|
||||
@@ -731,11 +740,29 @@
|
||||
node.classList.toggle("is-error", isError);
|
||||
}
|
||||
|
||||
function renderManualReviewWorkspace(priceReview = state.dailyPriceReview) {
|
||||
const fieldsAvailable = Boolean(state.arrDataReviewRequestId && arrDownloadNeedsDataReview()
|
||||
&& state.arrDownloadTask.request_id === state.arrDataReviewRequestId);
|
||||
const pricesAvailable = Boolean(priceReview && ["open", "generation_failed", "processing"].includes(priceReview.case_status));
|
||||
const mode = state.manualReviewMode || (fieldsAvailable ? "fields" : "prices");
|
||||
const showFields = mode === "fields" && fieldsAvailable;
|
||||
const showPrices = mode === "prices" && pricesAvailable;
|
||||
$("#arr-data-review-panel").hidden = !showFields;
|
||||
$("#daily-price-review-panel").hidden = !showPrices;
|
||||
$("#manual-review-workspace").hidden = !showFields && !showPrices;
|
||||
$("#manual-review-title").textContent = I18N.t("manual_review.title");
|
||||
const type = I18N.t(showFields ? "manual_review.fields" : "manual_review.prices");
|
||||
const priceTask = state.arrDownloadTask?.job_id === state.dailyPriceReviewJobId ? state.arrDownloadTask : null;
|
||||
const date = showFields ? state.arrDataReview?.report_date || state.arrDownloadTask?.report_date
|
||||
: priceReview?.business_date || priceReview?.report_date || priceTask?.report_date
|
||||
|| state.jobs.find((job) => job.job_id === state.dailyPriceReviewJobId)?.arrival_date;
|
||||
$("#manual-review-context").textContent = date ? I18N.t("manual_review.context", { date, type }) : type;
|
||||
}
|
||||
|
||||
function renderARRDataReview() {
|
||||
const panel = $("#arr-data-review-panel");
|
||||
const review = state.arrDataReview;
|
||||
panel.hidden = !state.arrDataReviewRequestId || !arrDownloadNeedsDataReview()
|
||||
|| state.arrDownloadTask.request_id !== state.arrDataReviewRequestId;
|
||||
renderManualReviewWorkspace();
|
||||
if (panel.hidden) return;
|
||||
const busy = state.arrDataReviewLoading || state.arrDataReviewMutating;
|
||||
const editable = review?.status === "editing" && !busy && !state.arrDataReviewDisconnected && !state.arrDataReviewFinalizing;
|
||||
@@ -786,12 +813,19 @@
|
||||
|
||||
async function loadARRDataReview(requestId = state.arrDownloadTask?.request_id, { scroll = false, showErrors = true } = {}) {
|
||||
if (!requestId || state.arrDataReviewLoading || !arrDownloadNeedsDataReview()) return null;
|
||||
if (state.manualReviewMode === "prices" && dailyPriceReviewHasUnsavedChanges()) {
|
||||
const message = I18N.t("daily_review.save_before_switch");
|
||||
setDailyPriceReviewMessage(message, true);
|
||||
showToast(message, true);
|
||||
return null;
|
||||
}
|
||||
if (state.arrDataReviewRequestId !== requestId) {
|
||||
resetARRDataReview();
|
||||
state.arrDataReviewRequestId = requestId;
|
||||
state.arrDataReviewDrafts = { ...state.arrDataReviewDraftsByRequest[requestId] };
|
||||
}
|
||||
const contextId = state.arrDownloadContextId;
|
||||
state.manualReviewMode = "fields";
|
||||
state.arrDataReviewLoading = true;
|
||||
renderARRDataReview();
|
||||
try {
|
||||
@@ -808,7 +842,7 @@
|
||||
if (item.confirmed && state.arrDataReviewDrafts[item.item_id] === arrDataReviewInputValue(item)) delete state.arrDataReviewDrafts[item.item_id];
|
||||
});
|
||||
if (scroll) {
|
||||
$("#arr-data-review-panel").scrollIntoView({ behavior: "smooth", block: "start" });
|
||||
$("#manual-review-workspace").scrollIntoView({ behavior: "smooth", block: "start" });
|
||||
$("#arr-data-review-panel").focus({ preventScroll: true });
|
||||
}
|
||||
return review;
|
||||
@@ -1315,13 +1349,12 @@
|
||||
const panel = $("#daily-price-review-panel");
|
||||
const body = $("#daily-price-review-body");
|
||||
const empty = $("#daily-price-review-empty");
|
||||
renderManualReviewWorkspace(review);
|
||||
if (!review) {
|
||||
panel.hidden = true;
|
||||
body.innerHTML = "";
|
||||
empty.hidden = true;
|
||||
return;
|
||||
}
|
||||
panel.hidden = false;
|
||||
const busy = state.dailyPriceReviewLoading || state.dailyPriceReviewMutating;
|
||||
const editable = dailyPriceReviewEditable(review);
|
||||
const retryable = review.case_status === "generation_failed";
|
||||
@@ -1393,31 +1426,33 @@
|
||||
|
||||
async function loadDailyPriceReview(jobId = state.dailyPriceReviewJobId, { reset = false, scroll = false, showErrors = true } = {}) {
|
||||
if (!jobId || state.dailyPriceReviewLoading) return;
|
||||
state.manualReviewMode = "prices";
|
||||
if (reset || jobId !== state.dailyPriceReviewJobId) {
|
||||
state.dailyPriceReviewJobId = jobId;
|
||||
state.dailyPriceReviewOffset = 0;
|
||||
state.dailyPriceReview = null;
|
||||
}
|
||||
const expectedJobId = state.dailyPriceReviewJobId;
|
||||
const contextId = state.arrDownloadContextId;
|
||||
state.dailyPriceReviewLoading = true;
|
||||
renderDailyPriceReview(state.dailyPriceReview);
|
||||
try {
|
||||
const review = await api(`/api/jobs/${encodeURIComponent(expectedJobId)}/review?limit=${DAILY_PRICE_REVIEW_PAGE_SIZE}&offset=${state.dailyPriceReviewOffset}`);
|
||||
if (state.dailyPriceReviewJobId !== expectedJobId) return;
|
||||
if (state.dailyPriceReviewJobId !== expectedJobId || state.arrDownloadContextId !== contextId) return;
|
||||
state.dailyPriceReview = review;
|
||||
renderDailyPriceReview(review);
|
||||
if (scroll) {
|
||||
const panel = $("#daily-price-review-panel");
|
||||
panel.scrollIntoView({ behavior: "smooth", block: "start" });
|
||||
$("#manual-review-workspace").scrollIntoView({ behavior: "smooth", block: "start" });
|
||||
panel.focus({ preventScroll: true });
|
||||
}
|
||||
} catch (error) {
|
||||
if (state.dailyPriceReviewJobId === expectedJobId && showErrors) {
|
||||
if (state.dailyPriceReviewJobId === expectedJobId && state.arrDownloadContextId === contextId && showErrors) {
|
||||
setDailyPriceReviewMessage(error.message, true);
|
||||
showToast(error.message, true);
|
||||
}
|
||||
} finally {
|
||||
if (state.dailyPriceReviewJobId === expectedJobId) {
|
||||
if (state.dailyPriceReviewJobId === expectedJobId && state.arrDownloadContextId === contextId) {
|
||||
state.dailyPriceReviewLoading = false;
|
||||
renderDailyPriceReview(state.dailyPriceReview);
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
"arr_download.needs_data_review": ["等待人工完善报表字段", "Awaiting source field review", "รอตรวจสอบข้อมูลรายงานด้วยตนเอง"],
|
||||
"arr_download.complete_data": ["完善报表字段", "Complete report fields", "กรอกข้อมูลรายงานให้ครบ"],
|
||||
"arr_download.date_independent": ["可选其他日期下载,当前待处理内容会保留。", "Choose another date to download; this review will be kept.", "เลือกวันอื่นเพื่อดาวน์โหลดได้ ข้อมูลที่รอตรวจสอบจะยังคงอยู่"],
|
||||
"arr_download.pending_dates": ["待处理日期", "Dates awaiting review", "วันที่รอดำเนินการ"],
|
||||
"arr_download.pending_dates": ["需处理日期", "Dates requiring attention", "วันที่ต้องดำเนินการ"],
|
||||
"arr_download.pending_date": ["待补字段", "Complete fields", "รอกรอกข้อมูล"],
|
||||
"arr_download.pending_price": ["待复核价格", "Review prices", "รอตรวจสอบราคา"],
|
||||
"arr_download.source_failed": ["到店数据获取未完成,请继续原任务重试。", "Arrival data could not be fetched. Resume the original task to retry.", "ยังดึงข้อมูลผู้เข้าพักไม่สำเร็จ โปรดดำเนินงานเดิมต่อเพื่อลองอีกครั้ง"],
|
||||
@@ -147,7 +147,11 @@
|
||||
"arr_download.date_conflict": ["原任务日期不能修改", "The original task date cannot be changed", "ไม่สามารถเปลี่ยนวันที่ของงานเดิม"],
|
||||
"arr_download.retry_unavailable": ["该任务不能继续重试,请查看任务日志", "This task cannot be retried. Check the task log.", "ไม่สามารถลองงานนี้อีกครั้ง โปรดดูบันทึกงาน"],
|
||||
"arr_download.other_active": ["该日期已有进行中的下载任务", "A download for this date is already in progress", "มีงานดาวน์โหลดสำหรับวันที่นี้กำลังดำเนินการอยู่"],
|
||||
"data_review.title": ["人工完善报表字段", "Complete report fields", "ตรวจสอบและกรอกข้อมูลรายงาน"],
|
||||
"manual_review.title": ["人工核对", "Manual review", "ตรวจสอบด้วยตนเอง"],
|
||||
"manual_review.fields": ["完善报表字段", "Complete report fields", "กรอกข้อมูลรายงานให้ครบ"],
|
||||
"manual_review.prices": ["价格复核", "Review prices", "ตรวจสอบราคา"],
|
||||
"manual_review.context": ["{date} · {type}", "{date} · {type}", "{date} · {type}"],
|
||||
"data_review.title": ["完善报表字段", "Complete report fields", "ตรวจสอบและกรอกข้อมูลรายงาน"],
|
||||
"data_review.copy": ["请按各项提示核实来源与原处理规则。可空字段不必补成有值;核实无此信息后,可明确确认留空。全部确认后可生成日报。", "Check each field's source and original processing requirement. Optional fields need no value when none exists; explicitly confirm this after verification. Generate the daily report after all items are confirmed.", "ตรวจสอบแหล่งข้อมูลและข้อกำหนดเดิมของแต่ละช่อง ช่องที่เว้นว่างได้ไม่จำเป็นต้องกรอกค่า หากตรวจสอบแล้วว่าไม่มีข้อมูล ให้ยืนยันการเว้นว่าง สร้างรายงานรายวันได้เมื่อยืนยันครบทุกช่อง"],
|
||||
"data_review.progress": ["{date} · 已确认 {completed} / {total} 项", "{date} · {completed} of {total} confirmed", "{date} · ยืนยันแล้ว {completed} / {total} รายการ"],
|
||||
"data_review.reservation": ["预订信息", "Reservation", "ข้อมูลการจอง"],
|
||||
@@ -250,7 +254,7 @@
|
||||
"daily_review.open": ["打开人工价格复核,已填写 {completed} / {total}", "Open manual price review, {completed} of {total} completed", "เปิดการตรวจสอบราคาด้วยตนเอง กรอกแล้ว {completed} / {total}"],
|
||||
"daily_review.progress_short": ["复核 {completed} / {total}", "Review {completed} / {total}", "ตรวจสอบ {completed} / {total}"],
|
||||
"daily_review.step": ["价格复核 / 待处理", "PRICE REVIEW / REQUIRED", "ตรวจสอบราคา / ต้องดำเนินการ"],
|
||||
"daily_review.title": ["人工价格复核", "Manual price review", "ตรวจสอบราคาด้วยตนเอง"],
|
||||
"daily_review.title": ["价格复核", "Review prices", "ตรวจสอบราคา"],
|
||||
"daily_review.default_instruction": ["请填写每晚处理价,可填 0。每项填写后点击“暂存”,全部暂存后生成日报。相同价格项只需填写一次。", "Enter the nightly price; 0 is allowed. Save each item, then generate the daily report when all items are saved. Enter each identical price key only once.", "กรอกราคาต่อคืน สามารถกรอก 0 ได้ กดบันทึกแต่ละรายการ แล้วสร้างรายงานรายวันเมื่อบันทึกครบทุกรายการ คีย์ราคาเดียวกันกรอกเพียงครั้งเดียว"],
|
||||
"daily_review.processing_instruction": ["正在使用已冻结的价格清单重放原始 XML;此时无法修改。", "The original XML is being replayed with the frozen price list. Prices cannot be changed now.", "กำลังประมวลผล XML ต้นทางซ้ำด้วยรายการราคาที่ตรึงไว้ ขณะนี้ไม่สามารถแก้ไขราคาได้"],
|
||||
"daily_review.progress_aria": ["人工价格复核进度", "Manual price review progress", "ความคืบหน้าการตรวจสอบราคาด้วยตนเอง"],
|
||||
@@ -268,7 +272,7 @@
|
||||
"daily_review.rooms_nights": ["房数 / 房晚", "Rooms / room nights", "ห้อง / คืนห้องพัก"],
|
||||
"daily_review.manual_price": ["人工价格", "Manual price", "ราคาที่กำหนดด้วยตนเอง"],
|
||||
"daily_review.price_placeholder": ["请输入价格(可填 0)", "Enter price (0 allowed)", "กรอกราคา (กรอก 0 ได้)"],
|
||||
"daily_review.save_before_switch": ["当前价格尚未暂存,请先暂存,再切换待处理日期。", "Save the current price edits before switching to another review.", "โปรดบันทึกราคาที่แก้ไขก่อนเปลี่ยนไปตรวจสอบวันที่อื่น"],
|
||||
"daily_review.save_before_switch": ["当前价格尚未暂存,请先暂存,再切换需处理日期。", "Save the current price edits before switching to another review.", "โปรดบันทึกราคาที่แก้ไขก่อนเปลี่ยนไปตรวจสอบวันที่อื่น"],
|
||||
"daily_review.no_candidates": ["暂无同公司 / Rate Code 固定价", "No fixed price for the same company / Rate Code", "ไม่มีราคาคงที่สำหรับบริษัท / Rate Code เดียวกัน"],
|
||||
"daily_review.price_key": ["价格键", "price key", "คีย์ราคา"],
|
||||
"daily_review.manual_price_label": ["{company} {rateCode} 的人工价格", "Manual price for {company} {rateCode}", "ราคาที่กำหนดด้วยตนเองสำหรับ {company} {rateCode}"],
|
||||
|
||||
+65
-59
@@ -74,10 +74,6 @@
|
||||
<span class="arr-download-indicator" aria-hidden="true"></span>
|
||||
<span id="arr-download-status">正在连接下载服务…</span>
|
||||
</div>
|
||||
<div class="arr-download-pending" id="arr-download-pending" hidden>
|
||||
<span id="arr-download-pending-title">待完善日期</span>
|
||||
<div id="arr-download-pending-list"></div>
|
||||
</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>
|
||||
@@ -132,66 +128,76 @@
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section class="panel arr-data-review-panel" id="arr-data-review-panel" aria-labelledby="arr-data-review-title" tabindex="-1" hidden>
|
||||
<header class="arr-data-review-header">
|
||||
<div>
|
||||
<h2 id="arr-data-review-title">人工完善报表字段</h2>
|
||||
<p id="arr-data-review-copy">请核实并逐项保存缺失或有冲突的字段。允许为空的字段也须明确确认,全部完成后才能生成日报。</p>
|
||||
</div>
|
||||
<p id="arr-data-review-progress" role="status" aria-live="polite"></p>
|
||||
</header>
|
||||
<div class="arr-data-review-toolbar">
|
||||
<p id="arr-data-review-message" role="status" aria-live="polite"></p>
|
||||
<div class="arr-data-review-actions">
|
||||
<button id="arr-data-review-refresh" type="button">刷新字段</button>
|
||||
<button class="primary-button" id="arr-data-review-finalize" type="button" disabled>确认并生成日报</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="arr-data-review-scroll" role="region" aria-label="待完善报表字段" tabindex="0">
|
||||
<table class="arr-data-review-table">
|
||||
<thead><tr><th scope="col">预订信息</th><th scope="col">待完善字段</th><th scope="col">核实后的值</th><th scope="col">操作</th></tr></thead>
|
||||
<tbody id="arr-data-review-body"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p class="arr-data-review-empty" id="arr-data-review-empty" hidden>没有待完善字段。</p>
|
||||
<section class="panel arr-download-pending" id="arr-download-pending" aria-labelledby="arr-download-pending-title" hidden>
|
||||
<h2 id="arr-download-pending-title">需处理日期</h2>
|
||||
<div id="arr-download-pending-list"></div>
|
||||
</section>
|
||||
|
||||
<section class="daily-price-review-panel" id="daily-price-review-panel" aria-labelledby="daily-price-review-title" tabindex="-1" hidden>
|
||||
<header class="daily-price-review-header">
|
||||
<div class="daily-price-review-title-block">
|
||||
<span class="step-label">价格复核 / 待处理</span>
|
||||
<h2 id="daily-price-review-title">人工价格复核</h2>
|
||||
<p id="daily-price-review-copy" role="status">请为所有缺少固定价的价格键填写每晚价格。相同键只需填写一次。</p>
|
||||
</div>
|
||||
<dl class="daily-price-review-metrics" aria-label="人工价格复核进度">
|
||||
<div><dt>已填写</dt><dd id="daily-price-review-completed">0</dd></div>
|
||||
<div class="is-review"><dt>待处理</dt><dd id="daily-price-review-pending">0</dd></div>
|
||||
</dl>
|
||||
<section class="panel manual-review-workspace" id="manual-review-workspace" aria-labelledby="manual-review-title" hidden>
|
||||
<header class="manual-review-heading">
|
||||
<h2 id="manual-review-title">人工核对</h2>
|
||||
<p id="manual-review-context" role="status" aria-live="polite"></p>
|
||||
</header>
|
||||
<div class="daily-price-review-toolbar">
|
||||
<p class="daily-price-review-message" id="daily-price-review-message" role="status"></p>
|
||||
<div class="daily-price-review-actions">
|
||||
<button class="daily-price-review-cancel" id="daily-price-review-cancel" type="button">取消本次复核</button>
|
||||
<button class="daily-price-review-finalize" id="daily-price-review-finalize" type="button" disabled>确认并生成日报</button>
|
||||
<section class="arr-data-review-panel" id="arr-data-review-panel" aria-labelledby="arr-data-review-title" tabindex="-1" hidden>
|
||||
<header class="arr-data-review-header">
|
||||
<div>
|
||||
<h3 class="sr-only" id="arr-data-review-title">完善报表字段</h3>
|
||||
<p id="arr-data-review-copy">请核实并逐项保存缺失或有冲突的字段。允许为空的字段也须明确确认,全部完成后才能生成日报。</p>
|
||||
</div>
|
||||
<p id="arr-data-review-progress" role="status" aria-live="polite"></p>
|
||||
</header>
|
||||
<div class="arr-data-review-toolbar">
|
||||
<p id="arr-data-review-message" role="status" aria-live="polite"></p>
|
||||
<div class="arr-data-review-actions">
|
||||
<button id="arr-data-review-refresh" type="button">刷新字段</button>
|
||||
<button class="primary-button" id="arr-data-review-finalize" type="button" disabled>确认并生成日报</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="daily-price-review-scroll" role="region" aria-label="待人工定价项" tabindex="0">
|
||||
<table class="daily-price-review-table">
|
||||
<thead>
|
||||
<tr><th scope="col">公司</th><th scope="col">Rate Code</th><th scope="col">Opera 价</th><th scope="col">固定价候选</th><th scope="col">影响记录</th><th scope="col">房数 / 房晚</th><th scope="col">人工价格</th><th scope="col">操作</th></tr>
|
||||
</thead>
|
||||
<tbody id="daily-price-review-body"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p class="daily-price-review-empty" id="daily-price-review-empty" hidden>没有可显示的待人工定价项。</p>
|
||||
<nav class="daily-price-review-pagination" aria-label="人工价格复核分页">
|
||||
<span id="daily-price-review-page-summary">共 0 项</span>
|
||||
<div>
|
||||
<button id="daily-price-review-prev" type="button" disabled>上一页</button>
|
||||
<strong id="daily-price-review-page-label">第 1 / 1 页</strong>
|
||||
<button id="daily-price-review-next" type="button" disabled>下一页</button>
|
||||
<div class="arr-data-review-scroll" role="region" aria-label="待完善报表字段" tabindex="0">
|
||||
<table class="arr-data-review-table">
|
||||
<thead><tr><th scope="col">预订信息</th><th scope="col">待完善字段</th><th scope="col">核实后的值</th><th scope="col">操作</th></tr></thead>
|
||||
<tbody id="arr-data-review-body"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</nav>
|
||||
<p class="arr-data-review-empty" id="arr-data-review-empty" hidden>没有待完善字段。</p>
|
||||
</section>
|
||||
|
||||
<section class="daily-price-review-panel" id="daily-price-review-panel" aria-labelledby="daily-price-review-title" tabindex="-1" hidden>
|
||||
<header class="daily-price-review-header">
|
||||
<div class="daily-price-review-title-block">
|
||||
<h3 class="sr-only" id="daily-price-review-title">价格复核</h3>
|
||||
<p id="daily-price-review-copy" role="status">请为所有缺少固定价的价格键填写每晚价格。相同键只需填写一次。</p>
|
||||
</div>
|
||||
<dl class="daily-price-review-metrics" aria-label="人工价格复核进度">
|
||||
<div><dt>已填写</dt><dd id="daily-price-review-completed">0</dd></div>
|
||||
<div class="is-review"><dt>待处理</dt><dd id="daily-price-review-pending">0</dd></div>
|
||||
</dl>
|
||||
</header>
|
||||
<div class="daily-price-review-toolbar">
|
||||
<p class="daily-price-review-message" id="daily-price-review-message" role="status"></p>
|
||||
<div class="daily-price-review-actions">
|
||||
<button class="daily-price-review-cancel" id="daily-price-review-cancel" type="button">取消本次复核</button>
|
||||
<button class="daily-price-review-finalize" id="daily-price-review-finalize" type="button" disabled>确认并生成日报</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="daily-price-review-scroll" role="region" aria-label="待人工定价项" tabindex="0">
|
||||
<table class="daily-price-review-table">
|
||||
<thead>
|
||||
<tr><th scope="col">公司</th><th scope="col">Rate Code</th><th scope="col">Opera 价</th><th scope="col">固定价候选</th><th scope="col">影响记录</th><th scope="col">房数 / 房晚</th><th scope="col">人工价格</th><th scope="col">操作</th></tr>
|
||||
</thead>
|
||||
<tbody id="daily-price-review-body"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p class="daily-price-review-empty" id="daily-price-review-empty" hidden>没有可显示的待人工定价项。</p>
|
||||
<nav class="daily-price-review-pagination" aria-label="人工价格复核分页">
|
||||
<span id="daily-price-review-page-summary">共 0 项</span>
|
||||
<div>
|
||||
<button id="daily-price-review-prev" type="button" disabled>上一页</button>
|
||||
<strong id="daily-price-review-page-label">第 1 / 1 页</strong>
|
||||
<button id="daily-price-review-next" type="button" disabled>下一页</button>
|
||||
</div>
|
||||
</nav>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section class="panel table-panel" aria-labelledby="daily-history-title">
|
||||
|
||||
@@ -201,16 +201,21 @@ button { color: inherit; }
|
||||
.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; }
|
||||
.arr-download-review:hover { color: var(--blue); }
|
||||
.arr-download-pending { margin: 10px 0 12px; }
|
||||
.arr-download-pending { margin: 0 0 20px; padding: 20px; }
|
||||
.arr-download-pending[hidden] { display: none; }
|
||||
.arr-download-pending > span { display: block; margin-bottom: 5px; color: var(--muted); font-size: 11px; }
|
||||
#arr-download-pending-list { display: flex; flex-wrap: wrap; gap: 6px; max-height: 110px; overflow-y: auto; }
|
||||
#arr-download-pending-list button { padding: 5px 8px; border: 1px solid var(--line); border-radius: 6px; color: var(--blue-dark); background: #fff; font: inherit; font-size: 11px; cursor: pointer; }
|
||||
.arr-download-pending h2 { margin: 0 0 12px; font-size: 18px; line-height: 1.3; letter-spacing: -.025em; }
|
||||
#arr-download-pending-list { display: flex; flex-wrap: wrap; gap: 8px; max-height: 160px; overflow-y: auto; }
|
||||
#arr-download-pending-list button { min-height: 38px; padding: 8px 12px; border: 1px solid var(--line); border-radius: 8px; color: var(--blue-dark); background: #fff; font: inherit; font-size: 12px; cursor: pointer; }
|
||||
#arr-download-pending-list button[aria-pressed="true"] { border-color: var(--blue); background: #f0f4ff; }
|
||||
#arr-download-pending-list button:disabled { opacity: .55; cursor: default; }
|
||||
.arr-data-review-panel { margin: 20px 0; border-color: #e6d4b5; overflow: hidden; }
|
||||
.manual-review-workspace { position: relative; margin: 0 0 20px; overflow: hidden; }
|
||||
.manual-review-workspace[hidden] { display: none; }
|
||||
.manual-review-heading { padding: 20px 20px 16px; border-bottom: 1px solid var(--line); }
|
||||
.manual-review-heading h2 { margin: 0; font-size: 18px; line-height: 1.3; letter-spacing: -.025em; }
|
||||
.manual-review-heading p { margin: 7px 0 0; color: var(--blue-dark); font-size: 12px; line-height: 1.5; font-variant-numeric: tabular-nums; }
|
||||
.arr-data-review-panel { margin: 0; overflow: hidden; }
|
||||
.arr-data-review-panel[hidden] { display: none; }
|
||||
.arr-data-review-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; padding: 20px; background: #fffcf5; }
|
||||
.arr-data-review-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; padding: 16px 20px; background: var(--surface-soft); }
|
||||
.arr-data-review-header h2 { margin: 0 0 6px; font-size: 17px; }
|
||||
.arr-data-review-header p { margin: 0; color: var(--muted); font-size: 12px; line-height: 1.6; }
|
||||
#arr-data-review-progress { flex-shrink: 0; color: var(--amber); font-variant-numeric: tabular-nums; }
|
||||
@@ -397,13 +402,14 @@ tbody tr:hover td { background: #fafcff; }
|
||||
.job-review-link:hover .job-review-progress { text-decoration-color: currentColor; }
|
||||
.job-review-link:hover .status-chip { box-shadow: inset 0 0 0 1px #e5ba63; }
|
||||
|
||||
.daily-price-review-panel { margin: 0 0 20px; overflow: hidden; scroll-margin-top: 18px; border: 1px solid #f1d49c; border-radius: 16px; background: #fff; box-shadow: 0 1px 2px rgba(16, 24, 40, .04), 0 14px 32px rgba(146, 93, 13, .08); }
|
||||
.daily-price-review-panel { margin: 0; overflow: hidden; scroll-margin-top: 18px; }
|
||||
.daily-price-review-panel[hidden] { display: none; }
|
||||
.daily-price-review-panel:focus-visible { outline: 3px solid rgba(168, 90, 10, .2); outline-offset: 3px; }
|
||||
.daily-price-review-header { padding: 18px 20px 16px; display: flex; align-items: center; justify-content: space-between; gap: 24px; border-bottom: 1px solid #f5e4bf; background: linear-gradient(100deg, #fffaf0, #fff); }
|
||||
.daily-price-review-header { padding: 16px 20px; display: flex; align-items: center; justify-content: space-between; gap: 24px; border-bottom: 1px solid var(--line); background: var(--surface-soft); }
|
||||
.daily-price-review-title-block { min-width: 0; flex: 1 1 auto; display: grid; gap: 5px; }
|
||||
.daily-price-review-title-block .step-label { color: #a85a0a; }
|
||||
.daily-price-review-title-block h2 { margin: 0; color: #3c280e; font-size: 18px; letter-spacing: -.025em; }
|
||||
.daily-price-review-title-block p { margin: 0; color: #7a5a2c; font-size: 11px; line-height: 1.5; }
|
||||
.daily-price-review-title-block p { margin: 0; color: var(--muted); font-size: 12px; line-height: 1.6; }
|
||||
.daily-price-review-metrics { margin: 0; display: grid; grid-template-columns: repeat(2, minmax(78px, 1fr)); gap: 8px; }
|
||||
.daily-price-review-metrics > div { min-width: 78px; padding: 8px 10px; border: 1px solid #ead9b4; border-radius: 9px; background: rgba(255, 255, 255, .82); }
|
||||
.daily-price-review-metrics > div.is-review { border-color: #f0c970; background: #fff7e5; }
|
||||
|
||||
Reference in new issue
Block a user