""" board-finance WXSS rpx 修正脚本 基于 H5 vs MP 逐选择器审计结果,精确替换 23 处差异。 审计报告:docs/reports/board-finance-h5-mp-audit.md 转换公式:rpx = CSS_px × (750/412) ≈ px × 1.8204 注意:2026-03-14 的 23 处修正已通过 IDE strReplace 直接应用。 本脚本保留作为修正记录和回滚参考。再次运行会因 old_text 不匹配而跳过。 """ import pathlib import sys import os def ensure_repo_root() -> None: """确保 cwd 为仓库根目录(含 pyproject.toml)。""" root_marker = pathlib.Path("pyproject.toml") if not root_marker.exists(): print(f"❌ 当前目录 {os.getcwd()} 不是仓库根目录,请在 C:\\NeoZQYY 下运行") sys.exit(1) ensure_repo_root() WXSS_PATH = pathlib.Path( "apps/miniprogram/miniprogram/pages/board-finance/board-finance.wxss" ) # (old_text, new_text, description) REPLACEMENTS: list[tuple[str, str, str]] = [ # --- #1 .filter-bar top: 78rpx → 80rpx (44px × 1.8204 = 80.10) --- ( "top: 78rpx;", "top: 80rpx;", "#1 .filter-bar top: 44px → 80rpx", ), # --- #2 .card-section border-radius: 30rpx → 14rpx (8px rounded-lg) --- # card-section 有 margin 和 border-radius 在同一块 ( " border-radius: 30rpx;\n overflow: visible;\n border: 2rpx solid #eeeeee;", " border-radius: 14rpx;\n overflow: visible;\n border: 2rpx solid #eeeeee;", "#2 .card-section border-radius: 8px → 14rpx", ), # --- #3 .card-header-dark padding: 24rpx → 26rpx (14px × 1.8204 = 25.49 → 26) --- ( " gap: 22rpx;\n padding: 24rpx 30rpx;\n background: #1a1a1a;", " gap: 22rpx;\n padding: 26rpx 30rpx;\n background: #1a1a1a;", "#3 .card-header-dark padding-TB: 14px → 26rpx", ), # --- #4 .card-header-emoji font-size: 32rpx → 33rpx (18px × 1.8204 = 32.77 → 33) --- ( ".card-header-emoji {\n font-size: 32rpx;", ".card-header-emoji {\n font-size: 33rpx;", "#4 .card-header-emoji font-size: 18px → 33rpx", ), # --- #5 .ai-insight-section margin: -2rpx → -30rpx (16px × 1.8204 = 29.13 → 30) --- ( " margin: 30rpx -2rpx -2rpx -2rpx;", " margin: 30rpx -30rpx -30rpx -30rpx;", "#5 .ai-insight-section margin: 16px -16px → 30rpx -30rpx", ), # --- #6 .ai-insight-icon width/height: 42rpx → 44rpx (24px × 1.8204 = 43.69 → 44) --- ( ".ai-insight-icon {\n width: 42rpx;\n height: 42rpx;", ".ai-insight-icon {\n width: 44rpx;\n height: 44rpx;", "#6 .ai-insight-icon w/h: 24px → 44rpx", ), # --- #7 .ai-insight-icon-img width/height: 32rpx → 33rpx (18px SVG) --- ( ".ai-insight-icon-img {\n width: 32rpx;\n height: 32rpx;", ".ai-insight-icon-img {\n width: 33rpx;\n height: 33rpx;", "#7 .ai-insight-icon-img w/h: 18px → 33rpx", ), # --- #8 .ai-insight-title font-size: 22rpx → 24rpx (13px × 1.8204 = 23.67 → 24) --- ( ".ai-insight-title {\n font-size: 22rpx;\n line-height: 29rpx;", ".ai-insight-title {\n font-size: 24rpx;\n line-height: 29rpx;", "#8 .ai-insight-title font-size: 13px → 24rpx", ), # --- #9 .card-section-title font-size: 22rpx → 24rpx (13px × 1.8204 = 23.67 → 24) --- ( ".card-section-title {\n font-size: 22rpx;\n line-height: 29rpx;\n font-weight: 600;", ".card-section-title {\n font-size: 24rpx;\n line-height: 29rpx;\n font-weight: 600;", "#9 .card-section-title font-size: 13px → 24rpx", ), # --- #10 .card-header-light border-radius: 30rpx 30rpx 0 0 → 14rpx 14rpx 0 0 --- ( " border-radius: 30rpx 30rpx 0 0;", " border-radius: 14rpx 14rpx 0 0;", "#10 .card-header-light border-radius: 8px top → 14rpx", ), # --- #11 .table-bordered border-radius: 30rpx → 14rpx --- ( ".table-bordered {\n border: 2rpx solid #e7e7e7;\n border-radius: 30rpx;", ".table-bordered {\n border: 2rpx solid #e7e7e7;\n border-radius: 14rpx;", "#11 .table-bordered border-radius: 8px → 14rpx", ), # --- #12 .total-balance-row border-radius: 30rpx → 14rpx --- ( " background: #f0f0f0;\n border-radius: 30rpx;\n border: 2rpx solid #e7e7e7;\n}\n\n.total-balance-left", " background: #f0f0f0;\n border-radius: 14rpx;\n border: 2rpx solid #e7e7e7;\n}\n\n.total-balance-left", "#12 .total-balance-row border-radius → 14rpx", ), # --- #13 .flow-item padding: 14rpx → 18rpx 0 (10px × 1.8204 = 18.20 → 18) --- ( ".flow-item {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 14rpx;", ".flow-item {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 18rpx 0;", "#13 .flow-item padding: 10px 0 → 18rpx 0", ), # --- #14 .flow-sum-row border-radius: 30rpx → 14rpx --- ( " border-radius: 30rpx;\n border-top: 2rpx solid #e7e7e7;\n}\n\n/* CHANGE 2026-03-13 | intent: 校对 H5 flow-sum-label", " border-radius: 14rpx;\n border-top: 2rpx solid #e7e7e7;\n}\n\n/* CHANGE 2026-03-13 | intent: 校对 H5 flow-sum-label", "#14 .flow-sum-row border-radius → 14rpx", ), # --- #15 .expense-cell border-radius: 30rpx → 14rpx --- ( ".expense-cell {\n background: #fafafa;\n border: 2rpx solid #e7e7e7;\n border-radius: 30rpx;", ".expense-cell {\n background: #fafafa;\n border: 2rpx solid #e7e7e7;\n border-radius: 14rpx;", "#15 .expense-cell border-radius → 14rpx", ), # --- #16 .sticky-section-header border-radius: 0 10rpx 10rpx 0 → 0 11rpx 11rpx 0 (6px × 1.8204 = 10.92 → 11) --- ( " border-radius: 0 10rpx 10rpx 0;", " border-radius: 0 11rpx 11rpx 0;", "#16 .sticky-section-header border-radius: 6px → 11rpx", ), # --- #17 .sticky-header-emoji font-size: 32rpx → 33rpx (18px) --- ( ".sticky-header-emoji {\n font-size: 32rpx;", ".sticky-header-emoji {\n font-size: 33rpx;", "#17 .sticky-header-emoji font-size: 18px → 33rpx", ), # --- #18 .sticky-header-tag border-radius: 10rpx → 11rpx (6px) --- ( " border-radius: 10rpx;\n white-space: nowrap;\n}\n\n/* ===== 卡片底部锯齿", " border-radius: 11rpx;\n white-space: nowrap;\n}\n\n/* ===== 卡片底部锯齿", "#18 .sticky-header-tag border-radius: 6px → 11rpx", ), # --- #19 & #20 .toc-item gap: 20rpx → 22rpx, padding: 20rpx → 22rpx (12px × 1.8204 = 21.84 → 22) --- ( ".toc-item {\n display: flex;\n align-items: center;\n gap: 20rpx;\n padding: 20rpx 30rpx;", ".toc-item {\n display: flex;\n align-items: center;\n gap: 22rpx;\n padding: 22rpx 30rpx;", "#19-20 .toc-item gap+padding: 12px → 22rpx", ), # --- #21 .toc-item-emoji font-size: 32rpx → 33rpx (18px) --- ( ".toc-item-emoji {\n font-size: 32rpx;", ".toc-item-emoji {\n font-size: 33rpx;", "#21 .toc-item-emoji font-size: 18px → 33rpx", ), # --- #22 & #23 .tip-toast-content font-size: 22rpx → 24rpx, line-height: 29rpx → 38rpx --- ( ".tip-toast-content {\n font-size: 22rpx;\n color: #4b4b4b;\n line-height: 29rpx;", ".tip-toast-content {\n font-size: 24rpx;\n color: #4b4b4b;\n line-height: 38rpx;", "#22-23 .tip-toast-content font-size: 13px → 24rpx, line-height: 1.6 → 38rpx", ), ] def main() -> None: if not WXSS_PATH.exists(): print(f"❌ 文件不存在: {WXSS_PATH}") sys.exit(1) content = WXSS_PATH.read_text(encoding="utf-8") applied = 0 skipped = 0 for old, new, desc in REPLACEMENTS: count = content.count(old) if count == 0: print(f"⚠️ 跳过(未匹配): {desc}") skipped += 1 elif count > 1: print(f"⚠️ 跳过(多次匹配 ×{count}): {desc}") skipped += 1 else: content = content.replace(old, new, 1) print(f"✅ 已修正: {desc}") applied += 1 WXSS_PATH.write_text(content, encoding="utf-8") print(f"\n完成: {applied} 处修正, {skipped} 处跳过") if __name__ == "__main__": main()