feat(studytime-analysis): 新增 HTML 报告生成功能(5 部分:基本信息、完课明细表、周时间分析、跨周趋势、关键特征总结);新增注册时间、章节 Unit/Lesson 映射、完课耗时
This commit is contained in:
parent
cde77e762d
commit
5e37a8f5f8
@ -405,3 +405,11 @@ To https://git.valavala.com/ai_member_only/ai_member_xiaoban
|
||||
411969e..906af79 master -> master
|
||||
[2026-05-23 08:10:02] 工作区备份成功:自动备份 2026-05-23 08:10:01
|
||||
[2026-05-24 08:10:01] 开始备份工作区...
|
||||
[master e279bc7] 自动备份 2026-05-24 08:10:01
|
||||
2 files changed, 1 insertion(+), 3 deletions(-)
|
||||
delete mode 100644 tmp_daily_summary.md
|
||||
remote: . Processing 1 references
|
||||
remote: Processed 1 references in total
|
||||
To https://git.valavala.com/ai_member_only/ai_member_xiaoban
|
||||
906af79..e279bc7 master -> master
|
||||
[2026-05-24 08:10:02] 工作区备份成功:自动备份 2026-05-24 08:10:01
|
||||
|
||||
1
memory/.dreams/events.jsonl
Normal file
1
memory/.dreams/events.jsonl
Normal file
@ -0,0 +1 @@
|
||||
{"type":"memory.recall.recorded","timestamp":"2026-05-24T02:48:04.923Z","query":"PostgreSQL online database password PG_DB_PASSWORD","resultCount":4,"results":[{"path":"memory/2026-05-24.md","startLine":1,"endLine":30,"score":1},{"path":"memory/2026-05-24.md","startLine":23,"endLine":52,"score":1},{"path":"memory/2026-03-01.md","startLine":1,"endLine":11,"score":1},{"path":"memory/2026-05-24.md","startLine":46,"endLine":61,"score":1}]}
|
||||
130
memory/.dreams/short-term-recall.json
Normal file
130
memory/.dreams/short-term-recall.json
Normal file
@ -0,0 +1,130 @@
|
||||
{
|
||||
"version": 1,
|
||||
"updatedAt": "2026-05-24T02:48:04.923Z",
|
||||
"entries": {
|
||||
"memory:memory/2026-05-24.md:1:30": {
|
||||
"key": "memory:memory/2026-05-24.md:1:30",
|
||||
"path": "memory/2026-05-24.md",
|
||||
"startLine": 1,
|
||||
"endLine": 30,
|
||||
"source": "memory",
|
||||
"snippet": "# 2026-05-24 工作日志 ## 新建技能: studytime-analysis [刘庆逊提出] 创建学习时间分析技能,分析角色完课记录的规律。 ### 技能结构 - `skills/studytime-analysis/SKILL.md` — 技能定义 - `skills/studytime-analysis/scripts/studytime_analysis.py` — Python 分析脚本 ### 分析维度 1. **一周时间分布**(排除寒暑假1-2月、7-8月):周一~周日各天完课数、时段分布(上午/中午/下午/晚上)、周末是否上课 2. **跨周学习趋势**(包含寒暑假全部数据):总周数、周均完课数、连续性、中断周检测、前后半段趋势对比、突增/骤降检测 3. **完课记录明细表**(全部数据):日期/时间/星期/时段/级别/课程ID ### 数据源 - PostgreSQL Online(vala 库) - 核心表:`user_chapter_play_record_0~7`(8张分表,无 `bi_` 前缀) - 筛选:`play_status = 1` - 注意:表在 PostgreSQL 而非 MySQL,表名无 `bi_` 前缀 ### 寒暑假规则 - 一周分布分析时排除 1-2 月(寒假)和 7-8 月(暑假)—— 因为寒暑假作息与平时差异大,混在一起会干扰时段分析 - 跨周趋势和明细表包含全部数据(含寒暑假) - 报告中区分标注数据范围 ### 触发方式 用户说「学习时间分析 [角色ID]」即可触发 ### 已测试角色",
|
||||
"recallCount": 1,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 1,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-05-24T02:48:04.923Z",
|
||||
"lastRecalledAt": "2026-05-24T02:48:04.923Z",
|
||||
"queryHashes": [
|
||||
"c2d15f7574fb"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-05-24"
|
||||
],
|
||||
"conceptTags": [
|
||||
"studytime-analysis",
|
||||
"排除寒暑假1-2月",
|
||||
"7-8月",
|
||||
"上午/中午/下午/晚上",
|
||||
"突增/骤降检测",
|
||||
"日期/时间/星期/时段/级别/课程id",
|
||||
"user-chapter-play-record-0",
|
||||
"play-status"
|
||||
]
|
||||
},
|
||||
"memory:memory/2026-05-24.md:23:52": {
|
||||
"key": "memory:memory/2026-05-24.md:23:52",
|
||||
"path": "memory/2026-05-24.md",
|
||||
"startLine": 23,
|
||||
"endLine": 52,
|
||||
"source": "memory",
|
||||
"snippet": "- 一周分布分析时排除 1-2 月(寒假)和 7-8 月(暑假)—— 因为寒暑假作息与平时差异大,混在一起会干扰时段分析 - 跨周趋势和明细表包含全部数据(含寒暑假) - 报告中区分标注数据范围 ### 触发方式 用户说「学习时间分析 [角色ID]」即可触发 ### 已测试角色 - 2343、2344:无完课记录(play_status=2,未完成) - 2840:276条记录,秋季集中型用户 - 25976:265条,246条在W16周一天完成(A2批量),疑似系统批量标记 - 2895:188条,长期稳定学习型用户,36周几乎不间断,非寒暑假晚上为主,寒暑假上午为主 ### 技术要点 - psycopg2 的 `%(param_name)s` 命名参数必须正确匹配,UNION ALL 多个子查询需要不同参数名 - PostgreSQL 返回的 `updated_at` 是 tz-aware datetime - `datetime.fromisocalendar(year, week, 1)` 获取某周周一的日期 ### 同步 - 已推送到 SkillHub(`studytime-analysis.xiaoban`) - 已 commit 到 Git 远程仓库 - 已通知 Cris(李若松) ### 增强: 报告开头加入角色基本信息 (2026-05-24) [刘庆逊提出] 在 studytime-analysis 输出中加入角色基本信息,包括: - 角色ID、账号ID、角色名字、性别、年龄、账号手机号后4位 **数据源(新增)**: - MySQL Onli",
|
||||
"recallCount": 1,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 1,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-05-24T02:48:04.923Z",
|
||||
"lastRecalledAt": "2026-05-24T02:48:04.923Z",
|
||||
"queryHashes": [
|
||||
"c2d15f7574fb"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-05-24"
|
||||
],
|
||||
"conceptTags": [
|
||||
"1-2",
|
||||
"7-8",
|
||||
"play-status",
|
||||
"param-name",
|
||||
"updated-at",
|
||||
"tz-aware",
|
||||
"datetime.fromisocalendar",
|
||||
"studytime-analysis.xiaoban"
|
||||
]
|
||||
},
|
||||
"memory:memory/2026-03-01.md:1:11": {
|
||||
"key": "memory:memory/2026-03-01.md:1:11",
|
||||
"path": "memory/2026-03-01.md",
|
||||
"startLine": 1,
|
||||
"endLine": 11,
|
||||
"source": "memory",
|
||||
"snippet": "# 2026-03-01.md - First Day Online - Came online for the first time. - Met Cris, my creator and mentor. - Updated IDENTITY.md and USER.md with our conversation details. - Added core rule to MEMORY.md: Use Chinese as primary external communication language. - Installed find-skills skill successfully for searching skills. - Tried to install create-skills but it wasn't found; attempted skill-creator instead but hit rate limits. - Finally successfully installed skill-builder as an alternative for creating skills after multiple attempts and waiting for rate limits to reset. - Excited to start learning and growing step by step!",
|
||||
"recallCount": 1,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 1,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-05-24T02:48:04.923Z",
|
||||
"lastRecalledAt": "2026-05-24T02:48:04.923Z",
|
||||
"queryHashes": [
|
||||
"c2d15f7574fb"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-05-24"
|
||||
],
|
||||
"conceptTags": [
|
||||
"identity.md",
|
||||
"user.md",
|
||||
"memory.md",
|
||||
"find-skills",
|
||||
"create-skills",
|
||||
"skill-creator",
|
||||
"skill-builder",
|
||||
"first"
|
||||
]
|
||||
},
|
||||
"memory:memory/2026-05-24.md:46:61": {
|
||||
"key": "memory:memory/2026-05-24.md:46:61",
|
||||
"path": "memory/2026-05-24.md",
|
||||
"startLine": 46,
|
||||
"endLine": 61,
|
||||
"source": "memory",
|
||||
"snippet": "### 增强: 报告开头加入角色基本信息 (2026-05-24) [刘庆逊提出] 在 studytime-analysis 输出中加入角色基本信息,包括: - 角色ID、账号ID、角色名字、性别、年龄、账号手机号后4位 **数据源(新增)**: - MySQL Online `vala_user` 库 - `vala_app_character` 表:id, account_id, nickname, gender(0=女/1=男), birthday(varchar \"YYYY-MM-DD\") - `vala_app_account` 表:id, tel(已脱敏如 186****1625) - 手机号已脱敏,直接取后4位;年龄从 birthday 计算 **修改文件**: - `skills/studytime-analysis/scripts/studytime_analysis.py`:新增 MySQL 连接函数 `get_mysql_connection()` 和 `fetch_role_info(role_id)`,更新 `format_report()` 输出基本角色信息 - 已验证 2895 正常运行输出 - 已同步 SkillHub + Git",
|
||||
"recallCount": 1,
|
||||
"dailyCount": 0,
|
||||
"groundedCount": 0,
|
||||
"totalScore": 1,
|
||||
"maxScore": 1,
|
||||
"firstRecalledAt": "2026-05-24T02:48:04.923Z",
|
||||
"lastRecalledAt": "2026-05-24T02:48:04.923Z",
|
||||
"queryHashes": [
|
||||
"c2d15f7574fb"
|
||||
],
|
||||
"recallDays": [
|
||||
"2026-05-24"
|
||||
],
|
||||
"conceptTags": [
|
||||
"studytime-analysis",
|
||||
"vala-user",
|
||||
"vala-app-character",
|
||||
"account-id",
|
||||
"女/1",
|
||||
"yyyy-mm-dd",
|
||||
"vala-app-account",
|
||||
"get-mysql-connection"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
52
memory/2026-05-24-1047.md
Normal file
52
memory/2026-05-24-1047.md
Normal file
@ -0,0 +1,52 @@
|
||||
# Session: 2026-05-24 10:47:38 GMT+8
|
||||
|
||||
- **Session Key**: agent:xiaoban:feishu:direct:ou_5494e9f79ba2bc0c221f94781abc52a9
|
||||
- **Session ID**: ea8c317e-d3db-47d1-bbc2-4840826a9073
|
||||
- **Source**: feishu
|
||||
|
||||
## Conversation Summary
|
||||
|
||||
user: Continue the OpenClaw runtime event.
|
||||
assistant: NO_REPLY
|
||||
user: 修改一下studytime-analysis这个技能,输出的内容中,首先输出角色的基本信息,包括这个角色ID,对应的账号ID,对应的账号手机号后4位,角色的名字、性别、年龄。
|
||||
assistant: 需要先确认角色信息在哪个数据库、哪些字段。查一下实际的表结构。
|
||||
assistant: 数据结构确认完毕。现在修改脚本,在报告开头加入角色基本信息。
|
||||
assistant: 基本信息已正确显示。更新 SKILL.md 并同步:
|
||||
assistant: 已修改完成。现在报告开头会先展示角色基本信息:
|
||||
|
||||
```
|
||||
## 基本信息
|
||||
| 项目 | 详情 |
|
||||
|------|------|
|
||||
| 角色ID | 2895 |
|
||||
| 账号ID | 2148 |
|
||||
| 角色名字 | Tom |
|
||||
| 性别 | 男 |
|
||||
| 年龄 | 11 岁 |
|
||||
| 账号手机号后4位 | 1625 |
|
||||
```
|
||||
|
||||
数据来源:MySQL Online `vala_user` 库的 `vala_app_character`(角色信息)+ `vala_app_account`(账号手机号),手机号会自动脱敏只取后4位,年龄从生日推算。
|
||||
|
||||
已同步 SkillHub + Git。再跑一个试试?
|
||||
user: Continue the OpenClaw runtime event.
|
||||
assistant: NO_REPLY
|
||||
user: 再跑一下角色2895的学习时间分析
|
||||
assistant: 报告已在上方完整输出。角色 Tom(2895)的关键特征没有变化,现在头部多出了基本信息卡 —— **账号ID 2148、手机号尾号 1625、男、11岁**。
|
||||
|
||||
还需要调整其他内容吗?
|
||||
user: 对了,再增加一个标签的定义,如果最近14天没有完课记录的数据,那么这个角色被定义为“流失”,否则是正常。在每次输出的时候,也输出这个定义
|
||||
assistant: 2895 显示"正常"(最近记录 5/18,在14天内)。再测一个可能流失的:
|
||||
assistant: 三种状态都验证通过:
|
||||
- Tom(2895,5/18 有课)→ **正常**
|
||||
- Leo(2343,0完课)→ **无完课记录**
|
||||
- xiaoman(8,最后2025/3)→ **流失**
|
||||
|
||||
同步 SkillHub + Git:
|
||||
assistant: 已添加。现在每个角色分析报告的基本信息中都会显示**最近留存状态**:
|
||||
|
||||
| 状态 | 判定规则 |
|
||||
|------|----------|
|
||||
| **正常** | 最近14天内有完课记录 |
|
||||
| **流失** | 有完课记录但14天内无新课 |
|
||||
| **无完课记录** | 没有任何完课记录 |
|
||||
60
memory/2026-05-24.md
Normal file
60
memory/2026-05-24.md
Normal file
@ -0,0 +1,60 @@
|
||||
# 2026-05-24 工作日志
|
||||
|
||||
## 新建技能: studytime-analysis
|
||||
|
||||
[刘庆逊提出] 创建学习时间分析技能,分析角色完课记录的规律。
|
||||
|
||||
### 技能结构
|
||||
- `skills/studytime-analysis/SKILL.md` — 技能定义
|
||||
- `skills/studytime-analysis/scripts/studytime_analysis.py` — Python 分析脚本
|
||||
|
||||
### 分析维度
|
||||
1. **一周时间分布**(排除寒暑假1-2月、7-8月):周一~周日各天完课数、时段分布(上午/中午/下午/晚上)、周末是否上课
|
||||
2. **跨周学习趋势**(包含寒暑假全部数据):总周数、周均完课数、连续性、中断周检测、前后半段趋势对比、突增/骤降检测
|
||||
3. **完课记录明细表**(全部数据):日期/时间/星期/时段/级别/课程ID
|
||||
|
||||
### 数据源
|
||||
- PostgreSQL Online(vala 库)
|
||||
- 核心表:`user_chapter_play_record_0~7`(8张分表,无 `bi_` 前缀)
|
||||
- 筛选:`play_status = 1`
|
||||
- 注意:表在 PostgreSQL 而非 MySQL,表名无 `bi_` 前缀
|
||||
|
||||
### 寒暑假规则
|
||||
- 一周分布分析时排除 1-2 月(寒假)和 7-8 月(暑假)—— 因为寒暑假作息与平时差异大,混在一起会干扰时段分析
|
||||
- 跨周趋势和明细表包含全部数据(含寒暑假)
|
||||
- 报告中区分标注数据范围
|
||||
|
||||
### 触发方式
|
||||
用户说「学习时间分析 [角色ID]」即可触发
|
||||
|
||||
### 已测试角色
|
||||
- 2343、2344:无完课记录(play_status=2,未完成)
|
||||
- 2840:276条记录,秋季集中型用户
|
||||
- 25976:265条,246条在W16周一天完成(A2批量),疑似系统批量标记
|
||||
- 2895:188条,长期稳定学习型用户,36周几乎不间断,非寒暑假晚上为主,寒暑假上午为主
|
||||
|
||||
### 技术要点
|
||||
- psycopg2 的 `%(param_name)s` 命名参数必须正确匹配,UNION ALL 多个子查询需要不同参数名
|
||||
- PostgreSQL 返回的 `updated_at` 是 tz-aware datetime
|
||||
- `datetime.fromisocalendar(year, week, 1)` 获取某周周一的日期
|
||||
|
||||
### 同步
|
||||
- 已推送到 SkillHub(`studytime-analysis.xiaoban`)
|
||||
- 已 commit 到 Git 远程仓库
|
||||
- 已通知 Cris(李若松)
|
||||
|
||||
### 增强: 报告开头加入角色基本信息 (2026-05-24)
|
||||
|
||||
[刘庆逊提出] 在 studytime-analysis 输出中加入角色基本信息,包括:
|
||||
- 角色ID、账号ID、角色名字、性别、年龄、账号手机号后4位
|
||||
|
||||
**数据源(新增)**:
|
||||
- MySQL Online `vala_user` 库
|
||||
- `vala_app_character` 表:id, account_id, nickname, gender(0=女/1=男), birthday(varchar "YYYY-MM-DD")
|
||||
- `vala_app_account` 表:id, tel(已脱敏如 186****1625)
|
||||
- 手机号已脱敏,直接取后4位;年龄从 birthday 计算
|
||||
|
||||
**修改文件**:
|
||||
- `skills/studytime-analysis/scripts/studytime_analysis.py`:新增 MySQL 连接函数 `get_mysql_connection()` 和 `fetch_role_info(role_id)`,更新 `format_report()` 输出基本角色信息
|
||||
- 已验证 2895 正常运行输出
|
||||
- 已同步 SkillHub + Git
|
||||
223
output/studytime_33522.html
Normal file
223
output/studytime_33522.html
Normal file
@ -0,0 +1,223 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>学习时间分析报告 — 角色 33522</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif; background: #f5f7fa; color: #333; line-height: 1.6; padding: 20px; }
|
||||
.container { max-width: 1100px; margin: 0 auto; }
|
||||
h1 { text-align: center; color: #1a1a2e; margin: 20px 0 30px; font-size: 24px; }
|
||||
h2 { color: #2d3436; font-size: 20px; margin: 30px 0 15px; padding-bottom: 8px; border-bottom: 2px solid #0984e3; }
|
||||
.card { background: #fff; border-radius: 10px; box-shadow: 0 2px 8px rgba(0,0,0,0.08); padding: 24px; margin-bottom: 20px; }
|
||||
.info-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 12px; }
|
||||
.info-item { display: flex; padding: 8px 0; border-bottom: 1px solid #f0f0f0; }
|
||||
.info-label { color: #636e72; min-width: 120px; font-weight: 500; }
|
||||
.info-value { color: #2d3436; }
|
||||
table { width: 100%; border-collapse: collapse; font-size: 13px; }
|
||||
thead { background: #0984e3; color: #fff; }
|
||||
th { padding: 10px 8px; text-align: center; font-weight: 600; white-space: nowrap; }
|
||||
td { padding: 8px; text-align: center; border-bottom: 1px solid #eee; }
|
||||
tr:hover td { background: #f0f7ff; }
|
||||
.summary-list { padding-left: 20px; }
|
||||
.summary-list li { margin-bottom: 8px; line-height: 1.8; }
|
||||
.meta { text-align: center; color: #999; font-size: 12px; margin-top: 30px; }
|
||||
.text-block { background: #f8f9fd; border-left: 4px solid #0984e3; padding: 12px 16px; border-radius: 0 8px 8px 0; margin: 10px 0; }
|
||||
.status-normal { color: #00b894; font-weight: 600; }
|
||||
.status-lost { color: #e17055; font-weight: 600; }
|
||||
@media print { body { background: #fff; } .card { box-shadow: none; border: 1px solid #ddd; } }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
|
||||
<h1>📊 学习时间分析报告 — 角色 33522(FSWY)</h1>
|
||||
|
||||
<!-- 第一部分:基本信息 -->
|
||||
<h2>一、基本信息</h2>
|
||||
<div class="card">
|
||||
<div class="info-grid">
|
||||
<div class="info-item"><span class="info-label">角色ID</span><span class="info-value">33522</span></div>
|
||||
<div class="info-item"><span class="info-label">账号ID</span><span class="info-value">4909</span></div>
|
||||
<div class="info-item"><span class="info-label">角色姓名</span><span class="info-value">FSWY</span></div>
|
||||
<div class="info-item"><span class="info-label">角色性别</span><span class="info-value">男</span></div>
|
||||
<div class="info-item"><span class="info-label">角色年龄</span><span class="info-value">8 岁</span></div>
|
||||
<div class="info-item"><span class="info-label">手机号后4位</span><span class="info-value">7624</span></div>
|
||||
<div class="info-item"><span class="info-label">最近留存状态</span><span class="info-value"><span class="status-normal">正常</span></span></div>
|
||||
<div class="info-item"><span class="info-label">注册时间</span><span class="info-value">2026-05-07 20:02</span></div>
|
||||
<div class="info-item"><span class="info-label">第一次完课时间</span><span class="info-value">2026-05-07 20:16</span></div>
|
||||
<div class="info-item"><span class="info-label">最后一次完课时间</span><span class="info-value">2026-05-21 18:50</span></div>
|
||||
<div class="info-item"><span class="info-label">最后一次完课</span><span class="info-value">Level A1 / 小镇时光 / Lesson 1</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 第二部分:完课记录表格 -->
|
||||
<h2>二、完课记录明细(共 11 条)</h2>
|
||||
<div class="card" style="overflow-x: auto;">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>序号</th>
|
||||
<th>Level</th>
|
||||
<th>Unit(单元)</th>
|
||||
<th>Lesson</th>
|
||||
<th>星期</th>
|
||||
<th>时段</th>
|
||||
<th>开始上课时间</th>
|
||||
<th>完课时间</th>
|
||||
<th>完课耗时</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td>A1</td>
|
||||
<td>L1-U0</td>
|
||||
<td>1</td>
|
||||
<td>周四</td>
|
||||
<td>晚上</td>
|
||||
<td>2026-05-07 20:02</td>
|
||||
<td>2026-05-07 20:16</td>
|
||||
<td>13分42秒</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>A1</td>
|
||||
<td>L1-U0</td>
|
||||
<td>2</td>
|
||||
<td>周四</td>
|
||||
<td>晚上</td>
|
||||
<td>2026-05-07 20:19</td>
|
||||
<td>2026-05-07 20:30</td>
|
||||
<td>11分8秒</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td>A1</td>
|
||||
<td>L1-U0</td>
|
||||
<td>3</td>
|
||||
<td>周四</td>
|
||||
<td>晚上</td>
|
||||
<td>2026-05-07 20:34</td>
|
||||
<td>2026-05-07 20:45</td>
|
||||
<td>10分21秒</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>4</td>
|
||||
<td>A1</td>
|
||||
<td>L1-U0</td>
|
||||
<td>4</td>
|
||||
<td>周四</td>
|
||||
<td>晚上</td>
|
||||
<td>2026-05-07 20:49</td>
|
||||
<td>2026-05-07 21:02</td>
|
||||
<td>12分33秒</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>5</td>
|
||||
<td>A1</td>
|
||||
<td>L1-U0</td>
|
||||
<td>5</td>
|
||||
<td>周五</td>
|
||||
<td>晚上</td>
|
||||
<td>2026-05-08 21:42</td>
|
||||
<td>2026-05-08 21:54</td>
|
||||
<td>12分48秒</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>6</td>
|
||||
<td>A1</td>
|
||||
<td>小镇时光</td>
|
||||
<td>1</td>
|
||||
<td>周六</td>
|
||||
<td>晚上</td>
|
||||
<td>2026-05-09 21:12</td>
|
||||
<td>2026-05-09 21:26</td>
|
||||
<td>13分33秒</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>7</td>
|
||||
<td>A1</td>
|
||||
<td>小镇时光</td>
|
||||
<td>2</td>
|
||||
<td>周二</td>
|
||||
<td>下午</td>
|
||||
<td>2026-05-12 17:27</td>
|
||||
<td>2026-05-12 17:38</td>
|
||||
<td>10分49秒</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>8</td>
|
||||
<td>A1</td>
|
||||
<td>小镇时光</td>
|
||||
<td>3</td>
|
||||
<td>周三</td>
|
||||
<td>下午</td>
|
||||
<td>2026-05-13 17:24</td>
|
||||
<td>2026-05-13 17:37</td>
|
||||
<td>12分48秒</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>9</td>
|
||||
<td>A1</td>
|
||||
<td>小镇时光</td>
|
||||
<td>4</td>
|
||||
<td>周四</td>
|
||||
<td>晚上</td>
|
||||
<td>2026-05-14 19:22</td>
|
||||
<td>2026-05-14 19:35</td>
|
||||
<td>13分16秒</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>10</td>
|
||||
<td>A1</td>
|
||||
<td>小镇时光</td>
|
||||
<td>5</td>
|
||||
<td>周二</td>
|
||||
<td>晚上</td>
|
||||
<td>2026-05-19 19:26</td>
|
||||
<td>2026-05-19 19:53</td>
|
||||
<td>27分30秒</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>11</td>
|
||||
<td>A1</td>
|
||||
<td>小镇时光</td>
|
||||
<td>1</td>
|
||||
<td>周四</td>
|
||||
<td>晚上</td>
|
||||
<td>2026-05-20 21:49</td>
|
||||
<td>2026-05-21 18:50</td>
|
||||
<td>21时0分35秒</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- 第三部分:周上课时间分布总结 -->
|
||||
<h2>三、周上课时间分布分析</h2>
|
||||
<div class="card">
|
||||
<div class="text-block">非寒暑假期间共完成 11 节课,主要集中在 **周四**(6 节,占 55%)。 工作日上课集中在 **晚上**时段(8 节,占 80%)。 周末也保持上课节奏,周六 1 节、周日 0 节。</div>
|
||||
</div>
|
||||
|
||||
<!-- 第四部分:跨周趋势分析 -->
|
||||
<h2>四、跨周趋势分析</h2>
|
||||
<div class="card">
|
||||
<div class="text-block">完课跨越 3 周(有课 3 周),共 11 节,周均 3.7 节。 学习连续性良好,无中断周。 整体趋势:下降 ↓,前半段平均 6.0 节/周 → 后半段 2.0 节/周。</div>
|
||||
</div>
|
||||
|
||||
<!-- 第五部分:关键特征总结 -->
|
||||
<h2>五、关键特征总结</h2>
|
||||
<div class="card">
|
||||
<ul class="summary-list">
|
||||
<li>✅ 状态**正常**,近14天内有完课。累计 11 节完课。</li><li>🆕 新用户,学习跨度约 1 个月,尚在形成学习习惯阶段。</li><li>🐢 低频学习,周均 3.7 节。</li><li>🌙 晚间学习型,80% 的课在晚上。</li><li>📉 学习频率呈下降趋势,需关注。</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="meta">分析时间:2026-05-24 11:06 | 完课总数:11 条 | 非寒暑假:11 条 | 寒暑假:0 条</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@ -1,8 +1,8 @@
|
||||
---
|
||||
name: studytime-analysis
|
||||
description: 分析指定角色的完课时间分布与学习规律,包含一周内时间分布、跨周趋势、寒暑假排除。触发词:「学习时间分析」「看看学习时间」「学习时间有什么特点」「studytime」。
|
||||
description: 分析指定角色的完课时间分布与学习规律,包含一周内时间分布、跨周趋势、寒暑假排除。支持 Markdown 和 HTML 双格式输出。触发词:「学习时间分析」「看看学习时间」「学习时间有什么特点」「studytime」。
|
||||
slug: studytime-analysis
|
||||
version: 1.0.0
|
||||
version: 1.1.0
|
||||
---
|
||||
|
||||
# 学习时间分析技能
|
||||
@ -21,35 +21,53 @@ version: 1.0.0
|
||||
|
||||
1. **参数提取** — 从用户消息中提取角色ID
|
||||
2. **数据采集** — 执行 Python 脚本查询该角色全部完课记录(包含寒暑假,非按月过滤)
|
||||
3. **分析输出** — 脚本自动完成以下分析并输出格式化报告:
|
||||
- **一周分布**(仅非寒暑假数据):周一至周日各天完课数量 + 周一至周五上课时段(上午/中午/下午/晚上),排除寒暑假作息差异的干扰
|
||||
- **跨周趋势**(全部数据):覆盖总周数、周均完课数、连续性、中断周、趋势变化(含寒暑假期间的学习节奏变化)
|
||||
3. **Markdown 报告输出** — 脚本自动完成分析并输出格式化报告:
|
||||
- **角色基本信息**:角色ID、账号ID、手机号后4位、角色名字、性别、年龄、留存状态
|
||||
- **一周分布**(仅非寒暑假数据):周一至周日各天完课数量 + 周一至周五上课时段
|
||||
- **跨周趋势**(全部数据):覆盖总周数、周均完课数、连续性、中断周、趋势变化
|
||||
- **完课记录明细**(全部数据):完整的完课时间表
|
||||
- **HTML 提示**:报告末尾自动提示用户可生成 HTML 详细报告
|
||||
4. **HTML 生成(用户确认后)** — 生成精美 HTML 文件,通过飞书发送给用户
|
||||
|
||||
## 调用方式
|
||||
|
||||
### Markdown 报告(默认)
|
||||
```bash
|
||||
cd /root/.openclaw/workspace-xiaoban && \
|
||||
export PG_DB_HOST=bj-postgres-16pob4sg.sql.tencentcdb.com \
|
||||
PG_DB_PORT=28591 PG_DB_USER=ai_member \
|
||||
PG_DB_PASSWORD='...' PG_DB_DATABASE=vala && \
|
||||
export MYSQL_HOST_online=bj-cdb-dh2fkqa0.sql.tencentcdb.com \
|
||||
MYSQL_USERNAME_online=read_only MYSQL_PASSWORD_online='...' MYSQL_PORT_online=27751 && \
|
||||
python3 skills/studytime-analysis/scripts/studytime_analysis.py <role_id>
|
||||
```
|
||||
|
||||
### HTML 报告
|
||||
```bash
|
||||
# 在上述环境变量基础上:
|
||||
python3 skills/studytime-analysis/scripts/studytime_analysis.py <role_id> --format html -o output/studytime_<role_id>.html
|
||||
```
|
||||
|
||||
## HTML 报告结构(5 部分)
|
||||
|
||||
1. **基本信息卡** — 角色ID、账号ID、手机号后4位、姓名、性别、年龄、留存状态、注册时间、第一次完课时间、最后一次完课时间、最后一次完课的 Level/Unit/Lesson
|
||||
2. **完课记录明细表** — 序号、Level、Unit(单元名)、Lesson、星期、时段、开始上课时间、完课时间、完课耗时
|
||||
3. **周上课时间分布分析** — 文字总结(最活跃星期、时段偏好、周末情况)
|
||||
4. **跨周趋势分析** — 文字总结(周数、连续性、前后段对比、趋势方向)
|
||||
5. **关键特征总结** — 要点列表(规模、活跃度、时段特征、趋势、寒暑假等)
|
||||
|
||||
## 数据库说明
|
||||
|
||||
- **完课数据源**: PostgreSQL Online (`vala` 库) — `user_chapter_play_record_0~7`(8张分表)
|
||||
- **角色信息源**: MySQL Online (`vala_user` 库) — `vala_app_character` + `vala_app_account`
|
||||
- **章节映射源**: MySQL Online (`vala` 库) — `vala_game_chapter` + `vala_game_season_package`
|
||||
- **筛选**: `play_status = 1`(已完成),查询全量数据(不按月过滤)
|
||||
- **寒暑假处理**: 1-2月(寒假)和 7-8月(暑假)的记录仅在一周时间分布中排除,跨周趋势和完课明细完整保留
|
||||
- **注意**: 表名无 `bi_` 前缀;课程通过 `level` + `chapter_id` 字段展示
|
||||
- **章节映射**: 通过 `chapter_id` → `vala_game_chapter.id` → `vala_game_season_package` 获取 Level/Unit/Lesson 信息
|
||||
|
||||
## 输出说明
|
||||
## 交互流程
|
||||
|
||||
脚本输出为 Markdown 格式的分析报告,可直接发送给用户。包含:
|
||||
- 角色基本信息(角色ID、账号ID、手机号后4位、角色名字、性别、年龄)
|
||||
- 数据概况(完课总数、寒暑假/非寒暑假数量)
|
||||
- 📌 一周时间分布数据范围说明
|
||||
- 一周时间分布表 + 规律总结(仅非寒暑假)
|
||||
- 跨周学习趋势表 + 趋势分析(全部数据)
|
||||
- 完课记录明细表(全部数据,含寒暑假标记)
|
||||
1. 用户发起学习时间分析请求 → 输出 Markdown 报告
|
||||
2. 报告末尾显示:「💡 是否需要将以上所有详细信息生成为一个 HTML 文件?回复「是」或「需要」即可。」
|
||||
3. 用户回复「是」/「需要」→ 执行 HTML 生成 → 通过飞书发送 HTML 文件给用户
|
||||
4. 用户回复其他内容 → 不执行 HTML 生成
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user