v1.4.2 — 自动归类取代手动选择板块

- 后端关键词自动归类立志/责善/勤学到六板块
- 移除DOM板块选择器,简化UI
- 蓝图面板展示各板块立志·责善·勤学统计+详情列表
- 旧数据自动兼容、新数据无需手动选分类
This commit is contained in:
mac
2026-06-04 15:58:56 +08:00
parent be9f10e968
commit 03745e19c3
4 changed files with 128 additions and 45 deletions

88
app.py
View File

@@ -77,7 +77,30 @@ def compute_stats():
total_evening = 0
total_study = 0
calendar = {}
all_morning_items = [] # 收集所有立志项用于蓝图统计
all_morning_items = []
all_evening_items = []
all_study_items = []
# 关键词 → 板块 自动归类规则
PILLAR_KEYWORDS = {
'医药营销': ['科普','科研','学术会议','学术','会议','患者管理','临床推广','临床','药企','处方','KOL','代表','拜访','荣昌','恒瑞','信达','鲁银','OPC','项目','标杆','客户'],
'医疗服务': ['诊疗','治疗','医生','医院','科室','手术','门诊','患者','','护理','诊断','影像','检验'],
'医疗支付': ['医保','商保','理赔','支付','保险','费用','报销','商业保险','保单'],
'AI 智能': ['AI','数字人','智能','算法','自动化','平台','系统','网站','开发','代码','程序','模型'],
'公司治理': ['团队','组织','管理','招聘','HR','制度','流程','财务','考核','KPI','规划','人才','架构','预算'],
'个人修养': ['早起','睡觉','俯卧撑','运动','冥想','阅读','复盘','写作','习惯','修身','立志','责善','改过','勤学'],
}
def classify_auto(text):
"""根据文本内容自动归类"""
if not text or not text.strip():
return ''
text_lower = text.strip()
for pillar, keywords in PILLAR_KEYWORDS.items():
for kw in keywords:
if kw in text_lower:
return pillar
return '' # 未匹配
for row in rows:
d = row['date']
@@ -86,12 +109,36 @@ def compute_stats():
evening = data.get('evening', [])
study = data.get('study', [])
# 收集 morning items
# 收集并自动归类
for mi in morning:
if isinstance(mi, dict) and (mi.get('text', '') or '').strip():
all_morning_items.append(mi)
elif isinstance(mi, str) and mi.strip():
all_morning_items.append({'text': mi, 'pillar': ''})
text = mi if isinstance(mi, str) else mi.get('text', '')
if isinstance(text, str) and text.strip():
auto_pillar = mi.get('pillar', '') if isinstance(mi, dict) else ''
if not auto_pillar:
auto_pillar = classify_auto(text)
all_morning_items.append({'text': text.strip(), 'pillar': auto_pillar})
for ei in evening:
if isinstance(ei, dict):
m = (ei.get('mistake') or '').strip()
imp = (ei.get('improvement') or '').strip()
if m or imp:
pillar = ei.get('pillar', '') or classify_auto(m + ' ' + imp)
all_evening_items.append({'mistake': m, 'improvement': imp, 'pillar': pillar})
elif isinstance(ei, str) and ei.strip():
all_evening_items.append({'mistake': ei.strip(), 'improvement': '', 'pillar': classify_auto(ei)})
for si in study:
name = si.get('name', '') if isinstance(si, dict) else str(si)
if name.strip():
pillar = si.get('pillar', '') if isinstance(si, dict) else ''
if not pillar:
pillar = classify_auto(name)
all_study_items.append({
'name': name.strip(),
'done': si.get('done', False) if isinstance(si, dict) else False,
'pillar': pillar
})
morning_count = sum(1 for x in morning if (
isinstance(x, str) and x.strip() or
@@ -114,11 +161,38 @@ def compute_stats():
# day_score = 60 + extra * 5 (不在此处使用,仅用于日历状态)
calendar[d] = 'pass' if all_three else 'fail'
# 构建板块统计
pillars = ['医疗服务','医药营销','医疗支付','AI 智能','公司治理','个人修养']
pillar_breakdown = {}
for p in pillars:
pillar_breakdown[p] = {
'morning': 0, 'evening': 0, 'study': 0,
'morning_items': [], 'evening_items': [], 'study_items': []
}
for mi in all_morning_items:
p = mi['pillar']
if p in pillar_breakdown:
pillar_breakdown[p]['morning'] += 1
pillar_breakdown[p]['morning_items'].append(mi)
for ei in all_evening_items:
p = ei['pillar']
if p in pillar_breakdown:
pillar_breakdown[p]['evening'] += 1
pillar_breakdown[p]['evening_items'].append(ei)
for si in all_study_items:
p = si['pillar']
if p in pillar_breakdown:
pillar_breakdown[p]['study'] += 1
pillar_breakdown[p]['study_items'].append(si)
return dict(
total_days=total_days, total_morning=total_morning,
total_evening=total_evening, total_study=total_study,
calendar=calendar,
morning_items=all_morning_items
morning_items=all_morning_items,
evening_items=all_evening_items,
study_items=all_study_items,
pillar_breakdown=pillar_breakdown
)