|
|
@@ -0,0 +1,379 @@
|
|
|
+const sendEmail = require('./Email')
|
|
|
+
|
|
|
+class emailTemplate {
|
|
|
+ stramptoTime(time) {
|
|
|
+ if (time < 10)
|
|
|
+ return '';
|
|
|
+ return new Date(+time).toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' });
|
|
|
+ }
|
|
|
+
|
|
|
+ async checkEmail(email, code) {
|
|
|
+ const time = new Date().getTime()
|
|
|
+ await sendEmail(email, 'RunForge - 邮箱验证码',
|
|
|
+ `<html lang="zh-CN">
|
|
|
+
|
|
|
+<head>
|
|
|
+ <meta charset="UTF-8">
|
|
|
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
+ <title>RunForge - 邮箱验证码</title>
|
|
|
+ <style>
|
|
|
+ body {
|
|
|
+ font-family: Arial, sans-serif;
|
|
|
+ background-color: #f4f4f4;
|
|
|
+ margin: 0;
|
|
|
+ padding: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .container {
|
|
|
+ width: 80%;
|
|
|
+ margin: 20px auto;
|
|
|
+ background-color: #fff;
|
|
|
+ padding: 20px;
|
|
|
+ border-radius: 8px;
|
|
|
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
|
|
+ }
|
|
|
+
|
|
|
+ .head {
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ gap:10px;
|
|
|
+ color: #2c3e50;
|
|
|
+ }
|
|
|
+
|
|
|
+ p {
|
|
|
+ font-size: 16px;
|
|
|
+ color: #34495e;
|
|
|
+ line-height: 1.6;
|
|
|
+ text-indent: 2em;
|
|
|
+ }
|
|
|
+
|
|
|
+ .code {
|
|
|
+ margin: 20px 0;
|
|
|
+ font-size: 1.5em;
|
|
|
+ text-align: center;
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+
|
|
|
+ .important {
|
|
|
+ color: #e74c3c;
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+
|
|
|
+ .footer {
|
|
|
+ font-size: 14px;
|
|
|
+ text-align: center;
|
|
|
+ color: #7f8c8d;
|
|
|
+ margin-top: 50px;
|
|
|
+ }
|
|
|
+ </style>
|
|
|
+</head>
|
|
|
+
|
|
|
+<body>
|
|
|
+ <div class="container">
|
|
|
+ <div class="head">
|
|
|
+ <h2>RunForge - 邮箱验证码</h2>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <p>尊敬的用户:</p>
|
|
|
+ <p>您正在本站进行邮箱验证操作,如非您本人操作,请忽略此邮件。</p>
|
|
|
+ <p>您的验证码为:</p>
|
|
|
+ <div class="code">
|
|
|
+ ${code}
|
|
|
+ </div>
|
|
|
+ <p class="important">验证码5分钟内有效,超时请重新获取</p>
|
|
|
+ <p class="footer">Copyright © 2025 RunForge</p>
|
|
|
+ </div>
|
|
|
+</body>
|
|
|
+
|
|
|
+</html>`
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ async registerSuccess(email, username) {
|
|
|
+ const time = new Date().getTime()
|
|
|
+ await sendEmail(email, '您已成功注册RunForge账号',
|
|
|
+ `<html lang="zh-CN">
|
|
|
+
|
|
|
+<head>
|
|
|
+ <meta charset="UTF-8">
|
|
|
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
+ <title>RunForge - 邮箱验证码</title>
|
|
|
+ <style>
|
|
|
+ body {
|
|
|
+ font-family: Arial, sans-serif;
|
|
|
+ background-color: #f4f4f4;
|
|
|
+ margin: 0;
|
|
|
+ padding: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .container {
|
|
|
+ width: 80%;
|
|
|
+ margin: 20px auto;
|
|
|
+ background-color: #fff;
|
|
|
+ padding: 20px;
|
|
|
+ border-radius: 8px;
|
|
|
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
|
|
+ }
|
|
|
+
|
|
|
+ .head {
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ gap: 10px;
|
|
|
+ color: #2c3e50;
|
|
|
+ }
|
|
|
+
|
|
|
+ p {
|
|
|
+ font-size: 16px;
|
|
|
+ color: #34495e;
|
|
|
+ line-height: 1.6;
|
|
|
+ text-indent: 2em;
|
|
|
+ }
|
|
|
+
|
|
|
+ .info {
|
|
|
+ background-color: #ecf0f1;
|
|
|
+ padding: 15px;
|
|
|
+ border-radius: 5px;
|
|
|
+ margin: 20px 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .info p {
|
|
|
+ margin: 5px 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .important {
|
|
|
+ color: #e74c3c;
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+
|
|
|
+ .footer {
|
|
|
+ font-size: 14px;
|
|
|
+ text-align: center;
|
|
|
+ color: #7f8c8d;
|
|
|
+ margin-top: 50px;
|
|
|
+ }
|
|
|
+ </style>
|
|
|
+</head>
|
|
|
+
|
|
|
+<body>
|
|
|
+ <div class="container">
|
|
|
+ <div class="head">
|
|
|
+ <h2>RunForge - 邮箱验证码</h2>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <p>尊敬的 ${username}:</p>
|
|
|
+ <p>您已成功注册RunForge账号:</p>
|
|
|
+ <div class="info">
|
|
|
+ <p><strong>用户名:</strong> ${username}</p>
|
|
|
+ <p><strong>注册时间:</strong> ${this.stramptoTime(time)}</p>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <p class="footer">Copyright © 2025 RunForge</p>
|
|
|
+ </div>
|
|
|
+</body>
|
|
|
+
|
|
|
+</html>`
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ async lepaoSuccess(email, data) {
|
|
|
+ await sendEmail(email, 'RunForge - 乐跑成功提醒',
|
|
|
+ `<html lang="zh-CN">
|
|
|
+ <head>
|
|
|
+ <meta charset="UTF-8">
|
|
|
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
+ <title>RunForge - 乐跑成功提醒</title>
|
|
|
+ <style>
|
|
|
+ body {
|
|
|
+ font-family: Arial, sans-serif;
|
|
|
+ background-color: #f4f4f4;
|
|
|
+ margin: 0;
|
|
|
+ padding: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .container {
|
|
|
+ width: 80%;
|
|
|
+ margin: 20px auto;
|
|
|
+ background-color: #fff;
|
|
|
+ padding: 20px;
|
|
|
+ border-radius: 8px;
|
|
|
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
|
|
+ }
|
|
|
+
|
|
|
+ .head {
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ gap: 10px;
|
|
|
+ color: #2c3e50;
|
|
|
+ }
|
|
|
+
|
|
|
+ p {
|
|
|
+ font-size: 16px;
|
|
|
+ color: #34495e;
|
|
|
+ line-height: 1.6;
|
|
|
+ text-indent: 2em;
|
|
|
+ }
|
|
|
+
|
|
|
+ .info {
|
|
|
+ background-color: #ecf0f1;
|
|
|
+ padding: 15px;
|
|
|
+ border-radius: 5px;
|
|
|
+ margin: 20px 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .info p {
|
|
|
+ margin: 5px 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .important {
|
|
|
+ color: #e74c3c;
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+
|
|
|
+ .footer {
|
|
|
+ font-size: 14px;
|
|
|
+ text-align: center;
|
|
|
+ color: #7f8c8d;
|
|
|
+ margin-top: 50px;
|
|
|
+ }
|
|
|
+ </style>
|
|
|
+ </head>
|
|
|
+
|
|
|
+ <body>
|
|
|
+ <div class="container">
|
|
|
+ <div class="head">
|
|
|
+ <h2>RunForge - 乐跑成功提醒</h2>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <p>尊敬的 ${data.name}:</p>
|
|
|
+ <p>RunForge已成功为您进行乐跑:</p>
|
|
|
+ <div class="info">
|
|
|
+ <p><strong>学号:</strong> ${data.account}</p>
|
|
|
+ <p><strong>跑区:</strong> ${data.pass_tit}</p>
|
|
|
+ <p><strong>跑步距离:</strong> ${data.distance} Km</p>
|
|
|
+ <p><strong>跑步时长:</strong> ${this.formatSecondsToMinSec(data.time)} Km</p>
|
|
|
+ <p><strong>平均配速:</strong> ${this.calculatePace(data.time, data.distance)}</p>
|
|
|
+ <p><strong>乐跑时间:</strong> ${this.stramptoTime(time)}</p>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <p class="important">请您开启了自动乐跑,请避免在其他设备上登录“智慧体育”小程序,否则将导致登录失效。</p>
|
|
|
+ <p class="important">如有疑问请联系RunForge客服。</p>
|
|
|
+ <p class="footer">Copyright © 2025 RunForge</p>
|
|
|
+ </div>
|
|
|
+ </body>
|
|
|
+
|
|
|
+ </html>`
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ async lepaoFail(email, data) {
|
|
|
+ const time = new Date().getTime()
|
|
|
+ await sendEmail(email, 'RunForge - 乐跑失败提醒',
|
|
|
+ `<html lang="zh-CN">
|
|
|
+
|
|
|
+ <head>
|
|
|
+ <meta charset="UTF-8">
|
|
|
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
+ <title>RunForge - 乐跑失败提醒</title>
|
|
|
+ <style>
|
|
|
+ body {
|
|
|
+ font-family: Arial, sans-serif;
|
|
|
+ background-color: #f4f4f4;
|
|
|
+ margin: 0;
|
|
|
+ padding: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .container {
|
|
|
+ width: 80%;
|
|
|
+ margin: 20px auto;
|
|
|
+ background-color: #fff;
|
|
|
+ padding: 20px;
|
|
|
+ border-radius: 8px;
|
|
|
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
|
|
+ }
|
|
|
+
|
|
|
+ .head {
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ gap: 10px;
|
|
|
+ color: #2c3e50;
|
|
|
+ }
|
|
|
+
|
|
|
+ p {
|
|
|
+ font-size: 16px;
|
|
|
+ color: #34495e;
|
|
|
+ line-height: 1.6;
|
|
|
+ text-indent: 2em;
|
|
|
+ }
|
|
|
+
|
|
|
+ .info {
|
|
|
+ background-color: #ecf0f1;
|
|
|
+ padding: 15px;
|
|
|
+ border-radius: 5px;
|
|
|
+ margin: 20px 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .info p {
|
|
|
+ margin: 5px 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ .important {
|
|
|
+ color: #e74c3c;
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+
|
|
|
+ .footer {
|
|
|
+ font-size: 14px;
|
|
|
+ text-align: center;
|
|
|
+ color: #7f8c8d;
|
|
|
+ margin-top: 50px;
|
|
|
+ }
|
|
|
+ </style>
|
|
|
+ </head>
|
|
|
+
|
|
|
+ <body>
|
|
|
+ <div class="container">
|
|
|
+ <div class="head">
|
|
|
+ <h2>RunForge - 乐跑失败提醒</h2>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <p>尊敬的 ${data.name}:</p>
|
|
|
+ <p>RunForge在尝试为您乐跑时遇到错误:</p>
|
|
|
+ <div class="info">
|
|
|
+ <p><strong>学号:</strong> ${data.account}</p>
|
|
|
+ <p><strong>时间:</strong> ${this.stramptoTime(time)}</p>
|
|
|
+ <p><strong>失败原因:</strong> ${data.reason}</p>
|
|
|
+ </div>
|
|
|
+ <p class="important">若登录失效请启动RunForge乐跑登录器重新登录“智慧体育”小程序。</p>
|
|
|
+ <p class="important">如有疑问请联系RunForge客服。</p>
|
|
|
+ <p class="footer">Copyright © 2025 RunForge</p>
|
|
|
+ </div>
|
|
|
+ </body>
|
|
|
+
|
|
|
+ </html>`
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ // 时长计算
|
|
|
+ formatSecondsToMinSec(totalSeconds) {
|
|
|
+ const minutes = Math.floor(totalSeconds / 60);
|
|
|
+ const seconds = totalSeconds % 60;
|
|
|
+
|
|
|
+ return `${minutes}分${seconds.toString().padStart(2, '0')}秒`;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 配速计算
|
|
|
+ calculatePace(seconds, kilometers) {
|
|
|
+ const paceInSeconds = seconds / kilometers;
|
|
|
+ const minutes = Math.floor(paceInSeconds / 60);
|
|
|
+ const remainingSeconds = Math.round(paceInSeconds % 60);
|
|
|
+
|
|
|
+ return `${minutes}'${remainingSeconds.toString().padStart(2, '0')}''`;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const EmailTemplate = new emailTemplate()
|
|
|
+module.exports = EmailTemplate
|