活动日志模块
约 1186 字大约 4 分钟
2025-08-11
概述
活动日志模块记录学生在学习平台上的各种活动行为,为学习分析、行为跟踪和个性化推荐提供数据基础。该系统支持多种活动类型的记录和分析。
表设计
student_activity_logs 表 - 学生活动日志表
DDL 定义
-- 创建活动类型枚举
CREATE TYPE activity_type AS ENUM (
'ai_question', -- AI问答
'ai_answer', -- AI回答
'course_access', -- 课程访问
'assessment_start', -- 开始测评
'assessment_complete', -- 完成测评
'knowledge_point_view' -- 查看知识点
);
CREATE TABLE IF NOT EXISTS public.student_activity_logs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
student_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
course_id UUID REFERENCES public.courses(id) ON DELETE CASCADE,
activity_type activity_type NOT NULL,
activity_data JSONB, -- 活动相关数据
session_id UUID, -- 会话标识
ip_address INET,
user_agent TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);字段说明
| 字段名 | 数据类型 | 约束 | 默认值 | 描述 |
|---|---|---|---|---|
id | UUID | PRIMARY KEY | gen_random_uuid() | 日志记录唯一标识 |
student_id | UUID | NOT NULL, FOREIGN KEY | - | 学生ID,关联auth.users表 |
course_id | UUID | FOREIGN KEY | NULL | 课程ID,关联courses表(可选) |
activity_type | activity_type | NOT NULL | - | 活动类型 |
activity_data | JSONB | NULLABLE | NULL | 活动相关数据(JSON格式) |
session_id | UUID | NULLABLE | NULL | 会话标识符 |
ip_address | INET | NULLABLE | NULL | 客户端IP地址 |
user_agent | TEXT | NULLABLE | NULL | 用户代理字符串 |
created_at | TIMESTAMPTZ | NOT NULL | NOW() | 活动发生时间 |
活动类型枚举
| 枚举值 | 中文名称 | 描述 | 典型使用场景 |
|---|---|---|---|
ai_question | AI问答问题 | 学生向AI提问 | 记录学习过程中的疑问 |
ai_answer | AI问答回答 | AI回答学生问题 | 记录知识获取过程 |
course_access | 课程访问 | 访问课程页面或内容 | 学习行为分析 |
assessment_start | 开始测评 | 开始做题或测试 | 测评行为跟踪 |
assessment_complete | 完成测评 | 完成测评活动 | 学习进度跟踪 |
knowledge_point_view | 查看知识点 | 查看知识点详情 | 知识点学习分析 |
activity_data 字段结构
不同活动类型的数据格式:
ai_question(AI问答问题)
{
"question_text": "如何求函数的极限?",
"question_type": "concept", // concept, calculation, application
"knowledge_point_ids": ["uuid1", "uuid2"],
"context": "学习微积分基础",
"difficulty_level": "medium"
}ai_answer(AI回答)
{
"question_id": "uuid", // 对应的问题ID
"answer_text": "求函数极限可以使用以下方法...",
"answer_quality": "high", // high, medium, low
"response_time_ms": 1500,
"tokens_used": 250,
"references": ["公式1", "定理2"]
}course_access(课程访问)
{
"page_url": "/courses/math101/chapter1",
"page_title": "函数的概念",
"visit_duration": 180, // 访问时长(秒)
"scroll_depth": 85, // 页面滚动深度(百分比)
"interaction_count": 3, // 交互次数
"referrer": "/dashboard"
}assessment_start(开始测评)
{
"assessment_id": "uuid",
"question_bank_id": "uuid",
"question_count": 20,
"time_limit": 3600, // 时间限制(秒)
"attempt_number": 1
}assessment_complete(完成测评)
{
"assessment_id": "uuid",
"score": 85.5,
"max_score": 100,
"time_spent": 2700, // 实际用时(秒)
"questions_answered": 18,
"questions_correct": 15,
"completion_rate": 90 // 完成率(百分比)
}knowledge_point_view(查看知识点)
{
"knowledge_point_id": "uuid",
"knowledge_point_name": "导数的定义",
"view_duration": 120, // 查看时长(秒)
"content_type": "video", // text, video, image, interactive
"source": "course_content", // course_content, search, recommendation
"learning_path_step": 3
}外键关系
student_activity_logs 表的外键关系
-- 学生关联
student_id REFERENCES auth.users(id) ON DELETE CASCADE
-- 课程关联(可选)
course_id REFERENCES public.courses(id) ON DELETE CASCADE删除策略说明
| 关联表 | 删除策略 | 说明 |
|---|---|---|
auth.users | CASCADE | 用户删除时,其活动日志也被删除 |
courses | CASCADE | 课程删除时,相关活动日志也被删除 |
索引
基础索引
-- 基础查询索引
CREATE INDEX IF NOT EXISTS idx_activity_logs_student_id ON public.student_activity_logs(student_id);
CREATE INDEX IF NOT EXISTS idx_activity_logs_course_id ON public.student_activity_logs(course_id);
CREATE INDEX IF NOT EXISTS idx_activity_logs_type ON public.student_activity_logs(activity_type);
CREATE INDEX IF NOT EXISTS idx_activity_logs_created_at ON public.student_activity_logs(created_at);
CREATE INDEX IF NOT EXISTS idx_activity_logs_session_id ON public.student_activity_logs(session_id);复合索引
-- 复合索引优化分析查询
CREATE INDEX IF NOT EXISTS idx_activity_logs_student_type_date ON public.student_activity_logs(student_id, activity_type, created_at);
CREATE INDEX IF NOT EXISTS idx_activity_logs_course_type_date ON public.student_activity_logs(course_id, activity_type, created_at);时间索引
-- 时间索引用于按日期查询
CREATE INDEX IF NOT EXISTS idx_activity_logs_created_student ON public.student_activity_logs(created_at, student_id);特殊索引
-- JSONB 索引用于活动数据搜索
CREATE INDEX IF NOT EXISTS idx_activity_logs_data_gin ON public.student_activity_logs USING GIN (activity_data);RLS策略
-- 学生活动日志访问控制
CREATE POLICY "学生查看自己的活动日志" ON public.student_activity_logs
FOR SELECT USING (
-- 学生可以查看自己的活动日志
student_id = auth.uid() OR
-- 管理员可以查看所有活动日志
get_user_role(auth.uid()) = 'admin'
);
CREATE POLICY "插入活动日志" ON public.student_activity_logs
FOR INSERT WITH CHECK (
-- 学生可以插入自己的日志
student_id = auth.uid() OR
-- 管理员可以插入日志
get_user_role(auth.uid()) = 'admin'
);触发器
-- 活动日志验证触发器
CREATE TRIGGER validate_activity_log_trigger
BEFORE INSERT ON public.student_activity_logs
FOR EACH ROW
EXECUTE FUNCTION validate_activity_log();数据库函数
validate_activity_log()
- 用途: 验证活动日志的合法性和数据完整性
- 触发时机: BEFORE INSERT ON student_activity_logs
- 返回类型: TRIGGER
- 验证规则:
- 检查学生ID有效性和激活状态
- 验证学生是否有权限访问指定课程
- 根据活动类型验证activity_data字段格式
- 数据格式验证:
- ai_question: 必须包含question字段
- ai_answer: 必须包含answer字段
- course_access: 必须包含access_type字段
- assessment_start/complete: 必须包含assessment_id字段
- knowledge_point_view: 必须包含knowledge_point_id字段
- 应用表: student_activity_logs
版权所有
版权归属:Evoliant
许可证:MIT