first
This commit is contained in:
+112
@@ -0,0 +1,112 @@
|
||||
const express = require('express');
|
||||
const cors = require('cors');
|
||||
const path = require('path');
|
||||
const { initDB } = require('./db');
|
||||
const { authenticateToken } = require('./middleware/auth');
|
||||
|
||||
const app = express();
|
||||
const PORT = process.env.PORT || 3000;
|
||||
|
||||
// Middleware
|
||||
app.use(cors());
|
||||
app.use(express.json());
|
||||
|
||||
// Static files (for serving built frontend)
|
||||
app.use(express.static(path.join(__dirname, 'public')));
|
||||
|
||||
async function startServer() {
|
||||
// Initialize database
|
||||
const db = await initDB();
|
||||
|
||||
// Make db available to routes
|
||||
app.locals.db = db;
|
||||
|
||||
// Auth routes (login is public)
|
||||
const jwt = require('jsonwebtoken');
|
||||
const bcrypt = require('bcryptjs');
|
||||
const { JWT_SECRET } = require('./middleware/auth');
|
||||
|
||||
app.post('/api/auth/login', (req, res) => {
|
||||
const { username, password } = req.body;
|
||||
if (!username || !password) return res.status(400).json({ code: 400, message: '用户名和密码不能为空' });
|
||||
const user = db.get('SELECT * FROM users WHERE username = ?', [username]);
|
||||
if (!user) return res.status(401).json({ code: 401, message: '用户名或密码错误' });
|
||||
if (user.status !== 1) return res.status(403).json({ code: 403, message: '账号已被禁用' });
|
||||
if (user.role === 'sales') return res.status(403).json({ code: 403, message: '销售人员无需登录系统' });
|
||||
if (!bcrypt.compareSync(password, user.password)) return res.status(401).json({ code: 401, message: '用户名或密码错误' });
|
||||
const token = jwt.sign({ id: user.id, username: user.username, role: user.role, realname: user.realname }, JWT_SECRET, { expiresIn: '24h' });
|
||||
res.json({ code: 200, message: '登录成功', data: { token, user: { id: user.id, username: user.username, realname: user.realname, role: user.role } } });
|
||||
});
|
||||
|
||||
app.get('/api/auth/me', authenticateToken, (req, res) => {
|
||||
const user = db.get('SELECT id, username, realname, role, status FROM users WHERE id = ?', [req.user.id]);
|
||||
if (!user) return res.status(404).json({ code: 404, message: '用户不存在' });
|
||||
res.json({ code: 200, data: user });
|
||||
});
|
||||
|
||||
// Module routes
|
||||
const adminRoutes = require('./routes/admin');
|
||||
const rdRoutes = require('./routes/rd');
|
||||
|
||||
app.use('/api/admin', authenticateToken, adminRoutes);
|
||||
app.use('/api/rd', authenticateToken, rdRoutes);
|
||||
|
||||
// Health check
|
||||
app.get('/api/health', (req, res) => {
|
||||
res.json({ code: 200, message: 'OK', time: new Date().toISOString() });
|
||||
});
|
||||
|
||||
// Fallback: serve index.html for SPA
|
||||
app.get('*', (req, res) => {
|
||||
const indexPath = path.join(__dirname, 'public', 'index.html');
|
||||
const fs = require('fs');
|
||||
if (fs.existsSync(indexPath)) {
|
||||
res.sendFile(indexPath);
|
||||
} else {
|
||||
res.status(404).json({ code: 404, message: 'Not found' });
|
||||
}
|
||||
});
|
||||
|
||||
app.listen(PORT, () => {
|
||||
console.log(`🚀 WorkTime Server running at http://localhost:${PORT}`);
|
||||
});
|
||||
|
||||
// ===== Auto-backup cron: daily at 03:00 =====
|
||||
const cron = require('node-cron');
|
||||
const fsBackup = require('fs');
|
||||
const { buildBackupJson, BACKUP_DIR, ensureBackupDir } = adminRoutes;
|
||||
|
||||
function runAutoBackup() {
|
||||
try {
|
||||
ensureBackupDir();
|
||||
const json = buildBackupJson(db);
|
||||
const date = new Date().toISOString().slice(0, 10);
|
||||
const filePath = `${BACKUP_DIR}/backup-${date}.json`;
|
||||
fsBackup.writeFileSync(filePath, json, 'utf8');
|
||||
console.log(`[AutoBackup] Saved: ${filePath}`);
|
||||
|
||||
// Purge backups older than 30 days
|
||||
const cutoff = Date.now() - 30 * 24 * 60 * 60 * 1000;
|
||||
fsBackup.readdirSync(BACKUP_DIR).forEach(f => {
|
||||
if (!f.endsWith('.json')) return;
|
||||
const fp = `${BACKUP_DIR}/${f}`;
|
||||
if (fsBackup.statSync(fp).mtimeMs < cutoff) {
|
||||
fsBackup.unlinkSync(fp);
|
||||
console.log(`[AutoBackup] Purged old backup: ${f}`);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('[AutoBackup] Error:', e.message);
|
||||
}
|
||||
}
|
||||
|
||||
cron.schedule('0 3 * * *', runAutoBackup);
|
||||
console.log('[AutoBackup] Scheduled daily at 03:00');
|
||||
}
|
||||
|
||||
startServer().catch(err => {
|
||||
console.error('Failed to start server:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
module.exports = app;
|
||||
Reference in New Issue
Block a user