You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于React.js与Node.js的待办清单当日任务提醒实现(附代码)

当日任务提醒功能实现方案

一、服务端(Node.js):任务筛选与触发逻辑

核心是从数据库筛选当日待提醒任务,再通过定时任务或实时推送触发提醒,这里以MongoDB为例实现。

1. 依赖安装

npm install node-schedule moment mongoose

2. 任务数据模型

先定义待办任务的Schema,存储日期和提醒状态:

// models/Todo.js
const mongoose = require('mongoose');
const todoSchema = new mongoose.Schema({
  title: String,
  content: String,
  dueDate: Date, // 客户端传入的任务截止日期
  userId: String, // 关联用户ID,用于定向推送
  isReminded: { type: Boolean, default: false } // 标记是否已发送提醒
});
module.exports = mongoose.model('Todo', todoSchema);

3. 当日任务筛选函数

筛选出当日未发送提醒的任务:

// services/reminderService.js
const moment = require('moment');
const Todo = require('../models/Todo');

async function getTodayUnremindedTodos() {
  const startOfDay = moment().startOf('day').toDate();
  const endOfDay = moment().endOf('day').toDate();
  
  return await Todo.find({
    dueDate: { $gte: startOfDay, $lte: endOfDay },
    isReminded: false
  });
}

4. 定时触发提醒

用node-schedule设置每日固定时间(比如早9点)执行提醒任务,同时标记任务为已提醒:

// server.js
const schedule = require('node-schedule');
const { getTodayUnremindedTodos } = require('./services/reminderService');
const Todo = require('./models/Todo');
const { Server } = require('socket.io');
const http = require('http');
const app = require('./app');
const server = http.createServer(app);
const io = new Server(server);

// 每日9点执行提醒
const reminderJob = schedule.scheduleJob('0 9 * * *', async () => {
  const todayTodos = await getTodayUnremindedTodos();
  if (todayTodos.length === 0) return;

  // 标记任务为已提醒
  await Todo.updateMany(
    { _id: { $in: todayTodos.map(todo => todo._id) } },
    { isReminded: true }
  );

  // 通过Socket.io推送给对应在线用户
  todayTodos.forEach(todo => {
    io.to(todo.userId).emit('today-reminder', {
      message: `你有当日任务待完成:${todo.title}`,
      todo: todo
    });
  });
});

server.listen(3001, () => console.log('服务启动'));

5. 客户端拉取接口

提供接口让客户端主动获取当日任务:

// routes/todos.js
const express = require('express');
const router = express.Router();
const { getTodayUnremindedTodos } = require('../services/reminderService');

router.get('/today', async (req, res) => {
  try {
    const todos = await getTodayUnremindedTodos();
    res.json(todos);
  } catch (err) {
    res.status(500).json({ message: '获取任务失败' });
  }
});

module.exports = router;

二、客户端(React):提醒接收与本地通知

支持两种方式获取提醒:主动定时拉取、Socket.io实时推送,同时利用浏览器Notification API弹出本地提醒。

1. 主动拉取实现

组件挂载后定时请求服务端接口,有任务则触发本地通知:

// components/Reminder.js
import { useEffect, useState } from 'react';
import axios from 'axios';

const Reminder = () => {
  const [todayTodos, setTodayTodos] = useState([]);

  const fetchTodayTodos = async () => {
    try {
      const res = await axios.get('/api/todos/today');
      setTodayTodos(res.data);
      if (res.data.length > 0) triggerNotification(res.data);
    } catch (err) {
      console.error('获取当日任务失败', err);
    }
  };

  const requestNotificationPermission = async () => {
    if ('Notification' in window) {
      const permission = await Notification.requestPermission();
      if (permission !== 'granted') alert('请开启浏览器通知权限以接收提醒');
    }
  };

  const triggerNotification = (todos) => {
    if (Notification.permission !== 'granted') return;
    todos.forEach(todo => {
      new Notification('待办清单提醒', {
        body: `今日任务:${todo.title}`,
        icon: '/todo-icon.png' // 自定义通知图标
      });
    });
  };

  useEffect(() => {
    requestNotificationPermission();
    fetchTodayTodos();
    // 每小时拉取一次
    const interval = setInterval(fetchTodayTodos, 3600000);
    return () => clearInterval(interval);
  }, []);

  return (
    <div className="reminder">
      {todayTodos.length > 0 && (
        <div className="alert">
          <h3>今日待办</h3>
          <ul>
            {todayTodos.map(todo => (
              <li key={todo._id}>{todo.title}</li>
            ))}
          </ul>
        </div>
      )}
    </div>
  );
};

export default Reminder;

2. Socket.io实时接收

监听服务端推送的提醒事件,实时弹出通知:

// components/SocketReminder.js
import { useEffect } from 'react';
import io from 'socket.io-client';

const socket = io('http://localhost:3001');

const SocketReminder = () => {
  useEffect(() => {
    const requestPermission = async () => {
      if ('Notification' in window) await Notification.requestPermission();
    };
    requestPermission();

    socket.on('today-reminder', (data) => {
      if (Notification.permission === 'granted') {
        new Notification('待办清单提醒', {
          body: data.message,
          icon: '/todo-icon.png'
        });
      }
    });

    return () => socket.off('today-reminder');
  }, []);

  return null;
};

export default SocketReminder;

三、注意事项

  • 浏览器通知必须用户授权,需先调用requestPermission
  • 服务端定时任务依赖进程存活,部署时用PM2等工具守护Node进程
  • 若为React Native应用,替换浏览器Notification API为react-native-push-notification
  • 可调整提醒触发逻辑,比如任务截止前1小时推送,而非固定每日9点

内容的提问来源于stack exchange,提问作者sina pouladrag

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 04:18:13