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

293 lines
13 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
board-coach.html: 将单一助教列表替换为按筛选分类的多个 dim-container
并添加 JS 切换逻辑。同时修复 board-customer.html 各维度指数标签。
"""
import re
# ============================================================
# 1. board-coach.html — 多维度切换
# ============================================================
filepath = "docs/h5_ui/pages/board-coach.html"
with open(filepath, "r", encoding="utf-8") as f:
content = f.read()
# 定位旧的助教列表 + 隐藏样式区域
old_start = ' <!-- 助教列表'
old_end = ' <!-- 悬浮助手按钮 -->'
start_idx = content.index(old_start)
end_idx = content.index(old_end)
# 6 位助教的基础信息(复用)
coaches = [
("", "小燕", "from-blue-400 to-indigo-500", "星级", "bg-gradient-to-r from-amber-400 to-orange-400 text-white", "中🎱", "bg-primary/10 text-primary", ""),
("", "泡芙", "from-green-400 to-emerald-500", "高级", "bg-gradient-to-r from-purple-400 to-violet-400 text-white", "斯诺克", "bg-success/10 text-success", ""),
("A", "Amy", "from-pink-400 to-rose-500", "星级", "bg-gradient-to-r from-amber-400 to-orange-400 text-white", "中🎱", "bg-primary/10 text-primary", '<span class="px-1.5 py-0.5 bg-success/10 text-success text-xs rounded flex-shrink-0">斯诺克</span>'),
("M", "Mia", "from-amber-400 to-orange-500", "中级", "bg-gradient-to-r from-blue-400 to-indigo-400 text-white", "麻将", "bg-warning/10 text-warning", ""),
("", "糖糖", "from-purple-400 to-violet-500", "初级", "bg-gradient-to-r from-gray-400 to-gray-500 text-white", "中🎱", "bg-primary/10 text-primary", ""),
("", "露露", "from-cyan-400 to-teal-500", "中级", "bg-gradient-to-r from-blue-400 to-indigo-400 text-white", "团建", "bg-error/10 text-error", ""),
]
clients = [
("💖 王先生", "💖 李女士", "💛 赵总"),
("💖 陈先生", "💛 刘女士", "💛 黄总"),
("💖 张先生", "💛 周女士", "💛 吴总"),
("💛 赵先生", "💛 吴女士", "💛 孙总"),
("💛 钱先生", "💛 孙女士", "💛 周总"),
("💛 郑先生", "💛 冯女士", "💛 陈总"),
]
def coach_header(i):
"""生成助教卡片的头像+昵称+标签行(通用)"""
ch, name, grad, level, lvl_cls, skill, sk_cls, extra = coaches[i]
return f''' <div class="w-11 h-11 rounded-full bg-gradient-to-br {grad} flex items-center justify-center flex-shrink-0">
<span class="text-white font-semibold text-base">{ch}</span>
</div>
<div class="flex-1 min-w-0">
<div class="flex items-center gap-1.5 flex-wrap">
<span class="text-base font-semibold text-gray-13">{name}</span>
<span class="px-1.5 py-0.5 {lvl_cls} text-xs rounded flex-shrink-0">{level}</span>
<span class="px-1.5 py-0.5 {sk_cls} text-xs rounded flex-shrink-0">{skill}</span>
{extra}
</div>'''
def coach_row2(i, right_html):
"""生成第二行:客户 + 右侧数据"""
c1, c2, c3 = clients[i]
return f''' <div class="flex items-center justify-between text-xs pt-2 border-t border-gray-100">
<div class="flex items-center gap-2 text-gray-6 truncate">
<span>{c1}</span><span>{c2}</span><span>{c3}</span>
</div>
{right_html}
</div>'''
# 定档业绩数据
perf_data = [
("86.2", "13.8", "92.0"),
("72.5", "7.5", "78.0"),
("68.0", "32.0", "72.5"),
("55.0", "5.0", ""),
("42.0", "达标", "45.0"),
("38.0", "22.0", ""),
]
perf_levels = [
("星级", "王牌"),
("高级", "星级"),
("星级", "王牌"),
("中级", "高级"),
("初级", "中级"),
("中级", "高级"),
]
def make_perf_card(i):
"""定档业绩最高/最低 卡片"""
h, need, pre = perf_data[i]
cur, nxt = perf_levels[i]
if need == "达标":
data_line = f''' <div class="mt-1 flex items-center gap-2 text-xs">
<span class="font-bold text-success text-sm">{h}h</span>
<span class="text-success font-medium">✅ 已达标</span>
</div>'''
else:
data_line = f''' <div class="mt-1 flex items-center gap-2 text-xs">
<span class="font-bold text-primary text-sm">{h}h</span>
<span class="text-gray-7">下一档还需 <span class="text-warning font-medium">{need}h</span></span>
</div>'''
pre_html = f'<span class="text-gray-5">|</span>\n <span>折前 <b class="text-gray-10">{pre}h</b></span>' if pre else ''
right = f'''<div class="flex items-center gap-2 text-gray-7 flex-shrink-0">
<span>定档 <b class="text-gray-10">{h}h</b></span>
{pre_html}
</div>'''
return f''' <a href="coach-detail.html" class="block bg-white rounded-2xl p-4 shadow-sm coach-card">
<div class="flex items-start gap-3 mb-2.5">
{coach_header(i)}
{data_line}
</div>
</div>
{coach_row2(i, right)}
</a>'''
# 工资数据
salary_data = ["¥12,680", "¥10,200", "¥9,800", "¥7,500", "¥6,200", "¥5,100"]
def make_salary_card(i):
"""工资最高/最低 卡片"""
sal = salary_data[i]
h = perf_data[i][0]
pre = perf_data[i][2]
pre_html = f'<span class="text-gray-5">|</span>\n <span>折前 <b class="text-gray-10">{pre}h</b></span>' if pre else ''
right = f'''<div class="flex items-center gap-2 text-gray-7 flex-shrink-0">
<span>定档 <b class="text-gray-10">{h}h</b></span>
{pre_html}
</div>'''
return f''' <a href="coach-detail.html" class="block bg-white rounded-2xl p-4 shadow-sm coach-card">
<div class="flex items-start gap-3 mb-2.5">
{coach_header(i)}
<div class="mt-1 flex items-center gap-2">
<span class="text-lg font-semibold text-gray-13">{sal}</span>
<span class="px-1.5 py-0.5 bg-warning/10 text-warning text-xs rounded">预估</span>
</div>
</div>
</div>
{coach_row2(i, right)}
</a>'''
# 客源储值数据
sv_balance = ["¥45,200", "¥38,600", "¥32,100", "¥28,500", "¥22,000", "¥18,300"]
sv_consume = ["¥8,600", "¥6,200", "¥5,800", "¥4,100", "¥3,500", "¥2,800"]
def make_sv_card(i):
"""客源储值最高 卡片"""
right = f'''<div class="flex items-center gap-2 text-gray-7 flex-shrink-0">
<span>周期消耗 <b class="text-gray-10">{sv_consume[i]}</b></span>
</div>'''
return f''' <a href="coach-detail.html" class="block bg-white rounded-2xl p-4 shadow-sm coach-card">
<div class="flex items-start gap-3 mb-2.5">
{coach_header(i)}
<div class="mt-1">
<span class="text-lg font-semibold text-gray-13">{sv_balance[i]}</span>
<span class="text-xs text-gray-6 ml-1">客户储值余额</span>
</div>
</div>
</div>
{coach_row2(i, right)}
</a>'''
# 任务完成数据
task_counts = [(32, 18), (28, 15), (25, 14), (20, 12), (18, 10), (15, 9)]
def make_task_card(i):
"""任务完成最多 卡片"""
tc, cc = task_counts[i]
h = perf_data[i][0]
pre = perf_data[i][2]
pre_html = f'<span class="text-gray-5">|</span>\n <span>折前 <b class="text-gray-10">{pre}h</b></span>' if pre else ''
right = f'''<div class="flex items-center gap-2 text-gray-7 flex-shrink-0">
<span>定档 <b class="text-gray-10">{h}h</b></span>
{pre_html}
</div>'''
return f''' <a href="coach-detail.html" class="block bg-white rounded-2xl p-4 shadow-sm coach-card">
<div class="flex items-start gap-3 mb-2.5">
{coach_header(i)}
<div class="mt-1 flex items-center gap-3">
<div><span class="text-lg font-semibold text-primary">{tc}</span><span class="text-xs text-gray-6 ml-0.5">个任务</span></div>
<div class="w-px h-4 bg-gray-3"></div>
<div><span class="text-lg font-semibold text-gray-13">{cc}</span><span class="text-xs text-gray-6 ml-0.5">位客户</span></div>
</div>
</div>
</div>
{coach_row2(i, right)}
</a>'''
# 生成各维度容器
dims = []
# 定档业绩最高
cards = "\n\n".join(make_perf_card(i) for i in range(6))
dims.append(f''' <!-- ====== 定档业绩最高/最低 ====== -->
<div id="dim-perf" class="dim-container active p-4 space-y-3">
{cards}
</div>''')
# 工资最高
cards = "\n\n".join(make_salary_card(i) for i in range(6))
dims.append(f''' <!-- ====== 工资最高/最低 ====== -->
<div id="dim-salary" class="dim-container p-4 space-y-3">
{cards}
</div>''')
# 客源储值最高
cards = "\n\n".join(make_sv_card(i) for i in range(6))
dims.append(f''' <!-- ====== 客源储值最高 ====== -->
<div id="dim-sv" class="dim-container p-4 space-y-3">
{cards}
</div>''')
# 任务完成最多
cards = "\n\n".join(make_task_card(i) for i in range(6))
dims.append(f''' <!-- ====== 任务完成最多 ====== -->
<div id="dim-task" class="dim-container p-4 space-y-3">
{cards}
</div>''')
new_section = "\n\n".join(dims) + "\n\n"
content = content[:start_idx] + new_section + content[end_idx:]
# 添加 dim-container CSS如果不存在
if '.dim-container' not in content:
content = content.replace(
'.coach-card:active {',
'.dim-container { display: none; }\n .dim-container.active { display: block; }\n .coach-card:active {'
)
# 替换 selectSort JS 函数,添加维度切换逻辑
old_select_sort = ''' function selectSort(value) {
document.getElementById('sortLabel').textContent = value;
closeAllFilters();
}'''
new_select_sort = ''' function selectSort(value) {
document.getElementById('sortLabel').textContent = value;
closeAllFilters();
// 切换维度容器
var dimMap = {
'定档业绩最高': 'dim-perf',
'定档业绩最低': 'dim-perf',
'工资最高': 'dim-salary',
'工资最低': 'dim-salary',
'客源储值最高': 'dim-sv',
'任务完成最多': 'dim-task'
};
document.querySelectorAll('.dim-container').forEach(function(el) { el.classList.remove('active'); });
var id = dimMap[value];
if (id) document.getElementById(id).classList.add('active');
}'''
content = content.replace(old_select_sort, new_select_sort)
with open(filepath, "w", encoding="utf-8") as f:
f.write(content)
print("OK — board-coach.html: 4 dim-containers + JS 切换")
# ============================================================
# 2. board-customer.html — 修正各维度的指数标签
# ============================================================
filepath2 = "docs/h5_ui/pages/board-customer.html"
with open(filepath2, "r", encoding="utf-8") as f:
c2 = f.read()
# 最高余额维度:指数标签应该是"余额排名"而不是"消费潜力指数"
# 最频繁维度:应该是"到店频率"
# 最近到店:应该是"到店新鲜度"
# 最专一:应该是"专一指数"
# 最高消费近60天应该是"消费力指数"
replacements = [
# dim-balance 区域
('id="dim-balance"', '消费潜力指数', '余额排名'),
# dim-freq60 区域
('id="dim-freq60"', '消费潜力指数', '到店频率'),
# dim-recent 区域
('id="dim-recent"', '消费潜力指数', '到店新鲜度'),
# dim-loyal 区域
('id="dim-loyal"', '消费潜力指数', '专一指数'),
# dim-spend60 区域
('id="dim-spend60"', '消费潜力指数', '消费力指数'),
]
for dim_id, old_label, new_label in replacements:
# 找到该维度区域的起始位置
dim_start = c2.index(dim_id)
# 找到下一个维度或文件末尾
next_dim = c2.find('dim-container', dim_start + 50)
if next_dim == -1:
next_dim = len(c2)
# 在该区域内替换标签
section = c2[dim_start:next_dim]
section = section.replace(old_label, new_label)
c2 = c2[:dim_start] + section + c2[next_dim:]
with open(filepath2, "w", encoding="utf-8") as f:
f.write(c2)
print("OK — board-customer.html: 各维度指数标签已修正")