Files
Neo-ZQYY/scripts/ops/redesign_board_customer.py

692 lines
41 KiB
Python

# -*- coding: utf-8 -*-
"""重新设计 board-customer.html 各维度的差异化卡片布局。
每个维度有独特的视觉重点和数据展示方式。"""
import pathlib, re
from _env_paths import ensure_repo_root
ensure_repo_root()
TARGET = pathlib.Path("docs/h5_ui/pages/board-customer.html")
html = TARGET.read_text(encoding="utf-8")
# ── 助教行模板(复用) ──
def coach_row(coaches_html):
return f''' <div class="text-xs border-t border-gray-1 pt-2 ml-11">
<span class="text-gray-6">助教:</span>
{coaches_html}
</div>'''
# 常用助教组合
COACHES_A = '''<span class="assistant-tag">❤️ <span class="assistant-assignee">小燕</span><span class="assistant-badge assistant-badge-follow">跟</span></span>
<span class="assistant-sep">|</span>
<span class="assistant-tag">❤️ <span class="assistant-normal">泡芙</span></span>
<span class="assistant-sep">|</span>
<span class="assistant-tag">❤️ <span class="assistant-abandoned">Amy</span><span class="assistant-badge assistant-badge-drop">弃</span></span>'''
COACHES_B = '''<span class="assistant-tag">❤️ <span class="assistant-normal">Amy</span></span>
<span class="assistant-sep">|</span>
<span class="assistant-tag">❤️ <span class="assistant-normal">小燕</span></span>'''
COACHES_C = '''<span class="assistant-tag">❤️ <span class="assistant-assignee">泡芙</span><span class="assistant-badge assistant-badge-follow">跟</span></span>
<span class="assistant-sep">|</span>
<span class="assistant-tag">❤️ <span class="assistant-normal">小燕</span></span>'''
COACHES_D = '''<span class="assistant-tag">❤️ <span class="assistant-normal">泡芙</span></span>
<span class="assistant-sep">|</span>
<span class="assistant-tag">❤️ <span class="assistant-assignee">小燕</span><span class="assistant-badge assistant-badge-follow">跟</span></span>'''
COACHES_E = '''<span class="assistant-tag">❤️ <span class="assistant-normal">Amy</span></span>
<span class="assistant-sep">|</span>
<span class="assistant-tag">❤️ <span class="assistant-abandoned">泡芙</span><span class="assistant-badge assistant-badge-drop">弃</span></span>'''
COACHES_F = '''<span class="assistant-tag">❤️ <span class="assistant-normal">小燕</span></span>
<span class="assistant-sep">|</span>
<span class="assistant-tag">❤️ <span class="assistant-normal">泡芙</span></span>
<span class="assistant-sep">|</span>
<span class="assistant-tag">❤️ <span class="assistant-abandoned">Amy</span><span class="assistant-badge assistant-badge-drop">弃</span></span>'''
COACHES_G = '''<span class="assistant-tag">❤️ <span class="assistant-assignee">小燕</span><span class="assistant-badge assistant-badge-follow">跟</span></span>
<span class="assistant-sep">|</span>
<span class="assistant-tag">❤️ <span class="assistant-normal">泡芙</span></span>'''
COACHES_H = '''<span class="assistant-tag">❤️ <span class="assistant-normal">泡芙</span></span>
<span class="assistant-sep">|</span>
<span class="assistant-tag">❤️ <span class="assistant-normal">Amy</span></span>'''
COACHES_I = '''<span class="assistant-tag">❤️ <span class="assistant-assignee">小燕</span><span class="assistant-badge assistant-badge-follow">跟</span></span>
<span class="assistant-sep">|</span>
<span class="assistant-tag">❤️ <span class="assistant-abandoned">泡芙</span><span class="assistant-badge assistant-badge-drop">弃</span></span>'''
COACHES_J = '''<span class="assistant-tag">❤️ <span class="assistant-assignee">Amy</span><span class="assistant-badge assistant-badge-follow">跟</span></span>
<span class="assistant-sep">|</span>
<span class="assistant-tag">❤️ <span class="assistant-normal">小燕</span></span>'''
# ── 头像模板 ──
def avatar(color_from, color_to, char):
return f'''<div class="w-9 h-9 rounded-xl bg-gradient-to-br from-{color_from} to-{color_to} flex items-center justify-center shrink-0">
<span class="text-white font-semibold text-sm">{char}</span>
</div>'''
# ══════════════════════════════════════════════════════════
# 维度1: 最应召回 — 突出超期天数红色警告 + 进度条
# ══════════════════════════════════════════════════════════
DIM_RECALL = '''
<!-- ==================== 最应召回(默认) ==================== -->
<div id="dim-recall" class="dim-container active p-4 pt-1 space-y-3">
<a href="customer-detail.html" class="block bg-white rounded-2xl p-4 shadow-sm customer-card">
<div class="flex items-center justify-between mb-2">
<div class="flex items-center gap-2">
''' + avatar("amber-400","orange-500","") + '''
<span class="font-semibold text-gray-13">王先生</span>
</div>
<div class="flex items-center gap-1.5">
<span class="px-2 py-0.5 bg-error/10 text-error text-xs font-bold rounded-full">超期 8天</span>
</div>
</div>
<!-- 召回进度条:理想间隔 vs 实际 -->
<div class="ml-11 mb-2">
<div class="flex items-center justify-between text-[10px] text-gray-6 mb-1">
<span>理想间隔 7天</span>
<span class="text-error font-medium">已过 15天</span>
</div>
<div class="h-1.5 bg-gray-100 rounded-full overflow-hidden">
<div class="h-full rounded-full bg-gradient-to-r from-warning to-error" style="width:100%"></div>
</div>
</div>
<div class="flex flex-wrap gap-x-4 gap-y-1 text-xs ml-11 mb-2">
<div class="text-gray-6">30天到店 <span class="text-gray-11 font-medium">5次</span></div>
<div class="text-gray-6">余额 <span class="text-gray-11 font-medium">¥8,000</span></div>
<div class="text-gray-6">召回指数 <span class="text-primary font-bold">0.92</span></div>
</div>
''' + coach_row(COACHES_A) + '''
</a>
<a href="customer-detail.html" class="block bg-white rounded-2xl p-4 shadow-sm customer-card">
<div class="flex items-center justify-between mb-2">
<div class="flex items-center gap-2">
''' + avatar("pink-400","rose-500","") + '''
<span class="font-semibold text-gray-13">李女士</span>
</div>
<div class="flex items-center gap-1.5">
<span class="px-2 py-0.5 bg-warning/10 text-warning text-xs font-bold rounded-full">超期 10天</span>
</div>
</div>
<div class="ml-11 mb-2">
<div class="flex items-center justify-between text-[10px] text-gray-6 mb-1">
<span>理想间隔 10天</span>
<span class="text-warning font-medium">已过 20天</span>
</div>
<div class="h-1.5 bg-gray-100 rounded-full overflow-hidden">
<div class="h-full rounded-full bg-gradient-to-r from-warning to-error" style="width:100%"></div>
</div>
</div>
<div class="flex flex-wrap gap-x-4 gap-y-1 text-xs ml-11 mb-2">
<div class="text-gray-6">30天到店 <span class="text-gray-11 font-medium">3次</span></div>
<div class="text-gray-6">余额 <span class="text-gray-11 font-medium">¥12,500</span></div>
<div class="text-gray-6">召回指数 <span class="text-primary font-bold">0.88</span></div>
</div>
''' + coach_row(COACHES_B) + '''
</a>
<a href="customer-detail.html" class="block bg-white rounded-2xl p-4 shadow-sm customer-card">
<div class="flex items-center justify-between mb-2">
<div class="flex items-center gap-2">
''' + avatar("blue-400","indigo-500","") + '''
<span class="font-semibold text-gray-13">张先生</span>
</div>
<div class="flex items-center gap-1.5">
<span class="px-2 py-0.5 bg-error/10 text-error text-xs font-bold rounded-full">超期 11天</span>
</div>
</div>
<div class="ml-11 mb-2">
<div class="flex items-center justify-between text-[10px] text-gray-6 mb-1">
<span>理想间隔 7天</span>
<span class="text-error font-medium">已过 18天</span>
</div>
<div class="h-1.5 bg-gray-100 rounded-full overflow-hidden">
<div class="h-full rounded-full bg-gradient-to-r from-warning to-error" style="width:100%"></div>
</div>
</div>
<div class="flex flex-wrap gap-x-4 gap-y-1 text-xs ml-11 mb-2">
<div class="text-gray-6">30天到店 <span class="text-gray-11 font-medium">2次</span></div>
<div class="text-gray-6">余额 <span class="text-gray-11 font-medium">¥3,200</span></div>
<div class="text-gray-6">召回指数 <span class="text-primary font-bold">0.85</span></div>
</div>
''' + coach_row(COACHES_C) + '''
</a>
</div>
'''
# ══════════════════════════════════════════════════════════
# 维度2: 最大消费潜力 — 突出潜力评级 + 消费趋势
# ══════════════════════════════════════════════════════════
DIM_POTENTIAL = '''
<!-- ==================== 最大消费潜力 ==================== -->
<div id="dim-potential" class="dim-container p-4 pt-1 space-y-3">
<a href="customer-detail.html" class="block bg-white rounded-2xl p-4 shadow-sm customer-card">
<div class="flex items-center justify-between mb-2">
<div class="flex items-center gap-2">
''' + avatar("rose-400","pink-500","") + '''
<span class="font-semibold text-gray-13">赵女士</span>
</div>
<div class="text-right shrink-0">
<div class="text-primary font-bold">0.95</div>
<div class="text-[10px] text-gray-6 -mt-0.5">消费潜力</div>
</div>
</div>
<!-- 潜力评级条 -->
<div class="ml-11 mb-2 bg-gradient-to-r from-primary/5 to-blue-50 rounded-lg p-2.5">
<div class="flex items-center gap-2 mb-1.5">
<span class="text-xs font-bold text-primary">🔥 S级潜力</span>
<span class="text-[10px] text-gray-6">高频 · 高客单 · 高余额</span>
</div>
<div class="grid grid-cols-3 gap-2 text-center">
<div><p class="text-xs font-bold text-gray-13">¥4,800</p><p class="text-[10px] text-gray-6">近30天消费</p></div>
<div><p class="text-xs font-bold text-gray-13">8次</p><p class="text-[10px] text-gray-6">月均到店</p></div>
<div><p class="text-xs font-bold text-success">¥15,000</p><p class="text-[10px] text-gray-6">余额</p></div>
</div>
</div>
''' + coach_row(COACHES_D) + '''
</a>
<a href="customer-detail.html" class="block bg-white rounded-2xl p-4 shadow-sm customer-card">
<div class="flex items-center justify-between mb-2">
<div class="flex items-center gap-2">
''' + avatar("green-400","emerald-500","") + '''
<span class="font-semibold text-gray-13">刘先生</span>
</div>
<div class="text-right shrink-0">
<div class="text-primary font-bold">0.87</div>
<div class="text-[10px] text-gray-6 -mt-0.5">消费潜力</div>
</div>
</div>
<div class="ml-11 mb-2 bg-gradient-to-r from-primary/5 to-blue-50 rounded-lg p-2.5">
<div class="flex items-center gap-2 mb-1.5">
<span class="text-xs font-bold text-primary">⭐ A级潜力</span>
<span class="text-[10px] text-gray-6">中频 · 高客单</span>
</div>
<div class="grid grid-cols-3 gap-2 text-center">
<div><p class="text-xs font-bold text-gray-13">¥3,500</p><p class="text-[10px] text-gray-6">近30天消费</p></div>
<div><p class="text-xs font-bold text-gray-13">5次</p><p class="text-[10px] text-gray-6">月均到店</p></div>
<div><p class="text-xs font-bold text-success">¥6,800</p><p class="text-[10px] text-gray-6">余额</p></div>
</div>
</div>
''' + coach_row(COACHES_E) + '''
</a>
</div>
'''
# ══════════════════════════════════════════════════════════
# 维度3: 最高余额 — 突出余额大字 + 消耗速率
# ══════════════════════════════════════════════════════════
DIM_BALANCE = '''
<!-- ==================== 最高余额 ==================== -->
<div id="dim-balance" class="dim-container p-4 pt-1 space-y-3">
<a href="customer-detail.html" class="block bg-white rounded-2xl p-4 shadow-sm customer-card">
<div class="flex items-center justify-between mb-1">
<div class="flex items-center gap-2">
''' + avatar("rose-400","pink-500","") + '''
<span class="font-semibold text-gray-13">赵女士</span>
</div>
</div>
<!-- 余额突出展示 -->
<div class="ml-11 mb-2">
<div class="flex items-baseline gap-1.5">
<span class="text-2xl font-bold text-warning">¥25,000</span>
<span class="text-[10px] text-gray-6">余额</span>
</div>
<div class="flex items-center gap-3 mt-1.5 text-xs">
<div class="text-gray-6">60天消费 <span class="text-gray-11 font-medium">¥6,200</span></div>
<div class="text-gray-6">月均消耗 <span class="text-gray-11 font-medium">¥3,100</span></div>
</div>
<!-- 余额消耗预估 -->
<div class="mt-2 flex items-center gap-2">
<div class="flex-1 h-1.5 bg-gray-100 rounded-full overflow-hidden">
<div class="h-full rounded-full bg-gradient-to-r from-success to-emerald-400" style="width:25%"></div>
</div>
<span class="text-[10px] text-gray-6 shrink-0">预计可用 <span class="text-success font-medium">8个月</span></span>
</div>
</div>
<div class="flex flex-wrap gap-x-4 gap-y-1 text-xs ml-11 mb-2">
<div class="text-gray-6">最近到店 <span class="text-gray-11 font-medium">12天前</span></div>
<div class="text-gray-6">理想间隔 <span class="text-gray-11 font-medium">10天</span></div>
</div>
''' + coach_row(COACHES_F) + '''
</a>
<a href="customer-detail.html" class="block bg-white rounded-2xl p-4 shadow-sm customer-card">
<div class="flex items-center justify-between mb-1">
<div class="flex items-center gap-2">
''' + avatar("purple-400","violet-500","") + '''
<span class="font-semibold text-gray-13">陈先生</span>
</div>
</div>
<div class="ml-11 mb-2">
<div class="flex items-baseline gap-1.5">
<span class="text-2xl font-bold text-warning">¥18,500</span>
<span class="text-[10px] text-gray-6">余额</span>
</div>
<div class="flex items-center gap-3 mt-1.5 text-xs">
<div class="text-gray-6">60天消费 <span class="text-gray-11 font-medium">¥3,800</span></div>
<div class="text-gray-6">月均消耗 <span class="text-gray-11 font-medium">¥1,900</span></div>
</div>
<div class="mt-2 flex items-center gap-2">
<div class="flex-1 h-1.5 bg-gray-100 rounded-full overflow-hidden">
<div class="h-full rounded-full bg-gradient-to-r from-success to-emerald-400" style="width:10%"></div>
</div>
<span class="text-[10px] text-gray-6 shrink-0">预计可用 <span class="text-success font-medium">9.7个月</span></span>
</div>
</div>
<div class="flex flex-wrap gap-x-4 gap-y-1 text-xs ml-11 mb-2">
<div class="text-gray-6">最近到店 <span class="text-gray-11 font-medium">8天前</span></div>
<div class="text-gray-6">理想间隔 <span class="text-gray-11 font-medium">14天</span></div>
</div>
''' + coach_row(COACHES_G) + '''
</a>
</div>
'''
# ══════════════════════════════════════════════════════════
# 维度4: 最近充值 — 时间线样式 + 充值金额突出
# ══════════════════════════════════════════════════════════
DIM_RECHARGE = '''
<!-- ==================== 最近充值 ==================== -->
<div id="dim-recharge" class="dim-container p-4 pt-1 space-y-3">
<a href="customer-detail.html" class="block bg-white rounded-2xl p-4 shadow-sm customer-card">
<div class="flex items-center gap-2 mb-2">
''' + avatar("indigo-400","blue-500","") + '''
<div class="flex-1 min-w-0">
<span class="font-semibold text-gray-13">吴先生</span>
</div>
<span class="text-[10px] text-gray-6">2天前充值</span>
</div>
<!-- 充值信息突出 -->
<div class="ml-11 mb-2 bg-gradient-to-r from-emerald-50 to-green-50 rounded-lg p-2.5 border border-emerald-100/50">
<div class="flex items-center justify-between">
<div>
<span class="text-lg font-bold text-success">+¥5,000</span>
<span class="text-[10px] text-gray-6 ml-1">充值</span>
</div>
<div class="text-right">
<div class="text-xs text-gray-6">充后余额</div>
<div class="text-sm font-bold text-gray-13">¥8,200</div>
</div>
</div>
</div>
<div class="flex flex-wrap gap-x-4 gap-y-1 text-xs ml-11 mb-2">
<div class="text-gray-6">最近到店 <span class="text-gray-11 font-medium">2天前</span></div>
<div class="text-gray-6">理想间隔 <span class="text-gray-11 font-medium">7天</span></div>
<div class="text-gray-6">本年充值 <span class="text-success font-medium">3次</span></div>
</div>
''' + coach_row(COACHES_B) + '''
</a>
<a href="customer-detail.html" class="block bg-white rounded-2xl p-4 shadow-sm customer-card">
<div class="flex items-center gap-2 mb-2">
''' + avatar("orange-400","amber-500","") + '''
<div class="flex-1 min-w-0">
<span class="font-semibold text-gray-13">郑女士</span>
</div>
<span class="text-[10px] text-gray-6">5天前充值</span>
</div>
<div class="ml-11 mb-2 bg-gradient-to-r from-emerald-50 to-green-50 rounded-lg p-2.5 border border-emerald-100/50">
<div class="flex items-center justify-between">
<div>
<span class="text-lg font-bold text-success">+¥3,000</span>
<span class="text-[10px] text-gray-6 ml-1">充值</span>
</div>
<div class="text-right">
<div class="text-xs text-gray-6">充后余额</div>
<div class="text-sm font-bold text-gray-13">¥6,500</div>
</div>
</div>
</div>
<div class="flex flex-wrap gap-x-4 gap-y-1 text-xs ml-11 mb-2">
<div class="text-gray-6">最近到店 <span class="text-gray-11 font-medium">5天前</span></div>
<div class="text-gray-6">理想间隔 <span class="text-gray-11 font-medium">10天</span></div>
<div class="text-gray-6">本年充值 <span class="text-success font-medium">2次</span></div>
</div>
''' + coach_row(COACHES_C) + '''
</a>
</div>
'''
# ══════════════════════════════════════════════════════════
# 维度5: 最高消费 近60天 — 消费金额突出 + 排名徽章
# ══════════════════════════════════════════════════════════
DIM_SPEND60 = '''
<!-- ==================== 最高消费 近60天 ==================== -->
<div id="dim-spend60" class="dim-container p-4 pt-1 space-y-3">
<a href="customer-detail.html" class="block bg-white rounded-2xl p-4 shadow-sm customer-card">
<div class="flex items-center justify-between mb-2">
<div class="flex items-center gap-2">
''' + avatar("pink-400","rose-500","") + '''
<span class="font-semibold text-gray-13">李女士</span>
<span class="w-5 h-5 bg-gradient-to-br from-amber-400 to-orange-500 rounded-full flex items-center justify-center text-white text-[10px] font-bold">1</span>
</div>
</div>
<!-- 消费金额突出 -->
<div class="ml-11 mb-2">
<div class="flex items-baseline gap-1">
<span class="text-2xl font-bold text-warning">¥12,800</span>
<span class="text-[10px] text-gray-6">近60天消费</span>
</div>
<div class="grid grid-cols-3 gap-2 mt-2 text-center">
<div class="bg-gray-50 rounded-lg py-1.5">
<p class="text-xs font-bold text-gray-13">18次</p>
<p class="text-[10px] text-gray-6">到店</p>
</div>
<div class="bg-gray-50 rounded-lg py-1.5">
<p class="text-xs font-bold text-gray-13">¥711</p>
<p class="text-[10px] text-gray-6">次均消费</p>
</div>
<div class="bg-gray-50 rounded-lg py-1.5">
<p class="text-xs font-bold text-success">¥8,200</p>
<p class="text-[10px] text-gray-6">余额</p>
</div>
</div>
</div>
''' + coach_row(COACHES_A) + '''
</a>
<a href="customer-detail.html" class="block bg-white rounded-2xl p-4 shadow-sm customer-card">
<div class="flex items-center justify-between mb-2">
<div class="flex items-center gap-2">
''' + avatar("amber-400","orange-500","") + '''
<span class="font-semibold text-gray-13">王先生</span>
<span class="w-5 h-5 bg-gradient-to-br from-gray-300 to-gray-400 rounded-full flex items-center justify-center text-white text-[10px] font-bold">2</span>
</div>
</div>
<div class="ml-11 mb-2">
<div class="flex items-baseline gap-1">
<span class="text-2xl font-bold text-warning">¥9,500</span>
<span class="text-[10px] text-gray-6">近60天消费</span>
</div>
<div class="grid grid-cols-3 gap-2 mt-2 text-center">
<div class="bg-gray-50 rounded-lg py-1.5">
<p class="text-xs font-bold text-gray-13">12次</p>
<p class="text-[10px] text-gray-6">到店</p>
</div>
<div class="bg-gray-50 rounded-lg py-1.5">
<p class="text-xs font-bold text-gray-13">¥792</p>
<p class="text-[10px] text-gray-6">次均消费</p>
</div>
<div class="bg-gray-50 rounded-lg py-1.5">
<p class="text-xs font-bold text-success">¥5,000</p>
<p class="text-[10px] text-gray-6">余额</p>
</div>
</div>
</div>
''' + coach_row(COACHES_H) + '''
</a>
</div>
'''
# ══════════════════════════════════════════════════════════
# 维度6: 最频繁 近60天 — 到店天数突出 + 频率柱状图
# ══════════════════════════════════════════════════════════
DIM_FREQ60 = '''
<!-- ==================== 最频繁 近60天 ==================== -->
<div id="dim-freq60" class="dim-container p-4 pt-1 space-y-3">
<a href="customer-detail.html" class="block bg-white rounded-2xl p-4 shadow-sm customer-card">
<div class="flex items-center justify-between mb-2">
<div class="flex items-center gap-2">
''' + avatar("blue-400","indigo-500","") + '''
<span class="font-semibold text-gray-13">张先生</span>
</div>
<div class="text-right shrink-0">
<div class="text-primary font-bold text-lg">18<span class="text-xs font-normal text-gray-6">天</span></div>
<div class="text-[10px] text-gray-6 -mt-0.5">60天到店</div>
</div>
</div>
<!-- 频率可视化:简易柱状图 -->
<div class="ml-11 mb-2">
<div class="flex items-end gap-0.5 h-6">
<div class="flex-1 bg-primary/20 rounded-t" style="height:60%"></div>
<div class="flex-1 bg-primary/30 rounded-t" style="height:80%"></div>
<div class="flex-1 bg-primary/40 rounded-t" style="height:50%"></div>
<div class="flex-1 bg-primary/50 rounded-t" style="height:100%"></div>
<div class="flex-1 bg-primary/40 rounded-t" style="height:70%"></div>
<div class="flex-1 bg-primary/60 rounded-t" style="height:90%"></div>
<div class="flex-1 bg-primary/30 rounded-t" style="height:40%"></div>
<div class="flex-1 bg-primary/50 rounded-t" style="height:75%"></div>
</div>
<div class="flex items-center justify-between text-[10px] text-gray-5 mt-0.5">
<span>8周前</span>
<span>本周</span>
</div>
</div>
<div class="flex flex-wrap gap-x-4 gap-y-1 text-xs ml-11 mb-2">
<div class="text-gray-6">平均间隔 <span class="text-primary font-medium">3.3天</span></div>
<div class="text-gray-6">60天消费 <span class="text-gray-11 font-medium">¥8,600</span></div>
<div class="text-gray-6">余额 <span class="text-gray-11 font-medium">¥4,200</span></div>
</div>
''' + coach_row(COACHES_F) + '''
</a>
<a href="customer-detail.html" class="block bg-white rounded-2xl p-4 shadow-sm customer-card">
<div class="flex items-center justify-between mb-2">
<div class="flex items-center gap-2">
''' + avatar("purple-400","violet-500","") + '''
<span class="font-semibold text-gray-13">陈先生</span>
</div>
<div class="text-right shrink-0">
<div class="text-primary font-bold text-lg">15<span class="text-xs font-normal text-gray-6">天</span></div>
<div class="text-[10px] text-gray-6 -mt-0.5">60天到店</div>
</div>
</div>
<div class="ml-11 mb-2">
<div class="flex items-end gap-0.5 h-6">
<div class="flex-1 bg-primary/20 rounded-t" style="height:40%"></div>
<div class="flex-1 bg-primary/30 rounded-t" style="height:60%"></div>
<div class="flex-1 bg-primary/40 rounded-t" style="height:70%"></div>
<div class="flex-1 bg-primary/30 rounded-t" style="height:50%"></div>
<div class="flex-1 bg-primary/50 rounded-t" style="height:80%"></div>
<div class="flex-1 bg-primary/40 rounded-t" style="height:65%"></div>
<div class="flex-1 bg-primary/60 rounded-t" style="height:90%"></div>
<div class="flex-1 bg-primary/50 rounded-t" style="height:70%"></div>
</div>
<div class="flex items-center justify-between text-[10px] text-gray-5 mt-0.5">
<span>8周前</span>
<span>本周</span>
</div>
</div>
<div class="flex flex-wrap gap-x-4 gap-y-1 text-xs ml-11 mb-2">
<div class="text-gray-6">平均间隔 <span class="text-primary font-medium">4天</span></div>
<div class="text-gray-6">60天消费 <span class="text-gray-11 font-medium">¥6,200</span></div>
<div class="text-gray-6">余额 <span class="text-gray-11 font-medium">¥7,800</span></div>
</div>
''' + coach_row(COACHES_J) + '''
</a>
</div>
'''
# ══════════════════════════════════════════════════════════
# 维度7: 最近到店 — 突出"X天前"大字 + 新鲜度色彩
# ══════════════════════════════════════════════════════════
DIM_RECENT = '''
<!-- ==================== 最近到店 ==================== -->
<div id="dim-recent" class="dim-container p-4 pt-1 space-y-3">
<a href="customer-detail.html" class="block bg-white rounded-2xl p-4 shadow-sm customer-card">
<div class="flex items-center gap-2 mb-2">
''' + avatar("green-400","emerald-500","") + '''
<div class="flex-1 min-w-0">
<span class="font-semibold text-gray-13">刘先生</span>
</div>
<!-- 新鲜度大字 -->
<div class="flex items-baseline gap-0.5 shrink-0">
<span class="text-2xl font-bold text-success">1</span>
<span class="text-xs text-gray-6">天前到店</span>
</div>
</div>
<div class="ml-11 mb-2">
<!-- 新鲜度条 -->
<div class="flex items-center gap-2 mb-1.5">
<div class="flex-1 h-2 bg-gray-100 rounded-full overflow-hidden">
<div class="h-full rounded-full bg-gradient-to-r from-success to-emerald-300" style="width:95%"></div>
</div>
<span class="text-[10px] text-success font-medium shrink-0">极新鲜</span>
</div>
<div class="flex flex-wrap gap-x-4 gap-y-1 text-xs">
<div class="text-gray-6">理想间隔 <span class="text-gray-11 font-medium">7天</span></div>
<div class="text-gray-6">60天到店 <span class="text-gray-11 font-medium">12天</span></div>
<div class="text-gray-6">余额 <span class="text-gray-11 font-medium">¥9,200</span></div>
</div>
</div>
''' + coach_row(COACHES_H) + '''
</a>
<a href="customer-detail.html" class="block bg-white rounded-2xl p-4 shadow-sm customer-card">
<div class="flex items-center gap-2 mb-2">
''' + avatar("cyan-400","teal-500","") + '''
<div class="flex-1 min-w-0">
<span class="font-semibold text-gray-13">周先生</span>
</div>
<div class="flex items-baseline gap-0.5 shrink-0">
<span class="text-2xl font-bold text-success">2</span>
<span class="text-xs text-gray-6">天前到店</span>
</div>
</div>
<div class="ml-11 mb-2">
<div class="flex items-center gap-2 mb-1.5">
<div class="flex-1 h-2 bg-gray-100 rounded-full overflow-hidden">
<div class="h-full rounded-full bg-gradient-to-r from-success to-emerald-300" style="width:85%"></div>
</div>
<span class="text-[10px] text-success font-medium shrink-0">很新鲜</span>
</div>
<div class="flex flex-wrap gap-x-4 gap-y-1 text-xs">
<div class="text-gray-6">理想间隔 <span class="text-gray-11 font-medium">10天</span></div>
<div class="text-gray-6">60天到店 <span class="text-gray-11 font-medium">8天</span></div>
<div class="text-gray-6">余额 <span class="text-gray-11 font-medium">¥5,500</span></div>
</div>
</div>
''' + coach_row(COACHES_I) + '''
</a>
</div>
'''
# ══════════════════════════════════════════════════════════
# 维度8: 最专一 — 助教关系优先 + 关系指数条
# ══════════════════════════════════════════════════════════
DIM_LOYAL = '''
<!-- ==================== 最专一 ==================== -->
<div id="dim-loyal" class="dim-container p-4 pt-1 space-y-3">
<a href="customer-detail.html" class="block bg-white rounded-2xl p-4 shadow-sm customer-card">
<div class="flex items-center justify-between mb-2">
<div class="flex items-center gap-2">
''' + avatar("teal-400","cyan-500","") + '''
<span class="font-semibold text-gray-13">孙先生</span>
</div>
<div class="text-right shrink-0">
<div class="text-primary font-bold">0.81</div>
<div class="text-[10px] text-gray-6 -mt-0.5">专一指数</div>
</div>
</div>
<!-- 助教关系指数条 -->
<div class="ml-11 mb-2 space-y-1.5">
<div class="flex items-center gap-2">
<span class="text-xs font-medium text-gray-13 w-8 shrink-0">小燕</span>
<div class="flex-1 h-2 bg-gray-100 rounded-full overflow-hidden">
<div class="h-full rounded-full bg-gradient-to-r from-error to-pink-400" style="width:95%"></div>
</div>
<span class="text-[10px] text-gray-9 font-medium w-7 text-right">0.95</span>
<span class="assistant-badge assistant-badge-follow text-[9px]">跟</span>
</div>
<div class="flex items-center gap-2">
<span class="text-xs font-medium text-gray-13 w-8 shrink-0">泡芙</span>
<div class="flex-1 h-2 bg-gray-100 rounded-full overflow-hidden">
<div class="h-full rounded-full bg-gradient-to-r from-warning to-amber-400" style="width:68%"></div>
</div>
<span class="text-[10px] text-gray-9 font-medium w-7 text-right">0.68</span>
</div>
<div class="flex items-center gap-2">
<span class="text-xs font-medium text-gray-7 w-8 shrink-0">Amy</span>
<div class="flex-1 h-2 bg-gray-100 rounded-full overflow-hidden">
<div class="h-full rounded-full bg-gray-300" style="width:32%"></div>
</div>
<span class="text-[10px] text-gray-5 font-medium w-7 text-right">0.32</span>
<span class="assistant-badge assistant-badge-drop text-[9px]">弃</span>
</div>
</div>
<div class="flex flex-wrap gap-x-4 gap-y-1 text-xs ml-11">
<div class="text-gray-6">最近到店 <span class="text-gray-11 font-medium">6天前</span></div>
<div class="text-gray-6">60天到店 <span class="text-gray-11 font-medium">10天</span></div>
<div class="text-gray-6">余额 <span class="text-gray-11 font-medium">¥7,200</span></div>
</div>
</a>
<a href="customer-detail.html" class="block bg-white rounded-2xl p-4 shadow-sm customer-card">
<div class="flex items-center justify-between mb-2">
<div class="flex items-center gap-2">
''' + avatar("rose-400","pink-500","") + '''
<span class="font-semibold text-gray-13">赵女士</span>
</div>
<div class="text-right shrink-0">
<div class="text-primary font-bold">0.90</div>
<div class="text-[10px] text-gray-6 -mt-0.5">专一指数</div>
</div>
</div>
<div class="ml-11 mb-2 space-y-1.5">
<div class="flex items-center gap-2">
<span class="text-xs font-medium text-gray-13 w-8 shrink-0">Amy</span>
<div class="flex-1 h-2 bg-gray-100 rounded-full overflow-hidden">
<div class="h-full rounded-full bg-gradient-to-r from-error to-pink-400" style="width:88%"></div>
</div>
<span class="text-[10px] text-gray-9 font-medium w-7 text-right">0.88</span>
</div>
<div class="flex items-center gap-2">
<span class="text-xs font-medium text-gray-13 w-8 shrink-0">泡芙</span>
<div class="flex-1 h-2 bg-gray-100 rounded-full overflow-hidden">
<div class="h-full rounded-full bg-gradient-to-r from-warning to-amber-400" style="width:72%"></div>
</div>
<span class="text-[10px] text-gray-9 font-medium w-7 text-right">0.72</span>
</div>
</div>
<div class="flex flex-wrap gap-x-4 gap-y-1 text-xs ml-11">
<div class="text-gray-6">最近到店 <span class="text-gray-11 font-medium">4天前</span></div>
<div class="text-gray-6">60天到店 <span class="text-gray-11 font-medium">14天</span></div>
<div class="text-gray-6">余额 <span class="text-gray-11 font-medium">¥12,000</span></div>
</div>
</a>
</div>
'''
# ══════════════════════════════════════════════════════════
# 执行替换
# ══════════════════════════════════════════════════════════
ALL_DIMS = DIM_RECALL + DIM_POTENTIAL + DIM_BALANCE + DIM_RECHARGE + DIM_SPEND60 + DIM_FREQ60 + DIM_RECENT + DIM_LOYAL
# 定位:从第一个 dim-container 到悬浮助手按钮之前
pattern = re.compile(
r'(<!-- ={5,} 最应召回.*?</div>\s*\n)' # 不用这个
r'|'
r'(<div id="dim-recall".*?)(?=\s*<!-- 悬浮助手按钮)',
re.DOTALL
)
# 更简单的方式:找到所有 dim-container 块并替换
start_marker = ' <!-- ==================== 最应召回(默认) ==================== -->'
end_marker = ' <!-- 悬浮助手按钮 -->'
start_idx = html.find(start_marker)
end_idx = html.find(end_marker)
if start_idx == -1 or end_idx == -1:
# 尝试备选标记
start_marker2 = '<div id="dim-recall"'
end_marker2 = '<!-- 悬浮助手按钮'
start_idx = html.find(start_marker2)
end_idx = html.find(end_marker2)
if start_idx == -1 or end_idx == -1:
print(f"ERROR: 找不到替换标记 start={start_idx} end={end_idx}")
import sys; sys.exit(1)
# 回退到行首
start_idx = html.rfind('\n', 0, start_idx) + 1
new_html = html[:start_idx] + ALL_DIMS + '\n' + html[end_idx:]
TARGET.write_text(new_html, encoding="utf-8")
print(f"OK: board-customer.html 已重写,共 {len(new_html)} 字符")