From 6d03cf9643cabd4799263d251b3efa4b5e247fbc Mon Sep 17 00:00:00 2001 From: OpenClaw Agent Date: Thu, 3 Sep 2026 22:14:48 +0800 Subject: [PATCH] snapshot: index.html @ 20260903_221448 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 由 index.html.bak.20260903_221448 重建的历史快照。 时间取自备份文件名(备份生成时刻,Asia/Shanghai)。 此提交只含 index.html,当时其余文件的状态没有对应备份,无法还原。 --- index.html | 164 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 132 insertions(+), 32 deletions(-) diff --git a/index.html b/index.html index abc11e8..f921b17 100644 --- a/index.html +++ b/index.html @@ -105,6 +105,16 @@ .stat-draft { background: #FEF3C7; color: #B45309; } .stat-final { background: #D1FAE5; color: #047857; } + /* 归属期徽章:标清一笔钱是哪个月挣的。进账列表里上月/本月混排, + 原本只写在小灰字副标题里、层级太弱,改用底色色块区分。 */ + .own-badge { + display: inline-flex; align-items: center; justify-content: center; + font-size: 9px; font-weight: 700; line-height: 1; + padding: 3px 5px; border-radius: 6px; white-space: nowrap; min-width: 32px; + } + .own-prev { background: #E2E8F0; color: #475569; } + .own-cur { background: #E0E7FF; color: #4338CA; } + /* ===== 日历格胶囊结构(第三轮) ===== 班次与工时整合为紧凑胶囊,避免 hInt/hFrac 拆分小数导致的折行; 左下实心属性点移除,仅保留右上状态点。 */ @@ -237,18 +247,21 @@ - +

- {{ currentMonth + 1 }}月预计到账 + {{ currentMonth + 1 }}月挣得· 干活口径

¥ {{ boardMain.int }} {{ boardMain.frac }}

+

- {{ settings.payDayB }}日 {{ money(payoutThisB) }} · {{ settings.payDayA }}日 {{ money(payoutThisA) }} + {{ currentMonth + 1 }}月进账 {{ money(cashTotal) }}(含{{ prevLabel.month + 1 }}月结转 {{ money(payoutThisB) }})

@@ -337,22 +350,71 @@
- +
- 本月到账 - 时薪 {{ settings.rate }} 元/h + {{ currentMonth + 1 }}月挣得 + 干活口径 · {{ currentMonth + 1 }}/1–{{ currentMonth + 1 }}/{{ daysInMonth }} +
+
+
+ 工时收入({{ fmt(monthStats.totalHours) }}h) + + 确定 + {{ money(monthStats.basePay) }} + +
+
+ 奖惩净额 + + {{ monthStats.finalized ? '已定稿' : '预估·待审核' }} + {{ signed(monthStats.adjustNet) }} + +
+
+ 合计应得 + {{ money(earnedTotal) }} +
+
+ +
+

何时到手

+
+
+ {{ currentMonth + 1 }}/{{ settings.payDayA }} 上半月工时({{ payDayAPassed ? '已发' : '待发' }}) + {{ money(earnedSplit.paid) }} +
+
+ {{ nextLabel.month + 1 }}/{{ settings.payDayB }} 下半月工时+奖惩(结转) + {{ money(earnedSplit.carry) }} +
+
+

处罚已超过下半月工时收入,结转那笔按 ¥0 计,所以两笔相加不等于合计应得

+
+
+ + +
+
+ {{ currentMonth + 1 }}月进账 + 钱包口径 · 时薪 {{ settings.rate }} 元/h
-
-
-

{{ currentMonth + 1 }}月{{ settings.payDayB }}日

-

{{ prevLabel.month + 1 }}月下半月 {{ fmt(prevStats.h2) }}h + 奖惩 {{ signed(prevStats.adjustNet) }}

+
+
+ {{ prevLabel.month + 1 }}月 +
+

{{ currentMonth + 1 }}/{{ settings.payDayB }}

+

下半月 {{ fmt(prevStats.h2) }}h + 奖惩 {{ signed(prevStats.adjustNet) }}

+
{{ money(payoutThisB) }}
- +
@@ -365,33 +427,39 @@
-
-
-

{{ currentMonth + 1 }}月{{ settings.payDayA }}日

-

本月上半月 {{ fmt(monthStats.h1) }}h · 纯工时

+
+
+ {{ currentMonth + 1 }}月 +
+

{{ currentMonth + 1 }}/{{ settings.payDayA }}

+

上半月 {{ fmt(monthStats.h1) }}h · 纯工时

+
{{ money(payoutThisA) }}
- 本月现金流合计 - {{ money(payoutThisB + payoutThisA) }} + 合计进账 + {{ money(cashTotal) }}
-

本月工时

+

{{ currentMonth + 1 }}月工时

上半月 1–{{ settings.cutoff }}日

{{ fmt(monthStats.h1) }}h

{{ money(monthStats.h1 * settings.rate) }}

+ +

本月{{ settings.payDayA }}号发

下半月 {{ settings.cutoff + 1 }}日–月底

{{ fmt(monthStats.h2) }}h

{{ money(monthStats.h2 * settings.rate) }}

+

结转{{ nextLabel.month + 1 }}月{{ settings.payDayB }}号发

@@ -404,7 +472,7 @@
-

本月奖惩

+

{{ currentMonth + 1 }}月奖惩

次月{{ settings.payDayB }}号结算

以下金额不计入当月工资

@@ -473,21 +541,25 @@
- +
-

{{ nextLabel.month + 1 }}月{{ settings.payDayB }}日预估

- {{ money(payoutNextB) }} +
+

结转到 {{ nextLabel.month + 1 }}月{{ settings.payDayB }}日

+

{{ currentMonth + 1 }}月挣得里未发的部分

+
+ {{ money(payoutNextB) }}
-
本月下半月工时 {{ fmt(monthStats.h2) }}h{{ money(monthStats.h2 * settings.rate) }}
-
本月奖惩结算{{ signed(monthStats.adjustNet) }}
+
{{ currentMonth + 1 }}月下半月工时 {{ fmt(monthStats.h2) }}h{{ money(monthStats.h2 * settings.rate) }}
+
{{ currentMonth + 1 }}月奖惩结算{{ signed(monthStats.adjustNet) }}
奖惩口径 {{ monthStats.finalized ? '已定稿' : '预估(未申报)' }}
-

处罚已超过下半月工时收入,实发按 ¥0 计,差额可能顺延

+

处罚已超过下半月工时收入,实发按 ¥0 计,差额可能顺延

@@ -1071,6 +1143,27 @@ createApp({ const payoutThisB = computed(() => Math.max(0, prevStats.value.h2 * cfg.value.rate + prevStats.value.adjustNet)); const payoutNextB = computed(() => Math.max(0, monthStats.value.h2 * cfg.value.rate + monthStats.value.adjustNet)); + // ===== 两套记账口径(这是页面之前最主要的歧义源) ===== + // 归属制「挣得」:本月 1–月底干出来的钱,不管什么时候发。打一天卡当天就涨。 + // 收付制「进账」:本月卡里实际进的钱,含上月结转部分。 + // 两者永远不相等,必须各自具名、分区展示,不能都叫「本月」。 + const earnedTotal = computed(() => monthStats.value.basePay + monthStats.value.adjustNet); + const cashTotal = computed(() => payoutThisB.value + payoutThisA.value); + // 「挣得」拆成两笔落地时间:上半月工时随本月 payDayA;下半月工时 + 奖惩结转次月 payDayB。 + // 这一行是两套口径之间唯一的桥,解释了为何挣得 ≠ 进账。 + const earnedSplit = computed(() => ({ paid: payoutThisA.value, carry: payoutNextB.value })); + // 上半月那笔到没到账,只在看当前月份时才有「待发」说法;翻历史月份一律算已发。 + const payDayAPassed = computed(() => { + if (!isCurrentMonth.value) { + const n = new Date(); + return currentYear.value < n.getFullYear() || + (currentYear.value === n.getFullYear() && currentMonth.value < n.getMonth()); + } + return new Date().getDate() >= cfg.value.payDayA; + }); + // 处罚吃穿下半月工时时,结转那笔被 ¥0 兰住,于是 paid+carry > earnedTotal。页面需要明说。 + const earnedFloored = computed(() => monthStats.value.h2 * cfg.value.rate + monthStats.value.adjustNet < 0); + const penaltyDetails = computed(() => { const c = cfg.value; const prefix = monthPrefix(currentYear.value, currentMonth.value); @@ -1094,7 +1187,7 @@ createApp({ const recordCount = computed(() => Object.keys(records.value).length); // 看板主数字:本月两笔到账合计 - const boardMain = computed(() => moneyParts(payoutThisB.value + payoutThisA.value)); + const boardMain = computed(() => moneyParts(earnedTotal.value)); const hasPenalty = (day) => { const r = getRecord(day); @@ -1296,22 +1389,28 @@ createApp({ const buildReport = () => { const s = monthStats.value, p = prevStats.value, c = cfg.value; const m = currentMonth.value + 1, nm = nextLabel.value.month + 1, pm = prevLabel.value.month + 1; + // 报告也按「挣得 / 进账」两套口径分段,与页面用词保持一致,否则复制出去又是一笔糊涂账。 return [ `${currentYear.value}年${m}月工时薪酬复盘(时薪 ${c.rate} 元/h)`, `出勤 ${s.workDays}/${c.fullDays} 天(白${s.dayShifts}/夜${s.nightShifts}) | 总工时 ${fmt(s.totalHours)}h`, `上半月 ${fmt(s.h1)}h → ${money(s.h1 * c.rate)} 下半月 ${fmt(s.h2)}h → ${money(s.h2 * c.rate)}`, ``, - `【本月奖惩·次月${settings.payDayB}号结算】`, + `【${m}月挣得·干活口径】${money(earnedTotal.value)}`, + `工时收入 ${money(s.basePay)}(确定) | 奖惩净额 ${signed(s.adjustNet)}(${s.finalized ? '已定稿' : '预估·待审核'})`, + `何时到手:${m}/${settings.payDayA} ${money(earnedSplit.value.paid)}(上半月工时) | ${nm}/${settings.payDayB} ${money(earnedSplit.value.carry)}(结转:下半月工时+奖惩)`, + ``, + `【${m}月奖惩明细·次月${settings.payDayB}号结算】`, `满勤奖 ${s.fullBonus > 0 ? '+' + money(s.fullBonus) : '¥0(未满勤)'}`, `查获 +${money(s.foundBonus)}(${s.foundCount}件) | 漏查 -${money(s.missedPenalty)}(${s.missedCount}件) | 其他 -${money(s.otherPenalties)}`, + `日常累计(待申报)${signed(s.rawReview)}${s.finalized ? ` → 审核终稿 ${signed(s.reviewAmount)}` : ''}`, `奖惩净额 ${signed(s.adjustNet)}`, ``, - `【本月到账】`, - `${m}月${settings.payDayB}日 ${money(payoutThisB.value)}(${pm}月下半月 ${fmt(p.h2)}h + ${pm}月奖惩 ${signed(p.adjustNet)})`, - `${m}月${settings.payDayA}日 ${money(payoutThisA.value)}(本月上半月 ${fmt(s.h1)}h)`, - `合计 ${money(payoutThisB.value + payoutThisA.value)}`, + `【${m}月进账·钱包口径】${money(cashTotal.value)}`, + `${m}月${settings.payDayB}日 ${money(payoutThisB.value)}(归属${pm}月:下半月 ${fmt(p.h2)}h + 奖惩 ${signed(p.adjustNet)})`, + `${m}月${settings.payDayA}日 ${money(payoutThisA.value)}(归属${m}月:上半月 ${fmt(s.h1)}h)`, + `合计 ${money(cashTotal.value)}(含${pm}月结转 ${money(payoutThisB.value)})`, ``, - `【${nm}月${settings.payDayB}日预估】${money(payoutNextB.value)}(本月下半月 ${fmt(s.h2)}h + 奖惩 ${signed(s.adjustNet)})` + `【${nm}月${settings.payDayB}日预估·结转】${money(payoutNextB.value)}(${m}月下半月 ${fmt(s.h2)}h + 奖惩 ${signed(s.adjustNet)})` ].join('\n'); }; @@ -1439,6 +1538,7 @@ createApp({ copied, dataCopied, toast, monthStats, prevStats, prevLabel, nextLabel, payoutThisA, payoutThisB, payoutNextB, penaltyDetails, + earnedTotal, cashTotal, earnedSplit, earnedFloored, payDayAPassed, fmt, money, signed, moneyParts, boardMain, buildReport, applyImport, isToday, isCurrentMonth, getRecord, hasPenalty, cellClass, isCutEdge, payDayKind, selectedPayInfo,