Browse Source

✨ feat: 新增账号更新接口

Pchen. 11 months ago
parent
commit
b1ac78d99a

+ 6 - 6
apis/Corn/StartAutoLepao.js

@@ -4,10 +4,10 @@ const lepao = require("../../lib/Lepao/Lepao.js").lepao
 
 
 const { BaseStdResponse } = require("../../BaseStdResponse");
 const { BaseStdResponse } = require("../../BaseStdResponse");
 
 
-class GetSeatMenu extends API {
+class StartAutoLepao extends API {
     constructor() {
     constructor() {
         super();
         super();
-        this.setPath('/Lepao/BeginLepao');
+        this.setPath('/Corn/StartAutoLepao');
         this.setMethod('GET');
         this.setMethod('GET');
     }
     }
 
 
@@ -18,16 +18,16 @@ class GetSeatMenu extends API {
             })
             })
 
 
             this.logger.info('开始执行自动乐跑任务')
             this.logger.info('开始执行自动乐跑任务')
-            let sql = 'SELECT name, create_user, student_num, token, uid, school_id FROM lepao_account WHERE \`state\` = 1'
+            let sql = 'SELECT name, create_user, student_num, token, uid, school_id, state FROM lepao_account WHERE auto_run = 1'
             let r = await db.query(sql)
             let r = await db.query(sql)
             if (!r)
             if (!r)
                 return this.logger.error('获取自动乐跑账号失败!')
                 return this.logger.error('获取自动乐跑账号失败!')
 
 
             for (const item of r) {
             for (const item of r) {
-                const { name, uuid, student_num, token, uid, school_id } = item;
+                const { name, create_user, student_num, token, uid, school_id, state } = item;
                 this.logger.info(`${name}(${student_num})开始乐跑`)
                 this.logger.info(`${name}(${student_num})开始乐跑`)
                 try {
                 try {
-                    await lepao.beginLepao(uuid, student_num, token, uid, school_id)
+                    await lepao.beginLepao(create_user, student_num, token, uid, school_id, state)
                     this.logger.info(`${name}(${student_num})乐跑完成`)
                     this.logger.info(`${name}(${student_num})乐跑完成`)
                 } catch (err) {
                 } catch (err) {
                     this.logger.error(`${name}(${student_num})乐跑失败:${err.message || err}`)
                     this.logger.error(`${name}(${student_num})乐跑失败:${err.message || err}`)
@@ -39,4 +39,4 @@ class GetSeatMenu extends API {
     }
     }
 }
 }
 
 
-module.exports.GetSeatMenu = GetSeatMenu;
+module.exports.StartAutoLepao = StartAutoLepao;

+ 2 - 2
apis/Lepao/SingleRun.js

@@ -27,7 +27,7 @@ class SingleRun extends API {
                 ...BaseStdResponse.ACCESS_DENIED
                 ...BaseStdResponse.ACCESS_DENIED
             })
             })
 
 
