消息管理系统

566 阅读1分钟

满足在后台向用户推送消息或者发送邮件的功能。

消息推送

使用 socket.io 来实现消息推送。

1.png

服务端实现

1.使用 express 启动服务

const app = express();

const httpServer = createServer(app);

httpServer.listen(SERVER_PORT);

wsMsg(app, httpServer);

2.连接 socket

import {Server} from 'socket.io';

const wsMsg = (app, httpServer) => {
  const io = new Server(httpServer, {
    allowRequest: (req, callback) => callback(null, req.headers.origin === undefined),
  });
  const msgIO = io.of('/ws-message');
  wsStore.msgIO = msgIO;

  msgIO.on('connection', async socket => {
    socket.on('disconnect', () => {
      socket.disconnect(true);
    });
    socket.on('error', (err) => {
      console.error('err.message');
    });

    socket.on('msg:send', (...args) => {
      msgIO.emit('msg:send', ...args);
    });
  });
  return msgIO;
};

3.通过接口触发消息推送

const sendMessage = async (req, res) => {
  const {type, title, context, receiver} = req.body;
  if (type === 'email') {
    if (!receiver) {
      return res.status(400).send({message: '请选择接收者!'});
    }
    sendMail(receiver, title, context);
  } else {
    if (wsStore.msgIO) {
      wsStore.msgIO.emit('msg:send', {title, context});
    }
  }
};

前端实现

4.png

1.配置 socket

import {io} from 'socket.io-client';

const wsMsgUrl = `${window.location.origin}/message`;

export const wsMsg = () => io(wsMsgUrl, {
  auth: {Authorization: `auth ${storage.get('token')}`},
  // autoConnect: false,
});

2.全局监听

const initWS = () => {
  const ws = wsMsg();
  ws.on('msg:send', ({title, context}) => {
    notification.info({
      message: `消息推送:${title}`,
      description: context,
    });
    notifyStore.setState(count => count + 1);
  });
  ws.on('msg:online', ({userid, count}) => {
    notification.info({
      message: `${userid} 已上线!`,
      description: `当前在线用户数: ${count}`,
    });
  });
  ws.on('msg:offline', ({userid, count}) => {
    notification.info({
      message: `${userid} 已下线!`,
      description: `当前在线用户数: ${count}`,
    });
  });
};

3.页面监听,获取实时数据

const Index = props => {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    const ws = wsMsg();
    ws.on('msg:userinfo', users => {
      setUsers(formatUser(users));
    });
  }, []);

  const columns = getColumns();

  const count = users.length;

  const pagination = {
    total: count || 1,
    current: 1,
    pageSize: count || 10,
  };

  return (
    <Row>
      <Col>
        <Panel>
          <h4>当前在线人数:{count}</h4>
          <Table
            pagination={pagination}
            columns={columns}
            dataSource={users}
            size="small"
          />
        </Panel>
      </Col>
    </Row>
  );
};

5.png

发送邮件

使用 nodemailer 来发送邮件。

2.png

1.nodejs 服务端配置

import nodemailer from 'nodemailer';

const sendMail = (to, title, context) => {
  const transporter = nodemailer.createTransport({
    host: 'smtp.xx.com',
    port: 465,
    secure: true,
    auth: {
      user: 'xxx',
      pass: 'xxx',
    },
  });
  const mailOptions = {
    from: '"xxx" xxx',
    to,
    subject: title,
    text: context,
    html: context,
  };

  transporter.sendMail(mailOptions, (error, info) => {
    if (error) {
      return error;
    }
    return info;
  });
};

2.通过接口发送邮件

const sendMessage = async (req, res) => {
  const {type, title, context, receiver} = req.body;
  if (type === 'email') {
    if (!receiver) {
      return res.status(400).send({message: '请选择接收者!'});
    }
    sendMail(receiver, title, context);
  } else {
    if (wsStore.msgIO) {
      wsStore.msgIO.emit('msg:send', {title, context});
    }
  }
};

3.png