這段時間疫情還在持續,你們出門記得戴口罩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
小夥伴們能夠直接在上面的網站上添加取消訂閱,前端源碼在整理當中稍後會更新在這篇文章的下方,有須要的小夥伴能夠先本身部署後臺的程序,至於前端其實能夠有不少的實現方式,這個項目的關鍵也在於後臺的處理,你們能夠嘗試用不同的頁面風格去對接上項目後臺。
對於項目的相關問題,小夥伴們能夠在下方評論區留言 ~ 一塊兒探討學習進步