通知模块
约 2129 字大约 7 分钟
2025-08-11
概述
通知模块 模块是平台通知系统的核心,支持多种类型的通知发送、目标用户管理和通知状态跟踪。该系统支持个人通知、群体通知和系统广播等多种通知模式。
表设计
notifications 表 - 通知表
DDL 定义
-- 创建通知类型枚举
CREATE TYPE notification_type AS ENUM (
'system', -- 系统通知
'course', -- 课程通知
'assignment', -- 作业通知
'assessment', -- 测评通知
'announcement', -- 公告通知
'reminder', -- 提醒通知
'message' -- 消息通知
);
-- 创建目标类型枚举
CREATE TYPE target_type AS ENUM (
'user', -- 单个用户
'class', -- 班级
'course_students', -- 课程的所有学生
'course_teachers', -- 课程的所有教师
'role', -- 指定角色
'broadcast' -- 全系统广播
);
-- 创建优先级枚举
CREATE TYPE priority_level AS ENUM ('low', 'normal', 'high', 'urgent');
CREATE TABLE IF NOT EXISTS public.notifications (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
sender_id UUID REFERENCES auth.users(id) ON DELETE SET NULL, -- 发送者ID(系统通知时为NULL)
title VARCHAR(200) NOT NULL,
content TEXT NOT NULL,
notification_type notification_type NOT NULL,
target_type target_type NOT NULL,
target_data JSONB NOT NULL, -- 目标数据
course_id UUID REFERENCES public.courses(id) ON DELETE CASCADE, -- 关联课程(用于权限控制)
class_id UUID REFERENCES public.classes(id) ON DELETE CASCADE, -- 关联班级(用于权限控制)
priority priority_level NOT NULL DEFAULT 'normal',
metadata JSONB, -- 通知元数据
expires_at TIMESTAMP WITH TIME ZONE, -- 过期时间
is_active BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);字段说明
| 字段名 | 数据类型 | 约束 | 默认值 | 描述 |
|---|---|---|---|---|
id | UUID | PRIMARY KEY | gen_random_uuid() | 通知唯一标识 |
sender_id | UUID | FOREIGN KEY | NULL | 发送者ID(系统通知时为NULL) |
title | VARCHAR(200) | NOT NULL | - | 通知标题 |
content | TEXT | NOT NULL | - | 通知内容 |
notification_type | notification_type | NOT NULL | - | 通知类型 |
target_type | target_type | NOT NULL | - | 目标类型 |
target_data | JSONB | NOT NULL | - | 目标数据(JSON格式) |
course_id | UUID | FOREIGN KEY | NULL | 关联课程(用于权限控制) |
class_id | UUID | FOREIGN KEY | NULL | 关联班级(用于权限控制) |
priority | priority_level | NOT NULL | 'normal' | 优先级 |
metadata | JSONB | NULLABLE | NULL | 通知元数据 |
expires_at | TIMESTAMPTZ | NULLABLE | NULL | 过期时间 |
is_active | BOOLEAN | NOT NULL | true | 通知激活状态 |
created_at | TIMESTAMPTZ | NOT NULL | NOW() | 记录创建时间 |
updated_at | TIMESTAMPTZ | NOT NULL | NOW() | 记录最后更新时间 |
通知类型枚举
| 枚举值 | 中文名称 | 描述 | 使用场景 |
|---|---|---|---|
system | 系统通知 | 系统级别的通知 | 系统维护、更新公告 |
course | 课程通知 | 课程相关通知 | 课程开课、停课、变更 |
assignment | 作业通知 | 作业相关通知 | 作业发布、提交提醒 |
assessment | 测评通知 | 测评相关通知 | 测试开始、成绩发布 |
announcement | 公告通知 | 重要公告 | 学校公告、政策通知 |
reminder | 提醒通知 | 提醒类通知 | 课程提醒、截止日期 |
message | 消息通知 | 个人消息 | 私信、回复消息 |
目标类型枚举
| 枚举值 | 中文名称 | 描述 | target_data格式 |
|---|---|---|---|
user | 单个用户 | 发送给特定用户 | {"user_id": "uuid"} |
class | 班级 | 发送给班级所有学生 | {"class_id": "uuid"} |
course_students | 课程学生 | 发送给课程的所有学生 | {"course_id": "uuid"} |
course_teachers | 课程教师 | 发送给课程的所有教师 | {"course_id": "uuid"} |
role | 指定角色 | 发送给指定角色的用户 | {"role": "student"} |
broadcast | 全系统广播 | 发送给所有用户 | {} |
优先级枚举
| 枚举值 | 中文名称 | 描述 | 显示效果 |
|---|---|---|---|
low | 低优先级 | 一般信息 | 普通显示 |
normal | 普通优先级 | 常规通知 | 默认显示 |
high | 高优先级 | 重要通知 | 突出显示 |
urgent | 紧急 | 紧急通知 | 强制提醒 |
user_notification_status 表 - 用户通知状态表
DDL 定义
CREATE TABLE IF NOT EXISTS public.user_notification_status (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
notification_id UUID NOT NULL REFERENCES public.notifications(id) ON DELETE CASCADE,
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
is_read BOOLEAN NOT NULL DEFAULT false,
is_dismissed BOOLEAN NOT NULL DEFAULT false,
read_at TIMESTAMP WITH TIME ZONE,
dismissed_at TIMESTAMP WITH TIME ZONE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
UNIQUE(notification_id, user_id)
);字段说明
| 字段名 | 数据类型 | 约束 | 默认值 | 描述 |
|---|---|---|---|---|
id | UUID | PRIMARY KEY | gen_random_uuid() | 状态记录唯一标识 |
notification_id | UUID | NOT NULL, FOREIGN KEY | - | 通知ID |
user_id | UUID | NOT NULL, FOREIGN KEY | - | 用户ID |
is_read | BOOLEAN | NOT NULL | false | 是否已读 |
is_dismissed | BOOLEAN | NOT NULL | false | 是否已关闭 |
read_at | TIMESTAMPTZ | NULLABLE | NULL | 读取时间 |
dismissed_at | TIMESTAMPTZ | NULLABLE | NULL | 关闭时间 |
created_at | TIMESTAMPTZ | NOT NULL | NOW() | 记录创建时间 |
target_data 和 metadata 字段详解
target_data 字段格式
// 单个用户
{
"user_id": "uuid"
}
// 班级通知
{
"class_id": "uuid"
}
// 课程学生
{
"course_id": "uuid"
}
// 指定角色
{
"role": "student", // student, teacher, admin
"course_id": "uuid" // 可选,限制在特定课程
}
// 全系统广播
{}metadata 字段格式
{
"action_url": "/courses/math101/assignment1", // 点击跳转链接
"action_text": "查看详情", // 操作按钮文字
"thumbnail": "https://example.com/image.jpg", // 缩略图
"tags": ["urgent", "math"], // 标签
"delivery_method": ["web", "email"], // 推送方式
"template": "assignment_reminder", // 通知模板
"variables": { // 模板变量
"assignment_name": "微积分作业1",
"due_date": "2025-08-15"
}
}外键关系
notifications 表的外键关系
-- 发送者关联(可选)
sender_id REFERENCES auth.users(id) ON DELETE SET NULL
-- 课程关联(可选)
course_id REFERENCES public.courses(id) ON DELETE CASCADE
-- 班级关联(可选)
class_id REFERENCES public.classes(id) ON DELETE CASCADEuser_notification_status 表的外键关系
-- 通知关联
notification_id REFERENCES public.notifications(id) ON DELETE CASCADE
-- 用户关联
user_id REFERENCES auth.users(id) ON DELETE CASCADE索引
基础索引
-- notifications 表索引
CREATE INDEX IF NOT EXISTS idx_notifications_target_type ON public.notifications(target_type);
CREATE INDEX IF NOT EXISTS idx_notifications_course_id ON public.notifications(course_id);
CREATE INDEX IF NOT EXISTS idx_notifications_class_id ON public.notifications(class_id);
CREATE INDEX IF NOT EXISTS idx_notifications_active ON public.notifications(is_active);
CREATE INDEX IF NOT EXISTS idx_notifications_expires_at ON public.notifications(expires_at);
CREATE INDEX IF NOT EXISTS idx_notifications_created_at ON public.notifications(created_at);
CREATE INDEX IF NOT EXISTS idx_notifications_priority ON public.notifications(priority);
CREATE INDEX IF NOT EXISTS idx_notifications_type ON public.notifications(notification_type);
-- user_notification_status 表索引
CREATE INDEX IF NOT EXISTS idx_user_notification_status_user_id ON public.user_notification_status(user_id);
CREATE INDEX IF NOT EXISTS idx_user_notification_status_notification_id ON public.user_notification_status(notification_id);
CREATE INDEX IF NOT EXISTS idx_user_notification_status_is_read ON public.user_notification_status(is_read);
CREATE INDEX IF NOT EXISTS idx_user_notification_status_is_dismissed ON public.user_notification_status(is_dismissed);复合索引
-- 复合索引优化常用查询
CREATE INDEX IF NOT EXISTS idx_notifications_active_expires ON public.notifications(is_active, expires_at);
CREATE INDEX IF NOT EXISTS idx_user_notification_unread ON public.user_notification_status(user_id, is_read) WHERE is_read = false;
CREATE INDEX IF NOT EXISTS idx_user_notification_user_created ON public.user_notification_status(user_id, created_at);特殊索引
-- JSONB 索引
CREATE INDEX IF NOT EXISTS idx_notifications_target_data_gin ON public.notifications USING GIN (target_data);
CREATE INDEX IF NOT EXISTS idx_notifications_metadata_gin ON public.notifications USING GIN (metadata);扩展功能
通知模板系统
可以基于 metadata 中的 template 字段实现通知模板功能,支持:
- 模板定义和管理
- 变量替换
- 多语言支持
- 样式定制
用户可以设置通知偏好:
- 通知类型开关
- 推送时间设置
- 免打扰模式
- 推送方式选择
RLS策略
-- 通知创建控制
CREATE POLICY "教师管理员创建通知" ON public.notifications
FOR INSERT WITH CHECK (get_user_role(auth.uid()) IN ('teacher', 'admin'));
-- 通知查看控制
CREATE POLICY "用户查看相关通知" ON public.notifications
FOR SELECT USING (
-- 系统管理员可以查看所有通知
get_user_role(auth.uid()) = 'admin' OR
-- 用户可以查看发送给自己的通知
EXISTS (
SELECT 1 FROM public.user_notification_status uns
WHERE uns.notification_id = notifications.id
AND uns.user_id = auth.uid()
)
);
-- 通知管理控制
CREATE POLICY "管理通知" ON public.notifications
FOR ALL USING (
-- 管理员可以管理所有通知
get_user_role(auth.uid()) = 'admin' OR
-- 发送者可以管理自己的通知
sender_id = auth.uid()
);
-- 用户通知状态访问控制
CREATE POLICY "用户查看自己的通知状态" ON public.user_notification_status
FOR SELECT USING (
-- 用户可以查看自己的通知状态
user_id = auth.uid() OR
-- 管理员可以查看所有通知状态
get_user_role(auth.uid()) = 'admin'
);
CREATE POLICY "用户管理自己的通知状态" ON public.user_notification_status
FOR ALL USING (
-- 用户可以管理自己的通知状态
user_id = auth.uid() OR
-- 管理员可以管理所有通知状态
get_user_role(auth.uid()) = 'admin'
);触发器
-- 自动更新时间戳触发器
CREATE TRIGGER update_notifications_updated_at
BEFORE UPDATE ON public.notifications
FOR EACH ROW
EXECUTE PROCEDURE update_updated_at_column();
-- 新通知处理触发器
CREATE TRIGGER on_notification_created
AFTER INSERT ON public.notifications
FOR EACH ROW EXECUTE FUNCTION handle_new_notification();
-- 通知验证触发器
CREATE TRIGGER validate_notification_trigger
BEFORE INSERT OR UPDATE ON public.notifications
FOR EACH ROW
EXECUTE FUNCTION validate_notification();数据库函数
update_updated_at_column()
- 用途: 自动更新记录的
updated_at字段 - 触发时机: BEFORE UPDATE
- 返回类型: TRIGGER
- 应用表: notifications
handle_new_notification()
- 用途: 处理新通知创建,自动生成用户通知状态记录
- 触发时机: AFTER INSERT ON notifications
- 返回类型: TRIGGER
- 业务逻辑: 根据目标类型和目标数据获取接收者列表,为每个接收者创建通知状态记录
- 目标类型处理:
- user: 单个用户通知
- class: 班级内所有学生
- course_students: 课程内所有已选课学生
- course_teachers: 课程内所有授课教师
- role: 指定角色的所有激活用户
- broadcast: 全系统广播给所有激活用户
- 应用表: notifications → user_notification_status
validate_notification()
- 用途: 验证通知数据的合法性
- 触发时机: BEFORE INSERT OR UPDATE ON notifications
- 返回类型: TRIGGER
- 验证规则:
- 验证目标数据格式(根据target_type)
- 检查发送者权限(只有教师或管理员可发送)
- 目标数据验证:
- user类型: 必须包含user_id字段
- class类型: 必须包含class_id字段
- course类型: 必须包含course_id字段
- role类型: 必须包含role字段
- 应用表: notifications
版权所有
版权归属:Evoliant
许可证:MIT