const express = require('express') const cors = require('cors') const sqlite3 = require('sqlite3').verbose() const path = require('path') const app = express() app.use(cors()) app.use(express.json()) app.use(express.static(path.join(__dirname, 'public'))) // SQLite 数据库初始化 const db = new sqlite3.Database(path.join(__dirname, 'activation.db'), (err) => { if (err) console.error('❌ 数据库连接失败:', err) else console.log('✅ SQLite 数据库已连接') }) // 创建表 db.serialize(() => { db.run(`CREATE TABLE IF NOT EXISTS activation_codes ( id INTEGER PRIMARY KEY AUTOINCREMENT, code TEXT UNIQUE NOT NULL, type TEXT NOT NULL, duration INTEGER NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, expires_at DATETIME, is_used BOOLEAN DEFAULT 0, is_active BOOLEAN DEFAULT 1, activated_at DATETIME, device_fingerprint TEXT, last_checkin DATETIME, last_checkin_device TEXT )`) db.run(`CREATE TABLE IF NOT EXISTS activation_logs ( id INTEGER PRIMARY KEY AUTOINCREMENT, code TEXT NOT NULL, action TEXT NOT NULL, message TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP )`) // 尝试添加新的列(如果表已存在且列不存在) db.run(`ALTER TABLE activation_codes ADD COLUMN last_checkin DATETIME`, (err) => { if (err && !err.message.includes('duplicate column name')) { console.warn('⚠️ 添加 last_checkin 列失败:', err.message) } }) db.run(`ALTER TABLE activation_codes ADD COLUMN last_checkin_device TEXT`, (err) => { if (err && !err.message.includes('duplicate column name')) { console.warn('⚠️ 添加 last_checkin_device 列失败:', err.message) } }) }) // 生成激活码 function generateCode() { 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 } // 计算过期时间 function calculateExpiresAt(type, duration) { const now = new Date() let expiresAt = new Date(now) if (type === 'minute') { expiresAt.setMinutes(expiresAt.getMinutes() + duration) } else if (type === 'hour') { expiresAt.setHours(expiresAt.getHours() + duration) } else if (type === 'day') { expiresAt.setDate(expiresAt.getDate() + duration) } else if (type === 'month') { expiresAt.setMonth(expiresAt.getMonth() + duration) } else if (type === 'year') { expiresAt.setFullYear(expiresAt.getFullYear() + duration) } return expiresAt.toISOString() } // API: 生成激活码 app.post('/api/codes/generate', (req, res) => { const { type = 'day', duration = 7 } = req.body const code = generateCode() const expiresAt = calculateExpiresAt(type, duration) db.run( 'INSERT INTO activation_codes (code, type, duration, expires_at) VALUES (?, ?, ?, ?)', [code, type, duration, expiresAt], (err) => { if (err) { return res.json({ success: false, error: err.message }) } res.json({ success: true, code: code, type: type, duration: duration, expiresAt: expiresAt }) } ) }) // API: 激活激活码 app.post('/api/activate', (req, res) => { const { code, device_fingerprint } = req.body db.get('SELECT * FROM activation_codes WHERE code = ?', [code], (err, row) => { if (err || !row) { db.run('INSERT INTO activation_logs (code, action, message) VALUES (?, ?, ?)', [code, 'activate_failed', '激活码不存在']) return res.json({ success: false, message: '激活码不存在' }) } if (!row.is_active) { return res.json({ success: false, message: '激活码已停用' }) } const now = new Date() const expiresAt = new Date(row.expires_at) if (now > expiresAt) { return res.json({ success: false, message: '激活码已过期' }) } if (row.is_used) { return res.json({ success: false, message: '激活码已被使用' }) } // 标记为已使用 db.run( 'UPDATE activation_codes SET is_used = 1, activated_at = ?, device_fingerprint = ? WHERE code = ?', [new Date().toISOString(), device_fingerprint, code], (err) => { if (err) { return res.json({ success: false, error: err.message }) } db.run('INSERT INTO activation_logs (code, action, message) VALUES (?, ?, ?)', [code, 'activate_success', '激活成功']) res.json({ success: true, code: code, type: row.type, duration: row.duration, activatedAt: new Date().toISOString(), expiresAt: row.expires_at }) } ) }) }) // API: 验证激活码 app.post('/api/validate', (req, res) => { const { code, device_fingerprint } = req.body db.get('SELECT * FROM activation_codes WHERE code = ?', [code], (err, row) => { if (err || !row) { return res.json({ valid: false, message: '激活码不存在' }) } if (!row.is_active) { return res.json({ valid: false, message: '激活码已停用' }) } const now = new Date() const expiresAt = new Date(row.expires_at) if (now > expiresAt) { return res.json({ valid: false, message: '激活码已过期', isExpired: true }) } if (!row.is_used) { return res.json({ valid: false, message: '激活码未被激活' }) } const remainingMs = expiresAt - now const remainingDays = Math.ceil(remainingMs / (1000 * 60 * 60 * 24)) const remainingHours = Math.ceil(remainingMs / (1000 * 60 * 60)) const remainingMinutes = Math.ceil(remainingMs / (1000 * 60)) res.json({ valid: true, code: code, type: row.type, duration: row.duration, activatedAt: row.activated_at, expiresAt: row.expires_at, remainingMs: remainingMs, remainingDays: remainingDays, remainingHours: remainingHours, remainingMinutes: remainingMinutes, isExpired: false }) }) }) // API: 获取所有激活码 app.get('/api/codes/list', (req, res) => { db.all('SELECT * FROM activation_codes ORDER BY created_at DESC', [], (err, rows) => { if (err) { return res.json({ success: false, error: err.message }) } res.json({ success: true, codes: rows }) }) }) // API: 停用激活码 app.post('/api/codes/disable', (req, res) => { const { code } = req.body db.run('UPDATE activation_codes SET is_active = 0 WHERE code = ?', [code], (err) => { if (err) { return res.json({ success: false, error: err.message }) } db.run('INSERT INTO activation_logs (code, action, message) VALUES (?, ?, ?)', [code, 'disable', '激活码已停用']) res.json({ success: true, message: '激活码已停用' }) }) }) // API: 启用激活码 app.post('/api/codes/enable', (req, res) => { const { code } = req.body db.run('UPDATE activation_codes SET is_active = 1 WHERE code = ?', [code], (err) => { if (err) { return res.json({ success: false, error: err.message }) } db.run('INSERT INTO activation_logs (code, action, message) VALUES (?, ?, ?)', [code, 'enable', '激活码已启用']) res.json({ success: true, message: '激活码已启用' }) }) }) // API: 删除激活码 app.post('/api/codes/delete', (req, res) => { const { code } = req.body db.run('DELETE FROM activation_codes WHERE code = ?', [code], (err) => { if (err) { return res.json({ success: false, error: err.message }) } res.json({ success: true, message: '激活码已删除' }) }) }) // API: 设备签到(记录最后启动时间) app.post('/api/device/checkin', (req, res) => { const { code, device_fingerprint } = req.body db.run( 'UPDATE activation_codes SET last_checkin = ?, last_checkin_device = ? WHERE code = ?', [new Date().toISOString(), device_fingerprint || 'unknown', code], (err) => { if (err) { console.error('❌ 设备签到失败:', err) return res.json({ success: false, error: err.message }) } db.run('INSERT INTO activation_logs (code, action, message) VALUES (?, ?, ?)', [code, 'device_checkin', `设备 ${device_fingerprint} 启动`]) res.json({ success: true, message: '设备签到成功' }) } ) }) // API: 获取统计信息 app.get('/api/codes/stats', (req, res) => { db.all(` SELECT COUNT(*) as total, SUM(CASE WHEN is_used = 0 THEN 1 ELSE 0 END) as unused, SUM(CASE WHEN is_used = 1 THEN 1 ELSE 0 END) as used, SUM(CASE WHEN is_active = 0 THEN 1 ELSE 0 END) as disabled FROM activation_codes `, [], (err, rows) => { if (err) { return res.json({ success: false, error: err.message }) } res.json({ success: true, stats: rows[0] }) }) }) // Web 管理后台路由 app.get('/admin', (req, res) => { res.sendFile(path.join(__dirname, 'public', 'admin.html')) }) const PORT = 3002 app.listen(PORT, () => { console.log(`\n✅ 激活码服务器已启动`) console.log(`📋 管理后台: http://localhost:${PORT}/admin`) console.log(`📡 API 地址: http://localhost:${PORT}/api\n`) })