Browse Source

更新支付接口

Pchen. 11 months ago
parent
commit
db687b59ac

+ 0 - 1
.gitignore

@@ -1,4 +1,3 @@
 node_modules/
 node_modules/
 *.log
 *.log
-config.json
 uploads/
 uploads/

+ 2 - 1
apis/Goods/Admin/GetGoods.js

@@ -50,6 +50,7 @@ class GetProduct extends API {
                 a.lepao_count,
                 a.lepao_count,
                 a.create_time,
                 a.create_time,
                 a.update_time,
                 a.update_time,
+                a.limit,
                 u1.username AS create_user,
                 u1.username AS create_user,
                 u2.username AS update_user
                 u2.username AS update_user
             FROM
             FROM
@@ -75,7 +76,7 @@ class GetProduct extends API {
 
 
         res.json({
         res.json({
             ...BaseStdResponse.OK,
             ...BaseStdResponse.OK,
-            data: rows
+            data: rows[0]
         })
         })
     }
     }
 }
 }

+ 1 - 0
apis/Goods/Admin/GetGoodsList.js

@@ -55,6 +55,7 @@ class GetProductList extends API {
                 a.views,
                 a.views,
                 a.create_time,
                 a.create_time,
                 a.update_time,
                 a.update_time,
+                a.limit,
                 u1.username AS create_user,
                 u1.username AS create_user,
                 u2.username AS update_user
                 u2.username AS update_user
             FROM
             FROM

+ 3 - 2
apis/Goods/GetGoods.js

@@ -25,7 +25,8 @@ class GetProduct extends API {
                 name,
                 name,
                 content,
                 content,
                 price,
                 price,
-                num
+                num,
+                \`limit\`
             FROM
             FROM
                 goods 
                 goods 
             WHERE id = ? AND state = 1
             WHERE id = ? AND state = 1
@@ -41,7 +42,7 @@ class GetProduct extends API {
 
 
         res.json({
         res.json({
             ...BaseStdResponse.OK,
             ...BaseStdResponse.OK,
-            data: rows
+            data: rows[0]
         })
         })
 
 
         sql = 'UPDATE goods SET views = views + 1 WHERE id = ?'
         sql = 'UPDATE goods SET views = views + 1 WHERE id = ?'

+ 8 - 52
apis/Goods/GetGoodsList.js

@@ -3,97 +3,53 @@ const db = require("../../plugin/DataBase/db");
 const { BaseStdResponse } = require("../../BaseStdResponse");
 const { BaseStdResponse } = require("../../BaseStdResponse");
 
 
 // 获取产品列表
 // 获取产品列表
-class GetProductList extends API {
+class GetGoodsList extends API {
     constructor() {
     constructor() {
         super();
         super();
 
 
         this.setPath('/Goods/List')
         this.setPath('/Goods/List')
-        this.setMethod('post')
+        this.setMethod('get')
     }
     }
 
 
     async onRequest(req, res) {
     async onRequest(req, res) {
-        let { keyword, pagesize, current } = req.body;
-
-        if ([pagesize, current].some(value => value === '' || value === null || value === undefined))
-            return res.json({
-                ...BaseStdResponse.MISSING_PARAMETER
-            })
-
-        // 校验分页参数
-        if (isNaN(pagesize) || pagesize <= 0) {
-            return res.json({
-                ...BaseStdResponse.ERR,
-                msg: '参数错误'
-            })
-        }
-
-        if (isNaN(current) || current <= 0) {
-            return res.json({
-                ...BaseStdResponse.ERR,
-                msg: '参数错误'
-            })
-        }
-
-        // 计算分页的 offset
-        const offset = (current - 1) * pagesize
+        let { keyword } = req.query
 
 
         let sql = `
         let sql = `
             SELECT
             SELECT
                 id,
                 id,
                 name,
                 name,
                 price,
                 price,
-                num
+                num,
+                \`limit\`
             FROM
             FROM
                 goods
                 goods
             WHERE state = 1 
             WHERE state = 1 
         `
         `
 
 
-        let countSql = `
-            SELECT COUNT(*) AS total
-            FROM goods
-            WHERE 1 = 1
-        `
-
         let params = []
         let params = []
-        let countParams = []
 
 
         if (keyword) {
         if (keyword) {
             sql += ` AND name LIKE ?`
             sql += ` AND name LIKE ?`
-            countSql += ` AND name LIKE ?`
             params.push(`%${keyword}%`)
             params.push(`%${keyword}%`)
-            countParams.push(`%${keyword}%`)
         }
         }
 
 
         sql += `
         sql += `
             ORDER BY 
             ORDER BY 
                 id DESC
                 id DESC
-            LIMIT ? OFFSET ?;
         `
         `
-        params.push(String(pagesize), String(offset))
-
         let rows = await db.query(sql, params)
         let rows = await db.query(sql, params)
-        let countResult = await db.query(countSql, countParams)
 
 
-        if (!rows || !countResult)
+        if (!rows)
             return res.json({
             return res.json({
                 ...BaseStdResponse.ERR,
                 ...BaseStdResponse.ERR,
                 msg: '获取商品失败!'
                 msg: '获取商品失败!'
             })
             })
 
 
-        let total = countResult[0].total
-        const totalPages = Math.ceil(total / pagesize)
-
         res.json({
         res.json({
             ...BaseStdResponse.OK,
             ...BaseStdResponse.OK,
-            data: rows,
-            pagination: {
-                current: current,
-                pagesize: pagesize,
-                total: total,
-                totalPages: totalPages
-            }
+            data: rows
         })
         })
     }
     }
 }
 }
 
 
-module.exports.GetProductList = GetProductList;
+module.exports.GetGoodsList = GetGoodsList;

+ 9 - 4
apis/Lepao/AddAccount.js

@@ -12,9 +12,9 @@ class GetType extends API {
     }
     }
 
 
     async onRequest(req, res) {
     async onRequest(req, res) {
-        let { uuid, session, student_num } = req.body
+        let { uuid, session, student_num, name, email, id } = req.body
 
 
-        if ([uuid, session, student_num].some(value => value === '' || value === null || value === undefined))
+        if ([uuid, session, student_num, name, email].some(value => value === '' || value === null || value === undefined))
             return res.json({
             return res.json({
                 ...BaseStdResponse.MISSING_PARAMETER,
                 ...BaseStdResponse.MISSING_PARAMETER,
                 endpoint: 1513126
                 endpoint: 1513126
@@ -29,8 +29,13 @@ class GetType extends API {
 
 
         let sql, r
         let sql, r
 
 
-        sql = 'INSERT INTO lepao_account (student_num, create_user, create_time) VALUES (?, ?, ?, ?)'
-        r = await db.query(sql, [student_num, uuid, time])
+        if (!id) {
+            sql = 'INSERT INTO lepao_account (student_num, name, email, create_user, create_time) VALUES (?, ?, ?, ?, ?)'
+            r = await db.query(sql, [student_num, name, email, uuid, time])
+        } else {
+            sql = 'UPDATE lepao_account SET student_num = ?, name = ?, email = ?,  update_time = ? WHERE id = ?'
+            r = await db.query(sql, [student_num, name, email, time, id])
+        }
 
 
         try {
         try {
             if (r && r.affectedRows > 0) {
             if (r && r.affectedRows > 0) {

+ 53 - 0
apis/Lepao/ChangeAutoRun.js

@@ -0,0 +1,53 @@
+const API = require("../../lib/API.js");
+const db = require("../../plugin/DataBase/db.js");
+const { BaseStdResponse } = require("../../BaseStdResponse.js");
+const AccessControl = require("../../lib/AccessControl.js");
+
+class ChangeAutoRun extends API {
+    constructor() {
+        super();
+
+        this.setPath('/Lepao/ChangeAutoRun')
+        this.setMethod('GET')
+    }
+
+    async onRequest(req, res) {
+        let { uuid, session, id } = req.query
+
+        if ([uuid, session, id].some(value => value === '' || value === null || value === undefined)) 
+            return res.json({
+                ...BaseStdResponse.MISSING_PARAMETER,
+                endpoint: 1513126
+            });
+
+        if (!await AccessControl.checkSession(uuid, session)) 
+            return res.status(401).json({
+                ...BaseStdResponse.ACCESS_DENIED
+            })
+        
+        let sql = 'UPDATE lepao_account SET auto_run = 1 - auto_run WHERE id = ?';
+        try {
+            let r = await db.query(sql, [id]);
+
+            if (r && r.affectedRows > 0) {
+                res.json({
+                    ...BaseStdResponse.OK
+                });
+            } else {
+                res.json({
+                    ...BaseStdResponse.ERR,
+                    endpoint: 7894378,
+                    msg: '切换自动乐跑状态失败!未找到对应数据或数据库未更新'
+                });
+            }
+        } catch (err) {
+            this.logger.error(`切换自动乐跑状态失败!${err.stack}`);
+            res.json({
+                ...BaseStdResponse.ERR,
+                msg: "切换自动乐跑状态失败!数据库异常"
+            });
+        }
+    }
+}
+
+module.exports.ChangeAutoRun = ChangeAutoRun;

+ 3 - 1
apis/Lepao/GetAccount.js

@@ -28,12 +28,13 @@ class GetAccount extends API {
         let sql = `
         let sql = `
                 SELECT 
                 SELECT 
                     a.id,
                     a.id,
-                    a.username,
                     a.name,
                     a.name,
                     a.student_num,
                     a.student_num,
                     a.create_time,
                     a.create_time,
                     a.update_time,
                     a.update_time,
                     a.state,
                     a.state,
+                    a.email,
+                    a.auto_run,
                     u.username AS create_user
                     u.username AS create_user
                 FROM 
                 FROM 
                     lepao_account a
                     lepao_account a
@@ -43,6 +44,7 @@ class GetAccount extends API {
                     a.create_user = u.uuid
                     a.create_user = u.uuid
                 WHERE 
                 WHERE 
                     a.create_user = ?
                     a.create_user = ?
+                ORDER BY id DESC
             `
             `
 
 
         let rows = await db.query(sql, [uuid])
         let rows = await db.query(sql, [uuid])

+ 60 - 0
apis/Lepao/GetLepaoRecords.js

@@ -0,0 +1,60 @@
+const API = require("../../lib/API.js");
+const db = require("../../plugin/DataBase/db.js");
+const { BaseStdResponse } = require("../../BaseStdResponse.js");
+const AccessControl = require("../../lib/AccessControl.js");
+
+class GetLepaoRecords extends API {
+    constructor() {
+        super();
+
+        this.setPath('/Lepao/Records')
+        this.setMethod('GET')
+    }
+
+    async onRequest(req, res) {
+        let { uuid, session } = req.query
+
+        if ([uuid, session].some(value => value === '' || value === null || value === undefined))
+            return res.json({
+                ...BaseStdResponse.MISSING_PARAMETER,
+                endpoint: 1513126
+            })
+
+        if (!await AccessControl.checkSession(uuid, session))
+            return res.status(401).json({
+                ...BaseStdResponse.ACCESS_DENIED
+            })
+
+        let sql = `
+                SELECT 
+                    r.time,
+                    r.lepao_account,
+                    r.result,
+                    a.name
+                FROM 
+                    lepao_record r
+                JOIN 
+                    lepao_account a
+                ON 
+                    r.lepao_account = a.student_num
+                WHERE 
+                    a.create_user = ?
+                ORDER BY 
+                    r.id DESC
+
+                            `
+        let rows = await db.query(sql, [uuid])
+
+        if (!rows)
+            return res.json({
+                ...BaseStdResponse.DATABASE_ERR
+            })
+
+        res.json({
+            ...BaseStdResponse.OK,
+            data: rows
+        })
+    }
+}
+
+module.exports.GetLepaoRecords = GetLepaoRecords;

+ 1 - 1
apis/Order/CallBack.js

@@ -31,7 +31,7 @@ class CallBack extends API {
             money, name, out_trade_no, pid, trade_no, trade_status, type
             money, name, out_trade_no, pid, trade_no, trade_status, type
         }
         }
         const sortedKeys = Object.keys(rawParams).sort()
         const sortedKeys = Object.keys(rawParams).sort()
-        const preSignStr = sortedKeys.map(key => `${key}=${rawParams[key]}`).join('&') + `&key=${PAYMENT_KEY}`
+        const preSignStr = sortedKeys.map(key => `${key}=${rawParams[key]}`).join('&') + PAYMENT_KEY
         const localSign = crypto.createHash('md5').update(preSignStr, 'utf8').digest('hex')
         const localSign = crypto.createHash('md5').update(preSignStr, 'utf8').digest('hex')
 
 
         if (localSign.toLowerCase() !== sign.toLowerCase()) {
         if (localSign.toLowerCase() !== sign.toLowerCase()) {

+ 33 - 22
apis/Order/CreateOrder.js

@@ -1,5 +1,6 @@
 const API = require("../../lib/API.js")
 const API = require("../../lib/API.js")
 const db = require("../../plugin/DataBase/db.js")
 const db = require("../../plugin/DataBase/db.js")
+const Redis = require('../../plugin/DataBase/Redis')
 const { BaseStdResponse } = require("../../BaseStdResponse.js")
 const { BaseStdResponse } = require("../../BaseStdResponse.js")
 const AccessControl = require("../../lib/AccessControl.js")
 const AccessControl = require("../../lib/AccessControl.js")
 const crypto = require('crypto')
 const crypto = require('crypto')
@@ -8,15 +9,17 @@ const config = require('../../config.json')
 function generateOrderId() {
 function generateOrderId() {
     const now = new Date()
     const now = new Date()
     const pad = (n, w = 2) => n.toString().padStart(w, '0')
     const pad = (n, w = 2) => n.toString().padStart(w, '0')
-    return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}`
-        + `${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`
-        + `${pad(now.getMilliseconds(), 3)}`
+    return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}` +
+        `${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}` +
+        `${pad(now.getMilliseconds(), 3)}`
 }
 }
 
 
 function generatePaymentSign(params, key) {
 function generatePaymentSign(params, key) {
-    const sorted = Object.keys(params).sort();
-    const query = sorted.map(k => `${k}=${params[k]}`).join('&') + `&key=${key}`;
-    return crypto.createHash('md5').update(query, 'utf8').digest('hex');
+    const sorted = Object.keys(params).sort()
+    const query = sorted.map(k => `${k}=${params[k]}`).join('&') + key
+    console.log(query)
+    
+    return crypto.createHash('md5').update(query, 'utf8').digest('hex')
 }
 }
 
 
 class CreateOrder extends API {
 class CreateOrder extends API {
@@ -44,7 +47,6 @@ class CreateOrder extends API {
         }
         }
 
 
         try {
         try {
-            // 查询商品信息
             const goodsSql = 'SELECT name, price, num, state FROM goods WHERE id = ?'
             const goodsSql = 'SELECT name, price, num, state FROM goods WHERE id = ?'
             const goodsRows = await db.query(goodsSql, [goods_id])
             const goodsRows = await db.query(goodsSql, [goods_id])
 
 
@@ -65,59 +67,68 @@ class CreateOrder extends API {
                 })
                 })
             }
             }
 
 
-            const createTime = new Date().getTime()
+            const createTime = Date.now()
             const orderId = generateOrderId()
             const orderId = generateOrderId()
 
 
             const insertSql = `
             const insertSql = `
                 INSERT INTO orders (orderId, create_user, create_time, goods_id, price, pay_type)
                 INSERT INTO orders (orderId, create_user, create_time, goods_id, price, pay_type)
                 VALUES (?, ?, ?, ?, ?, ?)
                 VALUES (?, ?, ?, ?, ?, ?)
             `
             `
-            const insertParams = [orderId, uuid, createTime, goods_id, goods.price, pay_type]
-            const result = await db.query(insertSql, insertParams)
+            const result = await db.query(insertSql, [
+                orderId, uuid, createTime, goods_id, goods.price, pay_type
+            ])
 
 
             const updateSql = 'UPDATE goods SET num = num - 1 WHERE id = ?'
             const updateSql = 'UPDATE goods SET num = num - 1 WHERE id = ?'
             await db.query(updateSql, [goods_id])
             await db.query(updateSql, [goods_id])
 
 
             if (result && result.affectedRows > 0) {
             if (result && result.affectedRows > 0) {
-                const paymentConfig = config.pay
+                const paymentConfig = config.pay || {}
+
+                if (!paymentConfig.pid || !paymentConfig.url || !paymentConfig.key || !paymentConfig.return_url) {
+                    return res.json({
+                        ...BaseStdResponse.ERR,
+                        msg: '支付配置错误,请联系管理员'
+                    })
+                }
 
 
                 const payParams = {
                 const payParams = {
                     pid: paymentConfig.pid,
                     pid: paymentConfig.pid,
                     type: pay_type,
                     type: pay_type,
                     out_trade_no: orderId,
                     out_trade_no: orderId,
                     notify_url: config.url + '/Order/CallBack',
                     notify_url: config.url + '/Order/CallBack',
-                    return_url: paymentConfig.return_url,
+                    return_url: paymentConfig.return_url + orderId,
                     name: goods.name,
                     name: goods.name,
-                    money: goods.price.toFixed(2),
-                    sitename: paymentConfig.sitename
+                    money: goods.price
                 }
                 }
 
 
-                const sign = generatePaymentSign(payParams, paymentConfig.key);
+                const sign = generatePaymentSign(payParams, paymentConfig.key)
                 payParams.sign = sign
                 payParams.sign = sign
                 payParams.sign_type = 'MD5'
                 payParams.sign_type = 'MD5'
 
 
-                // 构造支付URL
-                const queryString = new URLSearchParams(payParams).toString();
-                const payUrl = `${paymentConfig.url}?${queryString}`;
+                await Redis.set(`payData:${orderId}`, JSON.stringify(payParams), {
+                    EX: 300
+                })
 
 
                 return res.json({
                 return res.json({
                     ...BaseStdResponse.OK,
                     ...BaseStdResponse.OK,
                     id: orderId,
                     id: orderId,
-                    payUrl
+                    pay: {
+                        payUrl: paymentConfig.url,
+                        payData: payParams
+                    }
                 })
                 })
             } else {
             } else {
                 return res.json({
                 return res.json({
                     ...BaseStdResponse.ERR,
                     ...BaseStdResponse.ERR,
-                    msg: '创建订单失败!请联系客服',
+                    msg: '创建订单失败',
                     endpoint: 7894378
                     endpoint: 7894378
                 })
                 })
             }
             }
-
         } catch (err) {
         } catch (err) {
             this.logger.error(`创建订单失败!${err.stack}`)
             this.logger.error(`创建订单失败!${err.stack}`)
             return res.json({
             return res.json({
                 ...BaseStdResponse.ERR,
                 ...BaseStdResponse.ERR,
-                msg: "创建订单失败!请联系客服",
+                msg: "创建订单异常,请联系管理员"
             })
             })
         }
         }
     }
     }

+ 80 - 35
apis/Order/GetOrderDetail.js

@@ -1,5 +1,7 @@
 const API = require("../../lib/API.js");
 const API = require("../../lib/API.js");
 const db = require("../../plugin/DataBase/db.js");
 const db = require("../../plugin/DataBase/db.js");
+const Redis = require('../../plugin/DataBase/Redis');
+const config = require('../../config.json');
 const { BaseStdResponse } = require("../../BaseStdResponse.js");
 const { BaseStdResponse } = require("../../BaseStdResponse.js");
 const AccessControl = require("../../lib/AccessControl.js");
 const AccessControl = require("../../lib/AccessControl.js");
 
 
@@ -7,58 +9,101 @@ class GetAccount extends API {
     constructor() {
     constructor() {
         super();
         super();
 
 
-        this.setPath('/JW/Account')
-        this.setMethod('GET')
+        this.setPath('/Order/Detail');
+        this.setMethod('GET');
+    }
+
+    async getOrderDetail(uuid, orderId) {
+        const sql = `
+            SELECT 
+                a.orderId,
+                a.create_time,
+                a.price,
+                a.state,
+                a.pay_id,
+                a.pay_type,
+                a.pay_time,
+                g.name
+            FROM 
+                orders a
+            LEFT JOIN 
+                goods g 
+            ON 
+                a.goods_id = g.id
+            WHERE 
+                a.create_user = ?
+            AND 
+                a.orderId = ?
+        `;
+        const rows = await db.query(sql, [uuid, orderId]);
+        return rows?.[0] || null;
     }
     }
 
 
     async onRequest(req, res) {
     async onRequest(req, res) {
-        let { uuid, session, orderId } = req.query
+        const { uuid, session, orderId } = req.query;
 
 
-        if ([uuid, session, orderId].some(value => value === '' || value === null || value === undefined))
+        if (!uuid || !session || !orderId) {
             return res.json({
             return res.json({
                 ...BaseStdResponse.MISSING_PARAMETER,
                 ...BaseStdResponse.MISSING_PARAMETER,
                 endpoint: 1513126
                 endpoint: 1513126
-            })
+            });
+        }
 
 
-        if (!await AccessControl.checkSession(uuid, session))
+        if (!await AccessControl.checkSession(uuid, session)) {
             return res.status(401).json({
             return res.status(401).json({
                 ...BaseStdResponse.ACCESS_DENIED
                 ...BaseStdResponse.ACCESS_DENIED
-            })
-
-        let sql = `
-                SELECT 
-                    a.orderId,
-                    a.create_time,
-                    a.price,
-                    a.state,
-                    a.pay_id,
-                    a.pay_type,
-                    a.pay_time,
-                    a.state,
-                    g.name
-                FROM 
-                    orders a
-                LEFT JOIN 
-                    goods g 
-                ON 
-                    a.goods_id = g.id
-                WHERE 
-                    a.create_user = ?
-            `
+            });
+        }
 
 
-        let rows = await db.query(sql, [uuid])
+        let order = await this.getOrderDetail(uuid, orderId);
 
 
-        if (!rows || rows.length !== 1)
+        if (!order) {
             return res.json({
             return res.json({
                 ...BaseStdResponse.ERR,
                 ...BaseStdResponse.ERR,
                 msg: '订单获取失败!'
                 msg: '订单获取失败!'
-            })
+            });
+        }
+
+        // 订单未支付
+        if (order.state === 0) {
+            let payData = await Redis.get(`payData:${order.orderId}`);
+            if (!payData) {
+                // 标记为过期订单
+                await db.query('UPDATE orders SET state = 3 WHERE orderId = ?', [order.orderId]);
+
+                // 重新获取订单信息(更新后的)
+                order = await this.getOrderDetail(uuid, orderId);
+                if (!order) {
+                    return res.json({
+                        ...BaseStdResponse.ERR,
+                        msg: '订单获取失败!'
+                    });
+                }
+
+                return res.json({
+                    ...BaseStdResponse.OK,
+                    data: order
+                });
+            }
+
+            const payUrl = config.pay.url
+
+            return res.json({
+                ...BaseStdResponse.OK,
+                data: order,
+                payData: {
+                    payUrl,
+                    payData: JSON.parse(payData)
+                }
+            });
+        }
 
 
-        res.json({
+        // 订单已支付或其他状态
+        return res.json({
             ...BaseStdResponse.OK,
             ...BaseStdResponse.OK,
-            data: rows[0]
-        })
+            data: order
+        });
     }
     }
 }
 }
 
 
-module.exports.GetAccount = GetAccount;
+module.exports.GetAccount = GetAccount;

+ 106 - 0
apis/Upload/UploadAvatar.js

@@ -0,0 +1,106 @@
+const API = require("../../lib/API");
+const { v4: uuidv4 } = require('uuid');
+const { BaseStdResponse } = require("../../BaseStdResponse");
+const db = require("../../plugin/DataBase/db");
+const AccessControl = require("../../lib/AccessControl");
+const multer = require('multer');
+const path = require('path');
+
+const { url } = require("../../config.json")
+
+// 配置Multer的存储选项
+const storage = multer.diskStorage({
+    destination: (req, file, cb) => {
+        cb(null, 'uploads/');
+    },
+    filename: (req, file, cb) => {
+        const fileName = uuidv4();
+        const fileExtension = path.extname(file.originalname);
+        cb(null, `${fileName}${fileExtension}`);
+    }
+});
+
+// 限制文件类型
+const fileFilter = (req, file, cb) => {
+    // 只接受以下扩展名的图片文件
+    const allowedTypes = /jpeg|jpg|png|gif/;
+    const extname = allowedTypes.test(path.extname(file.originalname).toLowerCase());
+    const mimetype = allowedTypes.test(file.mimetype);
+
+    if (extname && mimetype) {
+        return cb(null, true);
+    } else {
+        cb(new Error('只允许上传图片文件 (jpeg, jpg, png, gif)'));
+    }
+};
+
+// 初始化Multer中间件
+const upload = multer({
+    storage: storage,
+    fileFilter: fileFilter,
+    limits: { fileSize: 3 * 1024 * 1024 } // 限制文件大小为3MB
+}).single('upload');
+
+class UploadAvatar extends API {
+    constructor() {
+        super();
+
+        this.setMethod("POST");
+        this.setPath("/UploadAvatar");
+    }
+
+    async onRequest(req, res) {
+        // 使用Multer中间件处理文件上传
+        upload(req, res, async (err) => {
+            if (err) {
+                this.logger.error(`图片上传失败!${err.stack || ''}`)
+                return res.json({
+                    ...BaseStdResponse.ERR,
+                    msg: '图片上传失败!'
+                });
+            }
+
+            let { uuid, session } = req.body
+
+            if ([uuid, session].some(value => value === '' || value === null || value === undefined)) {
+                return res.json({
+                    ...BaseStdResponse.MISSING_PARAMETER,
+                    endpoint: 1513126
+                });
+            }
+
+            if (!await AccessControl.checkSession(uuid, session)) {
+                return res.status(401).json({
+                    ...BaseStdResponse.ACCESS_DENIED,
+                    endpoint: 481545
+                });
+            }
+
+            if (!req.file) {
+                return res.json({
+                    ...BaseStdResponse.MISSING_PARAMETER,
+                    msg: '请上传图片文件'
+                });
+            }
+
+            const picturePath = url + req.file.filename; // 获取文件路径
+
+            let sql = 'UPDATE users SET avatar = ? WHERE uuid = ?'
+            let r = await db.query(sql, [picturePath, uuid])
+            if (r && r.affectedRows > 0)
+                return res.json({
+                    ...BaseStdResponse.OK,
+                    data: {
+                        picturePath
+                    }
+                });
+
+            res.json({
+                ...BaseStdResponse.ERR,
+                msg: '上传头像失败!'
+            })
+        });
+    }
+}
+
+module.exports.UploadAvatar = UploadAvatar;

+ 65 - 0
apis/User/BindEmail.js

@@ -0,0 +1,65 @@
+const API = require("../../lib/API");
+const db = require("../../plugin/DataBase/db");
+const { BaseStdResponse } = require("../../BaseStdResponse");
+const Redis = require('../../plugin/DataBase/Redis');
+const sendEmail = require('../../plugin/Email/Email');
+const AccessControl = require("../../lib/AccessControl");
+
+class BindEmail extends API {
+    constructor() {
+        super();
+
+        this.setMethod("POST");
+        this.setPath("/User/BindEmail");
+    }
+
+    async onRequest(req, res) {
+        let { uuid, session, email, code } = req.body;
+
+        if ([uuid, session, email, code].some(value => value === '' || value === null || value === undefined)) {
+            return res.json({
+                ...BaseStdResponse.MISSING_PARAMETER,
+                endpoint: 1513126
+            });
+        }
+
+        // 检查 session
+        if (!await AccessControl.checkSession(uuid, session))
+            return res.status(401).json({
+                ...BaseStdResponse.ACCESS_DENIED
+            })
+
+
+        const VerifyCode = await Redis.get(`email:${email}`);
+        if (!VerifyCode || VerifyCode != code)
+            return res.json({
+                ...BaseStdResponse.SMS_CHECK_FAIL,
+                msg: '邮箱验证码输入错误或已过期'
+            })
+
+        let sql = 'SELECT email FROM users WHERE email = ?';
+        let EmailRows = await db.query(sql, [email]);
+        if (EmailRows.length > 0)
+            return res.json({
+                ...BaseStdResponse.USER_ALREADY_EXISTS,
+                msg: '该邮箱已被注册!'
+            })
+
+        sql = 'UPDATE users SET email = ? WHERE uuid = ?';
+        let result = await db.query(sql, [email, uuid]);
+
+        if (result && result.affectedRows > 0) {
+            // 注册成功后删除邮箱对应的验证码 避免注册失败后重复获取
+            await Redis.del(`email:${email}`);
+
+            res.json({
+                ...BaseStdResponse.OK
+            });
+            await sendEmail(email, '换绑邮箱成功', `您的GitNexus账号换绑邮箱成功,操作时间:${new Date().toLocaleString()}`);
+        } else {
+            res.json({ ...BaseStdResponse.ERR, endpoint: 7894378, msg: '操作失败!' });
+        }
+    }
+}
+
+module.exports.BindEmail = BindEmail;

+ 47 - 0
apis/User/GetUserInfo.js

@@ -0,0 +1,47 @@
+const API = require("../../lib/API");
+const db = require("../../plugin/DataBase/db");
+const AccessControl = require("../../lib/AccessControl");
+const { BaseStdResponse } = require("../../BaseStdResponse");
+
+class GetRepoList extends API {
+    constructor() {
+        super();
+
+        this.setPath('/User/Info')
+        this.setMethod('GET')
+    }
+
+    async onRequest(req, res) {
+        let {
+            uuid,
+            session
+        } = req.query
+
+        if ([uuid, session].some(value => value === '' || value === null || value === undefined))
+            return res.json({
+                ...BaseStdResponse.MISSING_PARAMETER
+            })
+
+        // 检查 session
+        if (!await AccessControl.checkSession(uuid, session))
+            return res.status(401).json({
+                ...BaseStdResponse.ACCESS_DENIED
+            })
+
+        let sql = 'SELECT uuid, session, username, permission AS roles, avatar, email, registTime FROM users WHERE uuid = ?'
+        let rows = await db.query(sql, [uuid])
+
+        if (!rows || rows.length === 0)
+            return res.json({
+                ...BaseStdResponse.MISSING_FILE,
+                msg: '获取用户信息失败!'
+            })
+
+        res.json({
+            ...BaseStdResponse.OK,
+            data: rows[0]
+        })
+    }
+}
+
+module.exports.GetRepoList = GetRepoList;

+ 6 - 3
apis/User/Login.js

@@ -53,9 +53,10 @@ class Login extends API {
             })
             })
 
 
         const session = uuidv4();
         const session = uuidv4();
+        const time = new Date().getTime()
 
 
-        sql = 'UPDATE users SET session = ? WHERE id = ?';
-        let result = await db.query(sql, [session, rows[0].id]);
+        sql = 'UPDATE users SET session = ?, lastTime = ? WHERE id = ?';
+        let result = await db.query(sql, [session, time, rows[0].id]);
 
 
         if (result && result.affectedRows > 0) {
         if (result && result.affectedRows > 0) {
             res.json({
             res.json({
@@ -67,8 +68,10 @@ class Login extends API {
                     roles: rows[0].permission || [],
                     roles: rows[0].permission || [],
                     vip: rows[0].vip,
                     vip: rows[0].vip,
                     ic_count: rows[0].ic_count,
                     ic_count: rows[0].ic_count,
+                    lepao_count: rows[0].lepao_count,
                     crouse_count: rows[0].crouse_count,
                     crouse_count: rows[0].crouse_count,
-                    realname: rows[0].realname
+                    avatar: rows[0].avatar,
+                    email: rows[0].email
                 }
                 }
             });
             });
         } else {
         } else {

+ 32 - 0
config.json

@@ -0,0 +1,32 @@
+{
+    "port": 30003,
+    "database": {
+        "host": "8.137.37.202",
+        "database": "ic_ctbu",
+        "port": 13306,
+        "user": "root",
+        "password": "yx3ud937"
+    },
+    "redis": {
+        "host": "localhost",
+        "port": 5173,
+        "password": ""
+    },
+    "email": {
+        "host": "smtp.exmail.qq.com",
+        "port": 465,
+        "secure": true,
+        "user": "mail@ctbu.top",
+        "password": "FPhxUVrt5J9WxgiP"
+    },
+    "url": "https://cq1-api.ic.vite.net.cn/",
+    "url2": "http://127.0.0.1:30004",
+    "url3": "http://127.0.0.1:30001",
+    "pay": {
+        "url":"https://pay.ctbu.top/submit.php",
+        "pid": 1,
+        "key": "WfRF4t9wcepCjLs18lUoxRS2HiSF5mHI",
+        "return_url": "http://localhost:5173/#/store/orderDetail/"
+    },
+    "server": "CTBU_CLUB 重庆1号服务器"
+}