studytime-analysis: 新增留存状态判定 — 最近14天无完课标记为流失,否则正常

This commit is contained in:
xiaoban 2026-05-24 10:44:49 +08:00
parent ed6c864197
commit cde77e762d
2 changed files with 24 additions and 4 deletions

View File

@ -7,4 +7,4 @@ lark_wiki_operate_as_bot 2a37701f568849f03eb46dd938baeda171380fe252b698ac8bda69c
vala_git_workspace_backup 4cf352bec88fe84af065ba1ffcbb06647b77df0e01860faaf0bca9fd64b968ec
cron-schedule b1879fa59d60e3d99cea1138674f7abac84a4aecd32743b801d41bfd6ed7181d
study-analysis 33217dc132073ecd47b921800834f6df89494da9e7708fa90f15b3de7742e37f
studytime-analysis 042178f9f7e97eeef366fd619403f4d0c8e0dce290abf17af662dddfa67c4e83
studytime-analysis a3b2570583717cf5af2720f047de23752ee42cba8ff4a3f859d216e0580026ae

View File

@ -13,7 +13,7 @@ import sys
import psycopg2
import psycopg2.extras
import pymysql
from datetime import datetime, timedelta
from datetime import datetime, timedelta, timezone
from collections import defaultdict, OrderedDict
# ── 配置 ──────────────────────────────────────────────
@ -148,6 +148,21 @@ def fetch_role_info(role_id):
}
def check_retention(records, cutoff_days=14):
"""
检查角色留存状态
- 最近 cutoff_days 天内有完课记录 "正常"
- 否则 "流失"
当无任何完课记录时返回 "无完课记录"
"""
if not records:
return "无完课记录"
# 用本地时间比较(与 PG 存储时区一致 UTC+8
cutoff = datetime.now() - timedelta(days=cutoff_days)
has_recent = any(r["updated_at"].replace(tzinfo=None) >= cutoff for r in records)
return "正常" if has_recent else "流失"
def fetch_completion_records(role_id):
"""查询指定角色全部完课记录(包含寒暑假)"""
params = {}
@ -321,7 +336,7 @@ def analyze_weekly_trend(records):
# ── 输出格式化 ────────────────────────────────────────
def format_report(role_id, role_info, all_records, non_holiday_records, holiday_count, day_counts, weekday_periods, weeks_data, analysis):
def format_report(role_id, role_info, retention_status, all_records, non_holiday_records, holiday_count, day_counts, weekday_periods, weeks_data, analysis):
"""生成 Markdown 格式分析报告
Args:
@ -352,6 +367,8 @@ def format_report(role_id, role_info, all_records, non_holiday_records, holiday_
lines.append(f"| 年龄 | {role_info['age']} 岁 |")
if role_info['phone_tail']:
lines.append(f"| 账号手机号后4位 | {role_info['phone_tail']} |")
if retention_status:
lines.append(f"| 最近留存状态 | {retention_status} |")
lines.append(f"")
# ── 数据概况 ──
@ -566,12 +583,15 @@ def main():
# 角色基本信息MySQL
role_info = fetch_role_info(role_id)
# 留存状态判定
retention_status = check_retention(all_records)
# 一周分布分析:仅用非寒暑假数据
day_counts, weekday_periods = analyze_weekly_distribution(non_holiday_records)
# 跨周趋势分析:用全部数据
weeks_data, analysis = analyze_weekly_trend(all_records)
report = format_report(role_id, role_info, all_records, non_holiday_records, holiday_count, day_counts, weekday_periods, weeks_data, analysis)
report = format_report(role_id, role_info, retention_status, all_records, non_holiday_records, holiday_count, day_counts, weekday_periods, weeks_data, analysis)
print(report)