-        let sql = 'SELECT token, uid, school_id FROM lepao_account WHERE create_user = ? AND student_num = ?'
+        let sql = 'SELECT token, uid, school_id, state FROM lepao_account WHERE create_user = ? AND student_num = ?'
         let rows = await db.query(sql, [uuid, student_num])
         let rows = await db.query(sql, [uuid, student_num])
         if(!rows || rows.length === 0)
         if(!rows || rows.length === 0)
             return res.json({
             return res.json({
@@ -39,7 +39,7 @@ class SingleRun extends API {
             ...BaseStdResponse.OK
             ...BaseStdResponse.OK
         })
         })
 
 
-        lepao.beginLepao(uuid, student_num, rows[0].token, rows[0].uid, rows[0].school_id)
+        lepao.beginLepao(uuid, student_num, rows[0].token, rows[0].uid, rows[0].school_id, rows[0].state)
 
 
     } catch(err) {
     } catch(err) {
         this.logger.error(`手动乐跑失败!${err.stack}`);
         this.logger.error(`手动乐跑失败!${err.stack}`);

+ 78 - 0
apis/Lepao/UpdateAccount.js

@@ -0,0 +1,78 @@
+const API = require("../../lib/API.js")
+const db = require("../../plugin/DataBase/db.js")
+const axios = require('axios')
+const EmailTemplate = require('../../plugin/Email/emailTemplate')
+const config = require('../../config.json')
+const { BaseStdResponse } = require("../../BaseStdResponse.js")
+
+// 客户端上传数据接口
+class UpdateAccount extends API {
+    constructor() {
+        super();
+
+        this.setPath('/Lepao/UpdateAccount')
+        this.setMethod('POST')
+    }
+
+    async onRequest(req, res) {
+        let { data } = req.body
+
+        if ([data].some(value => value === '' || value === null || value === undefined))
+            return res.json({
+                ...BaseStdResponse.MISSING_PARAMETER,
+                endpoint: 1513126
+            })
+
+        try {
+            const endpoint = config.runpy + '/decrypted_data'
+            const resData = await axios.post(endpoint, { data })
+            const userData = resData.data
+            if (userData?.code !== 200 || !userData.data)
+                return res.json({
+                    ...BaseStdResponse.ERR,
+                    msg: '无法解析用户数据,请重试'
+                })
+            const { uid, student_num, school_id, token } = userData.data
+            if ([uid, student_num, school_id, token].some(value => value === '' || value === null || value === undefined))
+                return res.json({
+                    ...BaseStdResponse.ERR,
+                    msg: '未提取出用户登录信息,请重试'
+                })
+
+            let findSql = 'SELECT email, name FROM lepao_account WHERE student_num = ?'
+            let findRows = await db.query(findSql, [student_num])
+            if (!findRows)
+                return res.json({
+                    ...BaseStdResponse.ERR,
+                    msg: '无法解析用户数据,请重试'
+                })
+            if(findRows.length === 0)
+                return res.json({
+                    ...BaseStdResponse.ERR,
+                    msg: '该乐跑账号尚未在RunForge系统中添加,请先前往 https://lepao.ctbu.top/ 添加你的账户'
+                })
+            let updateSql = 'UPDATE lepao_account SET uid = ?, token = ?, school_id = ?, state = 1 WHERE student_num = ?'
+            let updateRows = await db.query(updateSql, [uid, token, school_id, student_num])
+
+            if(updateRows && updateRows.affectedRows > 0) {
+                res.json({
+                    ...BaseStdResponse.OK,
+                    data: {
+                        name: findRows[0].name,
+                        account: student_num
+                    }
+                })
+                let emailData = {
+                    name: findRows[0].name,
+                    account: student_num
+                }
+                
+                await EmailTemplate.updateSuccess(findRows[0].email, emailData)
+            }
+        } catch (error) {
+
+        }
+    }
+}
+
+module.exports.UpdateAccount = UpdateAccount;

+ 37 - 5
lib/Lepao/Lepao.js

@@ -46,7 +46,8 @@ class Lepao {
         return randomPath.id
         return randomPath.id
     }
     }
 
 
-    async beginLepao(uuid, account, token, uid, school_id) {
+    // 乐跑入口函数
+    async beginLepao(uuid, account, token, uid, school_id, state) {
         try {
         try {
             const userPermissionSql = 'SELECT vip, lepao_count FROM users WHERE uuid = ?'
             const userPermissionSql = 'SELECT vip, lepao_count FROM users WHERE uuid = ?'
             const userPermissionData = await db.query(userPermissionSql, [uuid])
             const userPermissionData = await db.query(userPermissionSql, [uuid])
@@ -55,12 +56,32 @@ class Lepao {
             if (userPermissionData[0].lepao_count < 1)
             if (userPermissionData[0].lepao_count < 1)
                 throw new Error('用户乐跑次数不足,请购买乐跑套餐!')
                 throw new Error('用户乐跑次数不足,请购买乐跑套餐!')
 
 
+            if(state !== 1) {
+                return this.sendFailEmail(account, '登录已过期,请尝试使用登录器重新登录')
+            }
+
             // 获取路径 ID
             // 获取路径 ID
             const path_id = await this.getPath(account, userPermissionData[0].vip)
             const path_id = await this.getPath(account, userPermissionData[0].vip)
 
 
+            // 更换跑区
+            const zoneUrl = this.runpy + '/set_zone'
+            const ossData = { uid, token, school_id, student_id: account, random_id: path_id }
+
+            try {
+                const zoneRes = await axios.post(zoneUrl, ossData)
+                const { data } = zoneRes
+
+                if (!data || data.status !== 1 || !data.data) {
+                    this.setStatusFail(account)
+                    throw new Error(data?.info || '未知错误,请尝试重新登录')
+                }
+
+            } catch (error) {
+                throw error
+            }
+
             // 上传 OSS
             // 上传 OSS
             const ossUrl = this.runpy + '/upload_oss_file'
             const ossUrl = this.runpy + '/upload_oss_file'
-            const ossData = { uid, token, school_id, student_id: account, random_id: path_id }
             let oss_path
             let oss_path
 
 
             try {
             try {
@@ -71,6 +92,7 @@ class Lepao {
                 }
                 }
                 oss_path = data.oss_path
                 oss_path = data.oss_path
             } catch (error) {
             } catch (error) {
+                this.setStatusFail(account)
                 this.logger.error(`上传OSS记录失败,请检查登录是否过期。${error.stack || error.message}`)
                 this.logger.error(`上传OSS记录失败,请检查登录是否过期。${error.stack || error.message}`)
                 throw new Error('请检查登录是否过期')
                 throw new Error('请检查登录是否过期')
             }
             }
@@ -95,6 +117,7 @@ class Lepao {
 
 
             console.log(lepaoData)
             console.log(lepaoData)
 
 
+            // 绑定乐跑数据
             const lepaoUrl = this.runpy + '/bind_data'
             const lepaoUrl = this.runpy + '/bind_data'
             try {
             try {
                 const lepaoRes = await axios.post(lepaoUrl, lepaoData)
                 const lepaoRes = await axios.post(lepaoUrl, lepaoData)
@@ -103,12 +126,13 @@ class Lepao {
                 console.log(data)
                 console.log(data)
 
 
                 if (!data || data.status !== 1 || !data.data) {
                 if (!data || data.status !== 1 || !data.data) {
-                    throw new Error(data.info || '未知错误,请尝试重新登录')
+                    this.setStatusFail(account)
+                    throw new Error(data?.info || '未知错误,请尝试重新登录')
                 }
                 }
 
 
                 await this.addRecord(account, data.data)
                 await this.addRecord(account, data.data)
                 if (data.data.record_failed_reason === '') {
                 if (data.data.record_failed_reason === '') {
-                    await this.sendSuccessEmail(account, data)
+                    await this.sendSuccessEmail(account, data.data)
                 } else {
                 } else {
                     await this.sendFailEmail(account, data.data.record_failed_reason)
                     await this.sendFailEmail(account, data.data.record_failed_reason)
                     await this.lepaoFail(uuid)
                     await this.lepaoFail(uuid)
@@ -116,7 +140,6 @@ class Lepao {
 
 
             } catch (error) {
             } catch (error) {
                 await this.lepaoFail(uuid)
                 await this.lepaoFail(uuid)
-
                 throw error
                 throw error
             }
             }
 
 
@@ -183,6 +206,15 @@ class Lepao {
             this.logger.error(`返还用户 ${uuid} 乐跑次数时出错: ${error.stack || error.message}`)
             this.logger.error(`返还用户 ${uuid} 乐跑次数时出错: ${error.stack || error.message}`)
         }
         }
     }
     }
+
+    async setStatusFail(account) {
+        try {
+            const sql = 'UPDATE lepao_account SET state = 0 WHERE student_num  = ?'
+            await db.query(sql, [account])
+        } catch (error) {
+            this.logger.error(`设置用户 ${account} state时出错: ${error.stack || error.message}`)
+        }
+    }
 }
 }
 
 
 const lepao = new Lepao()
 const lepao = new Lepao()

+ 93 - 3
plugin/Email/emailTemplate.js

@@ -177,6 +177,94 @@ class emailTemplate {
         )
         )
     }
     }
 
 
+    async updateSuccess(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>您已成功更新乐跑账号登录信息:</p>
+                    <div class="info">
+                        <p><strong>学号:</strong> ${data.account}</p>
+                        <p><strong>更新时间:</strong> ${this.stramptoTime(new Date().getTime())}</p>
+
+                    </div>
+
+                    <p class="important">请避免在其他设备上登录“智慧体育”小程序,否则将导致登录失效,届时需要重新进行登录操作。</p>
+                    <p class="important">如有疑问请联系RunForge客服。</p>
+                    <p class="footer">Copyright © 2025 RunForge</p>
+                </div>
+            </body>
+
+            </html>`
+        )
+    }
+
     async lepaoSuccess(email, data) {
     async lepaoSuccess(email, data) {
         await sendEmail(email, 'RunForge - 乐跑成功提醒',
         await sendEmail(email, 'RunForge - 乐跑成功提醒',
             `<html lang="zh-CN">
             `<html lang="zh-CN">
@@ -253,9 +341,7 @@ class emailTemplate {
                         <p><strong>学号:</strong> ${data.account}</p>
                         <p><strong>学号:</strong> ${data.account}</p>
                         <p><strong>跑区:</strong> ${data.pass_tit}</p>
                         <p><strong>跑区:</strong> ${data.pass_tit}</p>
                         <p><strong>跑步距离:</strong> ${data.distance} Km</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>
                     </div>
 
 
                     <p class="important">请您开启了自动乐跑,请避免在其他设备上登录“智慧体育”小程序,否则将导致登录失效。</p>
                     <p class="important">请您开启了自动乐跑,请避免在其他设备上登录“智慧体育”小程序,否则将导致登录失效。</p>
@@ -268,6 +354,10 @@ class emailTemplate {
         )
         )
     }
     }
 
 
+    // <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>
+
     async lepaoFail(email, data) {
     async lepaoFail(email, data) {
         const time = new Date().getTime()
         const time = new Date().getTime()
         await sendEmail(email, 'RunForge - 乐跑失败提醒',
         await sendEmail(email, 'RunForge - 乐跑失败提醒',