Advertisement
Guest User

Untitled

a guest
Sep 14th, 2017
506
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.31 KB | None | 0 0
  1. #!/usr/bin/env node
  2.  
  3. /*
  4. 更新: 可以补充今天的工作项了
  5.  
  6. 依赖node版本7.6以上
  7.  
  8. 使用前:
  9. npm install -g nodemailer
  10. 将config里的XXXX替换成自己的信息
  11.  
  12. 使用方法:
  13. 1. 将本文件放到项目根目录(注意不要add到git里,必要时可设置.gitignore)
  14. 2. 在项目根目录执行 node dailyreport.js
  15.  
  16. */
  17.  
  18. const nodemailer = require('nodemailer');
  19. const readline = require('readline');
  20.  
  21. const config = {
  22. gitName : 'XXXX',
  23. mailTansport: {
  24. host : 'smtp.ym.163.com',
  25. secure: true,
  26. port : 994,
  27. auth : {
  28. user: 'XXXX@yuanxin2015.com',
  29. pass: 'XXXXX',
  30. },
  31. },
  32. mailSubject : `工作日报_XXXX_${generatorDate()}`,
  33. mailFrom : '"XXXX" <zhangyu@yuanxin2015.com>',
  34. mailTo : [
  35. // 'XXXXX@yuanxin2015.com',
  36. // 'zhangbm@yuanxin2015.com',
  37. 'XXXXX@yuanxin2015.com',
  38. ],
  39. }
  40.  
  41. ;(async () => {
  42. let todayWorksArr = await getGitLog() || [];
  43. printArr(todayWorksArr, '\n今天的工作内容(Commits):');
  44.  
  45. todayWorksArr = todayWorksArr.concat(await getWorkList('今天的补充'));
  46. printArr(todayWorksArr, '\n今天的工作内容:');
  47.  
  48. let tomorrowWorksArr = await getWorkList('明天');
  49. printArr(tomorrowWorksArr, '\n明天的工作计划:');
  50.  
  51. let HTML = generatorHTML(todayWorksArr, tomorrowWorksArr);
  52.  
  53. if (await confirm('\n确认发送吗?(yes)')) {
  54. console.log('\n邮件发送中……');
  55. let log = await sendDailyPort(HTML);
  56. console.log(log);
  57. process.exit(0);
  58. }
  59. process.exit(0);
  60.  
  61. })()
  62. .catch(err => {
  63. console.log(err);
  64. process.exit(0);
  65. });
  66.  
  67. async function confirm (message) {
  68. const rl = readline.createInterface({
  69. input : process.stdin,
  70. output: process.stdout,
  71. prompt: '',
  72. });
  73. return new Promise((resolve, reject) => {
  74. rl.write(message + '\n');
  75. rl.on('line', line => {
  76. switch (line.trim().toLowerCase()) {
  77. case 'n':
  78. case 'no':
  79. resolve(false);
  80. rl.close();
  81. break;
  82. case '':
  83. case 'y':
  84. case 'yes':
  85. default:
  86. resolve(true);
  87. rl.close();
  88. break;
  89. }
  90. });
  91. });
  92. }
  93.  
  94. function printArr (arr, msg) {
  95. if (msg) {console.log(msg);}
  96. if (arr && arr.length > 0) {
  97. return arr.forEach(item => console.log(' ' + item));
  98. } else {
  99. return console.log(' 什么也没有');
  100. }
  101. }
  102.  
  103. //日期生成
  104. function generatorDate () {
  105. let date = new Date();
  106. return `${date.getFullYear()}${preZeroFill(date.getMonth() + 1, 2)}${preZeroFill(date.getDate(), 2)}`;
  107. }
  108.  
  109. //补零函数
  110. function preZeroFill (num, size) {
  111. if (num >= Math.pow(10, size)) { // 如果num本身位数不小于size位
  112. return num.toString();
  113. } else {
  114. var _str = Array(size + 1).join('0') + num;
  115. return _str.slice(_str.length - size);
  116. }
  117. }
  118.  
  119. //HTML生成
  120. function generatorHTML (gitLogArr, tomorrowWorksArr) {
  121. let todayHtmlContent = '';
  122. let todayHtmlTable = '';
  123. if (gitLogArr && gitLogArr.length > 0) {
  124. gitLogArr.forEach((item, index) => {
  125. todayHtmlContent += `
  126. <tr>
  127. <td>${index + 1}</td>
  128. <td>${item}</td>
  129. </tr>
  130. `;
  131. });
  132. todayHtmlTable = `
  133. <p style="color:#1F497D">今天工作内容:</p>
  134. <table class="table table-bordered">
  135. <tr style="border-bottom: solid 1pt #333;">
  136. <th style="width:70px">序号</th>
  137. <th>工作任务项</th>
  138. </tr>
  139. ${todayHtmlContent}
  140. </table>
  141. `;
  142. }
  143.  
  144. let tomorrowHtmlContent = '';
  145. let tomorrowHtmlTable = '';
  146. if (tomorrowWorksArr && tomorrowWorksArr.length > 0) {
  147. tomorrowWorksArr.forEach((item, index) => {
  148. tomorrowHtmlContent += `
  149. <tr>
  150. <td>${index + 1}</td>
  151. <td>${item}</td>
  152. </tr>
  153. `;
  154. });
  155. tomorrowHtmlTable = `
  156. <p style="color:#1F497D">明天工作计划:</p>
  157. <table class="table table-bordered">
  158. <tr style="border-bottom: solid 1pt #333;">
  159. <th style="width:70px">序号</th>
  160. <th>工作任务项</th>
  161. </tr>
  162. ${tomorrowHtmlContent}
  163. </table>
  164. `;
  165. }
  166.  
  167. // console.log(todayHtmlTable,tomorrowHtmlTable);
  168. let html = `
  169. <style>${renderStyle()}</style>
  170. ${todayHtmlTable}
  171. ${tomorrowHtmlTable}
  172. `;
  173. return html;
  174. }
  175.  
  176. //获取gitLog
  177. async function getGitLog () {
  178. const cmdStr = `git log --since="6am" --author="${config.gitName}" --pretty=format:"%s" --no-merges`; // --since="6am"
  179. const exec = require('child_process').exec;
  180. return new Promise((resolve, reject) => {
  181. exec(cmdStr, function (err, stdout, stderr) {
  182. if (err) {
  183. reject(err);
  184. } else {
  185. if (stdout.toString().trim() === '') {resolve(null);}
  186. let gitLogArr = stdout.toString().trim().split('\n');
  187.  
  188. resolve(gitLogArr);
  189. }
  190. });
  191. });
  192. }
  193.  
  194. //邮件发送
  195. function sendDailyPort (HTML, callback) {
  196. return new Promise((resolve, reject) => {
  197. const transporter = nodemailer.createTransport(config.mailTansport);
  198. const mailOptions = {
  199. from : config.mailFrom, // sender address
  200. to : config.mailTo, // ["liuzhen@yuanxin2015.com","zhangbm@yuanxin2015.com","zhangyu@yuanxin2015.com"], // list of receivers
  201. subject: config.mailSubject, // Subject line
  202. html : HTML,
  203. };
  204.  
  205. // 测试账号
  206. // transporter.verify(function (error, success) {
  207. // if (error) {
  208. // reject(error)
  209. // } else {
  210. // resolve('Server is ready to take our messages')
  211. // }
  212. // })
  213.  
  214. // 发送邮件
  215. transporter.sendMail(mailOptions, function (error, info) {
  216. if (error) {
  217. callback && callback(error);
  218. reject(error);
  219. } else {
  220. callback && callback(null, info.response);
  221. resolve(info.response);
  222. }
  223. });
  224. });
  225. }
  226.  
  227. function getWorkList (dayStr) {
  228. const rl = readline.createInterface({
  229. input : process.stdin,
  230. output: process.stdout,
  231. prompt: '',
  232. });
  233. return new Promise((resolve, reject) => {
  234. rl.question(`是否录入入${dayStr}工作计划?(yes)`, answer => {
  235. switch (answer.toLowerCase()) {
  236. case 'n':
  237. case 'no':
  238. case 'not':
  239. rl.write(`${dayStr}计划缺省\n`);
  240. resolve([]);
  241. break;
  242. case '':
  243. case 'y':
  244. case 'yes':
  245. default:
  246. let works = [];
  247. rl.write(`请录入${dayStr}工作计划,回车录入下一项,键入 end 以结束录入:\n`);
  248. rl.on('line', function (line) {
  249. switch (line.trim()) {
  250. case '':
  251. break;
  252. case 'end':
  253. resolve(works);
  254. rl.close();
  255. break;
  256. default:
  257. works.push(line);
  258. break;
  259. }
  260. });
  261. }
  262. });
  263. });
  264.  
  265. }
  266.  
  267. function renderStyle () {
  268. return `
  269. table {
  270. border-spacing: 0;
  271. border-collapse: collapse;
  272. }
  273. td,
  274. th {
  275. padding: 0;
  276. }
  277. table {
  278. background-color: transparent;
  279. }
  280. caption {
  281. padding-top: 8px;
  282. padding-bottom: 8px;
  283. color: #777;
  284. text-align: left;
  285. }
  286. th {
  287. text-align: left;
  288. }
  289. .table {
  290. width: 100%;
  291. max-width: 100%;
  292. margin-bottom: 20px;
  293. }
  294. .table > thead > tr > th,
  295. .table > tbody > tr > th,
  296. .table > tfoot > tr > th,
  297. .table > thead > tr > td,
  298. .table > tbody > tr > td,
  299. .table > tfoot > tr > td {
  300. padding: 8px;
  301. line-height: 1.42857143;
  302. vertical-align: top;
  303. border-top: 1px solid #ddd;
  304. }
  305. .table > thead > tr > th {
  306. vertical-align: bottom;
  307. border-bottom: 2px solid #ddd;
  308. }
  309. .table > caption + thead > tr:first-child > th,
  310. .table > colgroup + thead > tr:first-child > th,
  311. .table > thead:first-child > tr:first-child > th,
  312. .table > caption + thead > tr:first-child > td,
  313. .table > colgroup + thead > tr:first-child > td,
  314. .table > thead:first-child > tr:first-child > td {
  315. border-top: 0;
  316. }
  317. .table > tbody + tbody {
  318. border-top: 2px solid #ddd;
  319. }
  320. .table .table {
  321. background-color: #fff;
  322. }
  323. .table-condensed > thead > tr > th,
  324. .table-condensed > tbody > tr > th,
  325. .table-condensed > tfoot > tr > th,
  326. .table-condensed > thead > tr > td,
  327. .table-condensed > tbody > tr > td,
  328. .table-condensed > tfoot > tr > td {
  329. padding: 5px;
  330. }
  331. .table-bordered {
  332. border: 1px solid #ddd;
  333. }
  334. .table-bordered > thead > tr > th,
  335. .table-bordered > tbody > tr > th,
  336. .table-bordered > tfoot > tr > th,
  337. .table-bordered > thead > tr > td,
  338. .table-bordered > tbody > tr > td,
  339. .table-bordered > tfoot > tr > td {
  340. border: 1px solid #ddd;
  341. }
  342. .table-bordered > thead > tr > th,
  343. .table-bordered > thead > tr > td {
  344. border-bottom-width: 2px;
  345. }
  346. .table-striped > tbody > tr:nth-of-type(odd) {
  347. background-color: #f9f9f9;
  348. }
  349. .table-hover > tbody > tr:hover {
  350. background-color: #f5f5f5;
  351. }
  352. table col[class*="col-"] {
  353. position: static;
  354. display: table-column;
  355. float: none;
  356. }
  357. table td[class*="col-"],
  358. table th[class*="col-"] {
  359. position: static;
  360. display: table-cell;
  361. float: none;
  362. }
  363. .table > thead > tr > td.active,
  364. .table > tbody > tr > td.active,
  365. .table > tfoot > tr > td.active,
  366. .table > thead > tr > th.active,
  367. .table > tbody > tr > th.active,
  368. .table > tfoot > tr > th.active,
  369. .table > thead > tr.active > td,
  370. .table > tbody > tr.active > td,
  371. .table > tfoot > tr.active > td,
  372. .table > thead > tr.active > th,
  373. .table > tbody > tr.active > th,
  374. .table > tfoot > tr.active > th {
  375. background-color: #f5f5f5;
  376. }
  377. .table-hover > tbody > tr > td.active:hover,
  378. .table-hover > tbody > tr > th.active:hover,
  379. .table-hover > tbody > tr.active:hover > td,
  380. .table-hover > tbody > tr:hover > .active,
  381. .table-hover > tbody > tr.active:hover > th {
  382. background-color: #e8e8e8;
  383. }
  384. .table > thead > tr > td.success,
  385. .table > tbody > tr > td.success,
  386. .table > tfoot > tr > td.success,
  387. .table > thead > tr > th.success,
  388. .table > tbody > tr > th.success,
  389. .table > tfoot > tr > th.success,
  390. .table > thead > tr.success > td,
  391. .table > tbody > tr.success > td,
  392. .table > tfoot > tr.success > td,
  393. .table > thead > tr.success > th,
  394. .table > tbody > tr.success > th,
  395. .table > tfoot > tr.success > th {
  396. background-color: #dff0d8;
  397. }
  398. .table-hover > tbody > tr > td.success:hover,
  399. .table-hover > tbody > tr > th.success:hover,
  400. .table-hover > tbody > tr.success:hover > td,
  401. .table-hover > tbody > tr:hover > .success,
  402. .table-hover > tbody > tr.success:hover > th {
  403. background-color: #d0e9c6;
  404. }
  405. .table > thead > tr > td.info,
  406. .table > tbody > tr > td.info,
  407. .table > tfoot > tr > td.info,
  408. .table > thead > tr > th.info,
  409. .table > tbody > tr > th.info,
  410. .table > tfoot > tr > th.info,
  411. .table > thead > tr.info > td,
  412. .table > tbody > tr.info > td,
  413. .table > tfoot > tr.info > td,
  414. .table > thead > tr.info > th,
  415. .table > tbody > tr.info > th,
  416. .table > tfoot > tr.info > th {
  417. background-color: #d9edf7;
  418. }
  419. .table-hover > tbody > tr > td.info:hover,
  420. .table-hover > tbody > tr > th.info:hover,
  421. .table-hover > tbody > tr.info:hover > td,
  422. .table-hover > tbody > tr:hover > .info,
  423. .table-hover > tbody > tr.info:hover > th {
  424. background-color: #c4e3f3;
  425. }
  426. .table > thead > tr > td.warning,
  427. .table > tbody > tr > td.warning,
  428. .table > tfoot > tr > td.warning,
  429. .table > thead > tr > th.warning,
  430. .table > tbody > tr > th.warning,
  431. .table > tfoot > tr > th.warning,
  432. .table > thead > tr.warning > td,
  433. .table > tbody > tr.warning > td,
  434. .table > tfoot > tr.warning > td,
  435. .table > thead > tr.warning > th,
  436. .table > tbody > tr.warning > th,
  437. .table > tfoot > tr.warning > th {
  438. background-color: #fcf8e3;
  439. }
  440. .table-hover > tbody > tr > td.warning:hover,
  441. .table-hover > tbody > tr > th.warning:hover,
  442. .table-hover > tbody > tr.warning:hover > td,
  443. .table-hover > tbody > tr:hover > .warning,
  444. .table-hover > tbody > tr.warning:hover > th {
  445. background-color: #faf2cc;
  446. }
  447. .table > thead > tr > td.danger,
  448. .table > tbody > tr > td.danger,
  449. .table > tfoot > tr > td.danger,
  450. .table > thead > tr > th.danger,
  451. .table > tbody > tr > th.danger,
  452. .table > tfoot > tr > th.danger,
  453. .table > thead > tr.danger > td,
  454. .table > tbody > tr.danger > td,
  455. .table > tfoot > tr.danger > td,
  456. .table > thead > tr.danger > th,
  457. .table > tbody > tr.danger > th,
  458. .table > tfoot > tr.danger > th {
  459. background-color: #f2dede;
  460. }
  461. .table-hover > tbody > tr > td.danger:hover,
  462. .table-hover > tbody > tr > th.danger:hover,
  463. .table-hover > tbody > tr.danger:hover > td,
  464. .table-hover > tbody > tr:hover > .danger,
  465. .table-hover > tbody > tr.danger:hover > th {
  466. background-color: #ebcccc;
  467. }
  468. .table-responsive {
  469. min-height: .01%;
  470. overflow-x: auto;
  471. }
  472. `;
  473. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement