diff --git a/.project-docs/30-worklog/tasks/20261009-ui-simplify-b724.md b/.project-docs/30-worklog/tasks/20261009-ui-simplify-b724.md new file mode 100644 index 0000000..fb33da9 --- /dev/null +++ b/.project-docs/30-worklog/tasks/20261009-ui-simplify-b724.md @@ -0,0 +1,63 @@ +# Task: 精简日报界面与顶部卡片布局 + +## Identity + +- Task ID: 20261009-ui-simplify-b724 +- Mode: Feature +- Branch: codex/20261009-ui-simplify-b724-ui-simplify +- Worktree: /Users/chillishark/.codex/worktrees/arr-ui-simplify +- Base commit: 6d1a98743f61fd6216a38a6641bbb1df56619d56 +- Owner: codex +- Status: Ready for Integration + +## Scope + +- User-requested UI cleanup: remove download retention hint, rename acquisition status to status, remove review explanation/count/exclusion summaries and per-issue explanatory metadata, suppress zero-history operation, retain only the blue field-review action. Compress the desktop header card row to about two thirds of its current width and align upload/calendar headings and content. + +## Intent And Constraints + +- Preserve existing field/price inputs, save/confirm/generate actions, nonempty history access, task identity/queues, XML/OHIP/Finance/monthly business rules and all real data. Keep current blue/white style, generated-green popup calendar, responsive usable controls and accessible names. No Oracle query, report mutation or actual review changes. Local activation must preserve service configuration/data and avoid active jobs. Existing publication authorization to arr0918/main persists. + +## Outcome + +- Removed the pending-retention hint, review instructions, confirmation/exclusion summary and field reason/rule/source-row/company/rate metadata. Field review retains reservation identity, field name, input, confirmation status and actions. Price review retains the company/rate/Opera-price key, manual price and actions; candidate/affected-record/room-night explanation columns and top metrics are removed. Removed DOM references and associated presentational helpers, while required/optional enforcement and error feedback remain unchanged. +- Renamed acquisition label to “状态” in all three locales; retained progress/counts. The download card has only its blue main field-review action; price-review access remains available. Daily rows render a history button only when history_count>0, preserving nonempty history, download and delete operations. +- Desktop width>=1440 uses two thirds of the original header width, with compact flexible columns. Upload content is vertically centered and title/control starts align with the report calendar. Smaller widths keep full-width responsive grids or a single column. Existing green generated dates and popup/month navigation remain. +- Local8875 now runs this worktree, with a cold backup at /Users/chillishark/Library/Application Support/ARR2.0/ui-simplify-backup-20261009-062152. Activation changed only private code paths; processor4.4.0, schema008-022, credentials/hotel/routing and all business data remain. No Oracle request, acquisition, upload, report mutation or real review submission performed. Code publication is authorized to arr0918/main, with verified commit recorded privately after push. + +## Verification + +- 139 JavaScript UI tests passed; 15 relevant daily visual/price-review static checks passed, including root rerun after final CSS. JavaScript syntax and git diff --check passed. Independent review reran83 overlapping relevant cases, checked removed IDs have no dangling queries/bindings, and exercised real i18n.setLocale plus field/price rendering in zh-CN/en/th without API calls. +- Synthetic browser proof: explanations/metadata absent; one blue field action opens review; price0 enables save and is retained when unsaved-switch guard rejects changing dates. Five-column price rendering, neutral empty history and nonzero history access remain. English/Thai review/status render without errors. No synthetic mutation was submitted; private preview accepts only GET. +- Browser layout proof at actual375/767/1024/1440 widths: no page horizontal overflow or arrival-date clipping. Desktop1600 row933.33px versus shell1400px gives ratio0.666664; upload/report title and control start differ by less than1px. Popup is fully inside the viewport. Small screens naturally stack cards rather than force the compressed desktop width. +- Actual8875 readonly proof: September13 retains one room issue for reservation300622945 with only field/input/status/save operation, no explanation or exclusion counts; the main blue field button still opens the same review. “状态” progress shows completed135/135. September17 has no history button, September16 retains “历史记录(1)”. Screenshot evidence saved privately as live-compact-header.png and live-compact-review.png. +- Before/after comparison, repeated after browser actions, preserved all27 table fingerprints, 3 current report pointers, 4896 source files, monthly workbooks/API records, queue statuses, pending datesSeptember15/13 and retirement audit. No business/API/Python/schema source changed. + +## Follow-ups + +- No requested product work remains. Retain this worktree because the local service runs from it. Canonical reconciliation remains a separate serialized integration task; old clean worktrees were left untouched. + +## Promotion Candidates + +- Target: portal architecture/current-state. Proposal: record compact two-thirds desktop header, upload/calendar alignment and simplified field/price review presentation; required validation/audit facts remain stored but explanatory prose is omitted from operator forms. Evidence: explicit seven-point user instruction, 139 JS/15 UI checks, independent review and actual readonly browser/data-preservation proof. Future impact: avoid reintroducing duplicate field-review or zero-history actions and implementation/audit explanations into the product flow. No business-rule conflict; this product revision was explicitly authorized. Feature mode does not write canonical memory. + +## Concurrent Task Gate + +- Passed: bundled check_project_docs succeeded (canonical migration pending integration); start succeeded with task20261009-ui-simplify-b724, feature/codex, managed worktree/Users/chillishark/.codex/worktrees/arr-ui-simplify, branchcodex/20261009-ui-simplify-b724-ui-simplify, base6d1a98743f61fd6216a38a6641bbb1df56619d56. Status JSON confirms matching identity. Calendar/lifecycle/production-review peers are Ready for Integration, Scope/Constraints/Promotion Candidates read-only. Original primary remains untouched; only this new task changes its checkout. + +## Project Context Loaded + +- Read: read-before-planning/planning-gate, own task, memory-index, positioning, current-state active snapshot, decision-index, system-overview, domain rules, success criteria, ADR006/007, relevant evidence/commitments/stale indexes, and peer scopes/constraints/promotions. +- Project goal: same deterministic XML/OHIP processing into daily Finance facts and automatic monthly results. +- Current focus: user-facing clarity and compact aligned daily header; remove surplus prose and duplicate actions. +- Constraints/decisions: display-only changes; non-negative reviewed prices including0 and required field enforcement remain unchanged. Current effective daily date/pointer determines calendar status. No actual submissions/deletions/Oracle queries. +- Evidence/conflicts: canonical September docs are stale versus direct October instructions and completed source-task evidence (productionhotel57106, schema022, processor4.4.0, multiple agents permitted). Direct user instruction supersedes the old visible explanations and duplicated links; no business-rule conflict. Current8875 runs calendar worktree; this isolated checkout needs safe activation. +- Modules: static app/index/i18n/styles and relevant existing UI tests; local static serving composition only if needed. +- Unknowns: interpretation of two-thirds width is implemented literally for desktop, with responsive fallback to avoid clipping. Align upload/calendar title/control positions using common spacing. No blocking user decision. +- Gate: Passed. Design guidance adapted to the established blue/white interface; no glass effects or new typography/dependencies. + +## Plan + +1. Remove requested surplus content and duplicate/zero-history actions while preserving operational state and input controls. +2. Implement compact header width and upload/calendar alignment with usable responsive breakpoints. +3. Verify rendering/interaction using synthetic and read-only live evidence, preserve all data, activate locally and publish the scoped change. diff --git a/arr_web/DIRECT_DATA_ENTRY.md b/arr_web/DIRECT_DATA_ENTRY.md index 0998a30..ebddb90 100644 --- a/arr_web/DIRECT_DATA_ENTRY.md +++ b/arr_web/DIRECT_DATA_ENTRY.md @@ -14,6 +14,8 @@ 任务结果待确认时,先检查或继续按钮上标明日期的原任务,避免重复提交。 某一天等待人工完善不阻塞其他日期:另选日期后可点击“下载并处理”,此前字段或价格任务仍保存在“需处理日期”中。 点击需处理日期可返回该日的“人工核对”,刷新后列表仍保留;同一天的未完成任务沿用原编号。 + +人工核对页面只展示预订编号、字段名、输入和确认操作;价格核对保留公司、费率代码、Opera价、人工价格和保存操作。页面不展示来源/规则解释或取消、PM排除数量,相关原始数据和审计仍保留。字段完善在下载卡片仅保留蓝色主按钮,必填/留空限制、保存校验和生成门槛不变。 切换字段任务保留各自草稿,未保存的价格会阻止切换核对任务;刷新或切换语言前仍应保存输入,已保存决定长期保留。 完整采集中的缺字段、多个候选或不满足原规则的字段先进入“待完善数据”(`needs_data_review`)。 全部阻塞字段通过并确认后,原任务自动继续处理;随后只有缺少pureprice时进入原有价格复核(`needs_review`)。 @@ -35,11 +37,11 @@ 点击列表中的日期,可查看该日概览;上方日期与房数始终对应当前查看日期。待处理新版本会单独提示,尚无有效日报时显示空值,不借用其他日期的成功结果。 -顶部概览提供“自动下载 ARR、上传 ARR.XML、ARRIVAL DATE、NO. OF ROOM、本月报表情况”五个区域,顶部不再展示处理耗时。“本月报表情况”默认收起,显示月份和已生成天数;点击带日历图标的月份按钮展开月历,支持切换月份。每一天按是否存在当前有效日报标为“已生成”或“未生成”,已有报表的日期显示为绿色。历史版本、已删除版本和仅待核对的任务不算已生成;已有有效日报、另有待核对新版本时,仍标为已生成。读取中或读取失败会单独显示,不把未知状态当作未生成。 +顶部概览提供“自动下载 ARR、上传 ARR.XML、ARRIVAL DATE、NO. OF ROOM、本月报表情况”五个区域,顶部不再展示处理耗时。宽屏卡片行宽度约为原来的2/3,上传与日历标题、内容对齐,小屏按可用宽度自动排列。“本月报表情况”默认收起,显示月份和已生成天数;点击带日历图标的月份按钮展开月历,支持切换月份。每一天按是否存在当前有效日报标为“已生成”或“未生成”,已有报表的日期显示为绿色。历史版本、已删除版本和仅待核对的任务不算已生成;已有有效日报、另有待核对新版本时,仍标为已生成。读取中或读取失败会单独显示,不把未知状态当作未生成。 点击日历日期只切换查看日期和日报列表月份,不会获取Oracle数据、生成报表或提交人工核对值。需要下载新数据时,仍须在自动下载入口主动提交;未保存的人工价格继续受切换保护。日历月份与列表分页独立,显示整月状态;生成或删除后的刷新会更新标记。 -“历史记录”保留同一天的旧版本和未完成版本。删除前页面会说明影响: +存在历史版本时显示“历史记录”入口,保留同一天的旧版本和未完成版本;数量为0时不显示该按钮。删除前页面会说明影响: - 删除当前有效日报:该日从月报中移除,系统自动生成剩余日期的月报;整月已无有效日报时,撤下该月报。旧日报不会自动恢复。 - 删除历史版本或待价格核对版本:保留当前有效日报,月报不变。运行中的版本须等任务停止后再删除。 diff --git a/arr_web/README.md b/arr_web/README.md index 30c351b..b493ce0 100644 --- a/arr_web/README.md +++ b/arr_web/README.md @@ -4,6 +4,8 @@ 顶部“本月报表情况”提供可展开的日历按钮,有当前有效日报的日期显示为绿色,可切换月份和选择日期查看;顶部处理耗时已移除。日历只读取ARR已保存状态,不查询Oracle或自动创建报表。 +日报界面已精简:下载卡片显示“状态”,字段完善保留一个主按钮;人工核对只展示定位和填写所需信息及操作,不显示来源说明或排除统计。宽屏顶部卡片行约占原宽度的2/3,上传与日历内容对齐,小屏保持自适应。日报仅在存在历史版本时提供历史记录入口。 + 2026-09-18:[直接数据入口](DIRECT_DATA_ENTRY.md)已接通日期按钮、日报、复核和月报;独立本机模拟8875,未查询实际Oracle。 2026-09-17:[本机接口模拟全流程及按钮联调](LOCAL_API_SIMULATION.md)已在独立8874验证;[原文件重放](LOCAL_XML_REPLAY.md)8873保留。两个入口均明确未连接Oracle,不改变默认运行配置。 diff --git a/arr_web/static/app.js b/arr_web/static/app.js index 741e4de..36aa841 100644 --- a/arr_web/static/app.js +++ b/arr_web/static/app.js @@ -522,11 +522,12 @@ dateInput.disabled = locked; $("#arr-date-toggle").disabled = locked; $("#arr-date-toggle").setAttribute("aria-label", I18N.t("arr_download.choose_date")); - $("#arr-download-help").textContent = I18N.t(locked ? "arr_download.submitting" + const helpKey = locked ? "arr_download.submitting" : arrDownloadActive() ? "arr_download.date_next" - : arrDownloadNeedsDataReview() || task?.status === "needs_review" ? "arr_download.date_independent" - : reconciling ? "arr_download.date_resume" : "arr_download.help", - { date: state.arrDownloadIntent?.report_date }); + : arrDownloadNeedsDataReview() || task?.status === "needs_review" ? "" + : reconciling ? "arr_download.date_resume" : "arr_download.help"; + $("#arr-download-help").textContent = helpKey ? I18N.t(helpKey, { date: state.arrDownloadIntent?.report_date }) : ""; + $("#arr-download-help").hidden = !helpKey; if (locked) closeARRCalendar(); button.disabled = !state.arrDownloadLoaded || !state.arrDownloadReady || locked || arrDownloadActive() || state.arrDataReviewFinalizing || (!reconciling && !arrDownloadCanResume() && !validARRDate(dateInput.value)) @@ -555,8 +556,6 @@ const taskDate = viewingAnotherDate ? dateInput.value : task?.report_date || state.arrDownloadIntent?.report_date; $("#arr-download-status").textContent = taskDate ? `${taskDate} · ${text}` : text; $("#arr-download-review").hidden = viewingAnotherDate || task?.status !== "needs_review" || !task.job_id; - $("#arr-download-data-review").hidden = !selectedARRDateNeedsDataReview(); - $("#arr-download-data-review").disabled = locked; renderARRAcquisitionProgress(task); renderARRPendingReviews(); syncDailyOverviewDate(dateInput.value); @@ -815,25 +814,6 @@ return Array.isArray(item.value) ? item.value.join("\n") : String(item.value ?? ""); } - function arrDataReviewReasonKey(item) { - if (item.confirmed) return "confirmed_value"; - const sourceState = String(item.source_state || "").toLowerCase(); - const reason = String(item.reason_code || "").toUpperCase(); - // Older review snapshots do not expose source_state. Recognize only the - // collector's explicit failure codes; a missing optional field is not a - // failed request and does not make the field required. - const failedReasons = ["HTTP_FAILURE", "HTTP_PERMISSION_DENIED", "TRANSPORT_RETRY_EXHAUSTED", - "REQUEST_LIMIT_EXCEEDED", "RESPONSE_TOO_LARGE", "OPERATION_MISMATCH", "HOTEL_MISMATCH", - "INVALID_DATA_ENVELOPE", "MISSING_ORACLE_REQUEST_ID", "SECRET_IN_RESPONSE", "INVALID_JSON", - "UPSTREAM_WARNING_OR_ERROR"]; - if (sourceState === "failed" || failedReasons.includes(reason)) return "fetch_failed"; - if (sourceState === "ambiguous" || /(?:^|_)(?:CONFLICT|AMBIGUOUS|MISMATCH|DISAGREEMENT|CHANGED)(?:_|$)/.test(reason)) return "conflict_value"; - if (/(?:^|_)(?:INVALID|MALFORMED)(?:_|$)/.test(reason) || ["XML_NEGATIVE_NIGHTS", "DATA_NEGATIVE_NIGHTS"].includes(reason)) return "invalid_value"; - if (item.field === "DISP_ROOM_NO" && !item.can_be_empty - && ["CALENDAR_MISSING_ROOMS", "DATA_ROOM_MISSING", "XML_ROOM_MISSING"].includes(reason)) return "room_missing_in_scope"; - return item.can_be_empty ? "source_unconfirmed" : "required_value_missing"; - } - function arrDataReviewCanFinalize(review = state.arrDataReview) { return Boolean(arrDownloadNeedsDataReview() && state.arrDownloadTask.request_id === state.arrDataReviewRequestId && !state.arrDownloadBusy && review && review.status === "editing" && review.can_finalize && Number(review.pending_count) === 0 @@ -879,16 +859,6 @@ const editable = review?.status === "editing" && !busy && !state.arrDataReviewDisconnected && !state.arrDataReviewFinalizing; panel.setAttribute("aria-busy", String(busy)); $("#arr-data-review-title").textContent = I18N.t("data_review.title"); - $("#arr-data-review-copy").textContent = I18N.t(state.arrDataReviewFinalizing || review?.status === "finalized" ? "data_review.finalizing_copy" : "data_review.copy"); - $("#arr-data-review-progress").textContent = review ? I18N.t("data_review.progress", { - date: review.report_date, completed: Number(review.total_count) - Number(review.pending_count), total: review.total_count, - }) : I18N.t("data_review.loading"); - if (Number.isInteger(review?.excluded_cancelled_count) && review.excluded_cancelled_count > 0) { - $("#arr-data-review-progress").textContent += ` · ${I18N.t("data_review.excluded_cancelled", { count: review.excluded_cancelled_count })}`; - } - if (Number.isInteger(review?.excluded_pm_count) && review.excluded_pm_count > 0) { - $("#arr-data-review-progress").textContent += ` · ${I18N.t("data_review.excluded_pm", { count: review.excluded_pm_count })}`; - } $("#arr-data-review-refresh").textContent = I18N.t("data_review.refresh"); $("#arr-data-review-refresh").disabled = busy; const finalize = $("#arr-data-review-finalize"); @@ -901,8 +871,6 @@ const labelKey = `data_review.field_${field.toLowerCase()}`; const translatedLabel = I18N.t(labelKey); const label = translatedLabel === labelKey ? (item.field_label || field) : translatedLabel; - const reasonKey = arrDataReviewReasonKey(item); - const ruleKey = item.can_be_empty ? "optional_field_rule" : "required_field_rule"; const inputId = `arr-data-review-value-${index}`; const value = Object.prototype.hasOwnProperty.call(state.arrDataReviewDrafts, item.item_id) ? state.arrDataReviewDrafts[item.item_id] : arrDataReviewInputValue(item); @@ -912,8 +880,8 @@ ? `` : ``; return `
${escapeHtml(item.rate_code || "—")}