这段时间疫情还在持续,你们出门记得戴口罩javascript
灵感来源: 为抗击新肺炎贡献一份技术力量html
访问网址:前端
从而有了文中网站和这篇文章,说来~写文章花的时间可能比项目自己还要多点vue
此次疫情来势汹汹,从街上的反应,家里长辈也都戴上口罩等情形看来,状况比想象中更要严峻一些,如今也到了关键的十来天,但愿能尽快将控制住,待一切安好java
关于这个网站的原型网上已经有不少版本了,决定开写一方面来自于假期的庸长与慌闷,另外一方面也但愿能引发更多人的重视,多一个渠道也好,多一份关注的力量node
网站内数据来源于丁香医生,央视新闻等官方渠道,数据与官方渠道保持更新git
本网站开发主要采用Javascript语言,数据采集后端采用上文提供的接口基础上进行开发,增长邮件管理方面的接口,邮件发送采用nodemailer库,网站前端则采用了vue和element-ui这俩常见组合。程序员
PC端 | 移动端 |
---|---|
![]() |
![]() |
![]() |
![]() |
后台 | 前端 |
---|---|
![]() |
![]() |
关于天天疫情的数据采集,省市数据,辟谣等部分,可参考原做者@普通程序员 连接:juejin.im/post/5e2c6a…. 写的时候原做者还没放出邮件部分的代码,因此我尝试着写了下,没有原做者写的规范全面,不过基本的邮件发送和订阅管理(主要是添加,取消,查询)也是实现了,而且能经过网站前端进行订阅的相关操做,可供参考npm
因为两个进程分离开来,用户前端请求不会影响邮件列表的维护,反之亦然,进程守护一样采用原文中的pm2 读取邮件部分比较简单,直接贴代码了,关键代码在json和nodemailer接收的数据格式转换,须要从数组转为字符串(line 6),其余部分按照nodemailer配置来就能够element-ui
async function sendMailForHtml(title, text) {
// 当天日期
let now = moment();
let today = now.clone().add(0, 'days').format('YYYY-MM-DD');
let toListFile = await fs.readJSON('data/mail.json')
let toListInit = toListFile.toList.join(',') // array转str
let mailOptions = {
from: emailName, // 发件地址
to: toListInit, // 收件列表
subject: `${title}(${today})`, // 标题
html: '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">'+ text // html 内容
};
transporter.sendMail(mailOptions, function(error, info) {
if(error) {
return console.log('邮件发送出错', error);
}
console.log('Message sent: ' + info.response);
});
}
复制代码
至于邮件的发送,相比原做者的“diff”推送方式,我采用了相对简单粗暴的定时发送方式
// 每周1-7的6点和12点,18点执行
let rule = new schedule.RecurrenceRule();
rule.dayOfWeek =[1,2,3,4,5,6,7];
rule.hour =[6,12,18];
rule.minute =0;
rule.second =0;
schedule.scheduleJob( rule, () => {
readyMail()
})
复制代码
能够看到,经过node-schedule库的定时函数,设定为天天的3个时段运行,你们若是有不一样的定时需求,直接修改这个任务函数便可
对于邮件订阅的一些需求,我写了三个对应的处理,分别为基本的添加,取消还有查询,请求处理方式沿用了原文的koa路由方式,逻辑主要集中在对邮件格式的验证和去重方面,这里以删除为例,添加和查询的处理写法也大都类似,详细可见 本项目源码
// GET 删除邮箱名 status=>10(出现错误) status=>2(正常)
router.get('/mail/cut/:mail', async (ctx, next) =>{
let mail = ctx.params.mail || ''
let reg = /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/;
let isEmail = reg.test(mail) ? true : false
let checkResult = await checkMail(mail)
console.log('格式', isEmail)
// 检查格式
if(!isEmail) {
ctx.response.body = { error: '邮件格式不正确,拦截请求', status: 10 }
return
}
// 不存在则跳过
if ( !checkResult ){
ctx.response.body = { warn: '邮箱名不存在,拦截请求', status: 10 }
return
}
let fileData = await fs.readJSON('./resource/mail.json')
let mailList = fileData.toList
let index = mailList.findIndex( item => item === mail ) // 肯定索引
if(index>-1){
mailList.splice(index, 1)
let resultObj = { "toList": mailList }
await fs.writeJSON('./resource/mail.json', resultObj ) //保存MAIL数据
ctx.response.body = { data: '删除mail ok', status: 2 }
}else{
ctx.response.body = { data: '删除mail 失败 不存在邮箱/未知错误', status: 10 }
}
});
复制代码
顺带说下,这里的status是我在这个项目里人为约定的状态,与http协议状态无关,因项目规模小,约定了仅有0,1,10,2这几种状态,分别表明了有/无,出错和成功这几种状况供前端识别。
目前网站已支持邮件的订阅发送和取消等管理,若是须要将本身的邮箱做为发送方的小伙伴,能够这里看下项目里面须要配置的地方
主要的配置入口在项目根目录的mail.js里
const transporter = nodemailer.createTransport({
service: 'qq',
port: 465, // SMTP 端口
secureConnection: true, // 使用 SSL
auth: {
user: emailName,
pass: emailPassword
}
});
复制代码
这里以Q Q邮箱为例,采用其余邮箱的小伙伴可能要自行更改协议端口了 具体的emailName和password,以及接收邮件名,我采用了外置的配置文件和批量发送的方式。 外置的配置文件位于 resource/mailConfig.js下,而 resource/mail.json里面的邮件列表则做为真正要发送的邮箱列表,至于链接二者的桥梁在于sendMailForHtml函数中
下面截取了这段函数中对二者的链接代码
let toListFile = await fs.readJSON('./resource/mail.json')
let toListInit = toListFile.toList.join(',') // array转str
let mailOptions = {
from: emailName, // 发件地址
to: toListInit, // 收件列表
... }
复制代码
实际部署中,利用前面说到的http请求方式便可添加/删除对应邮箱,而须要手动更改的时候直接修改 resource/mail.json里面的邮箱列表便可
部署这块其实相对简单,前提是系统环境,项目依赖都装好没问题的前提下,这里贴下我目前服务器部署的基本环境供你们参考
Node.js=>10.15.0
pm2=>3.2.9
npm=> 6.4.1
确保环境和依赖安装好后,接下来就是进入项目根目录下经过pm2启动相应进程
pm2 start app.js
pm2 start server.js
复制代码
亦可经过原文中的PM2配置文件方式启动,建议在开发环境下,像上面那样单独启动较为合适,方便随时停用程序和作调试等等
本项目后台源码已发布 连接 gitee.com/dunye/nCov_…
跟项目配套的前端网站也已上线,网址: cookcloud.club
小伙伴们能够直接在上面的网站上添加取消订阅,前端源码在整理当中稍后会更新在这篇文章的下方,有须要的小伙伴能够先本身部署后台的程序,至于前端其实能够有不少的实现方式,这个项目的关键也在于后台的处理,你们能够尝试用不同的页面风格去对接上项目后台。
对于项目的相关问题,小伙伴们能够在下方评论区留言 ~ 一块儿探讨学习进步