Spaces:
Sleeping
Sleeping
| const crypto = require('crypto'); | |
| const { runQuery, getQuery, allQuery } = require('../database/database'); | |
| class ActivationCode { | |
| // 生成批量激活码 | |
| static async generateCodes(count, days = 30) { | |
| try { | |
| const codes = []; | |
| const insertPromises = []; | |
| for (let i = 0; i < count; i++) { | |
| const code = this.generateUniqueCode(); | |
| codes.push(code); | |
| const insertPromise = runQuery( | |
| `INSERT INTO activation_codes (code, days) VALUES (?, ?)`, | |
| [code, days] | |
| ); | |
| insertPromises.push(insertPromise); | |
| } | |
| await Promise.all(insertPromises); | |
| return codes; | |
| } catch (error) { | |
| throw error; | |
| } | |
| } | |
| // 生成唯一激活码 | |
| static generateUniqueCode() { | |
| // 生成16位激活码,格式:XXXX-XXXX-XXXX-XXXX | |
| const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; | |
| let code = ''; | |
| for (let i = 0; i < 16; i++) { | |
| if (i > 0 && i % 4 === 0) { | |
| code += '-'; | |
| } | |
| code += chars.charAt(Math.floor(Math.random() * chars.length)); | |
| } | |
| return code; | |
| } | |
| // 验证激活码 | |
| static async validateCode(code) { | |
| try { | |
| const activationCode = await getQuery( | |
| `SELECT * FROM activation_codes WHERE code = ? AND is_used = 0`, | |
| [code] | |
| ); | |
| if (!activationCode) { | |
| throw new Error('激活码无效或已被使用'); | |
| } | |
| return activationCode; | |
| } catch (error) { | |
| throw error; | |
| } | |
| } | |
| // 使用激活码 | |
| static async useCode(code, userId) { | |
| try { | |
| // 验证激活码 | |
| const activationCode = await this.validateCode(code); | |
| // 标记激活码为已使用 | |
| await runQuery( | |
| `UPDATE activation_codes SET is_used = 1, used_by = ?, used_at = strftime('%s', 'now') WHERE code = ?`, | |
| [userId, code] | |
| ); | |
| return activationCode; | |
| } catch (error) { | |
| throw error; | |
| } | |
| } | |
| // 获取所有激活码 | |
| static async getAllCodes(page = 1, pageSize = 50) { | |
| try { | |
| const offset = (page - 1) * pageSize; | |
| const codes = await allQuery( | |
| `SELECT ac.*, u.email as used_by_email | |
| FROM activation_codes ac | |
| LEFT JOIN users u ON ac.used_by = u.id | |
| ORDER BY ac.created_at DESC | |
| LIMIT ? OFFSET ?`, | |
| [pageSize, offset] | |
| ); | |
| const totalResult = await getQuery( | |
| `SELECT COUNT(*) as total FROM activation_codes` | |
| ); | |
| return { | |
| codes, | |
| total: totalResult.total, | |
| page, | |
| pageSize, | |
| totalPages: Math.ceil(totalResult.total / pageSize) | |
| }; | |
| } catch (error) { | |
| throw error; | |
| } | |
| } | |
| // 获取激活码统计 | |
| static async getStatistics() { | |
| try { | |
| const totalResult = await getQuery( | |
| `SELECT COUNT(*) as total FROM activation_codes` | |
| ); | |
| const usedResult = await getQuery( | |
| `SELECT COUNT(*) as used FROM activation_codes WHERE is_used = 1` | |
| ); | |
| const unusedResult = await getQuery( | |
| `SELECT COUNT(*) as unused FROM activation_codes WHERE is_used = 0` | |
| ); | |
| const todayResult = await getQuery( | |
| `SELECT COUNT(*) as today FROM activation_codes | |
| WHERE created_at > strftime('%s', 'now', '-1 day')` | |
| ); | |
| return { | |
| total: totalResult.total, | |
| used: usedResult.used, | |
| unused: unusedResult.unused, | |
| todayGenerated: todayResult.today | |
| }; | |
| } catch (error) { | |
| throw error; | |
| } | |
| } | |
| // 删除激活码 | |
| static async deleteCode(codeId) { | |
| try { | |
| const result = await runQuery( | |
| `DELETE FROM activation_codes WHERE id = ? AND is_used = 0`, | |
| [codeId] | |
| ); | |
| return result.changes > 0; | |
| } catch (error) { | |
| throw error; | |
| } | |
| } | |
| } | |
| module.exports = ActivationCode; | |