feat: add all route modules (auth, records, stats, recurring, categories, export, search)

This commit is contained in:
Developer
2026-03-18 16:10:41 +08:00
parent 9c3281e6ac
commit 9165188100
7 changed files with 648 additions and 0 deletions
+115
View File
@@ -0,0 +1,115 @@
const express = require('express');
const db = require('../config/database');
const { authenticate } = require('../middleware/auth');
const { asyncHandler, AppError } = require('../middleware/errorHandler');
const { validateImportPayload, normalizeNote } = require('../utils/validators');
const router = express.Router();
// 导出数据
router.get('/', authenticate, asyncHandler(async (req, res) => {
const recordsStmt = db.prepare('SELECT * FROM records WHERE user_id = ? ORDER BY date DESC');
const records = recordsStmt.all(req.userId);
const recurringStmt = db.prepare('SELECT * FROM recurring_bills WHERE user_id = ?');
const recurring = recurringStmt.all(req.userId);
const categoriesStmt = db.prepare('SELECT * FROM categories WHERE user_id = ?');
const categories = categoriesStmt.all(req.userId);
console.log(`Data exported: user=${req.userId}`);
res.json({
version: '1.0',
exportDate: new Date().toISOString(),
records,
recurring,
customCategories: categories,
});
}));
// 导入数据
router.post('/', authenticate, asyncHandler(async (req, res) => {
const { records: importRecords, recurring: importRecurring, customCategories: importCategories } = req.body;
const validationError = validateImportPayload(req.body);
if (validationError) {
throw new AppError(validationError, 400, 'VALIDATION_ERROR');
}
const importCount = { records: 0, recurring: 0, categories: 0 };
if (importRecords && Array.isArray(importRecords)) {
const insertRecord = db.prepare(`
INSERT INTO records (user_id, type, amount, category, date, note, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?)
`);
const insertMany = db.transaction((records) => {
for (const r of records) {
insertRecord.run(
req.userId,
r.type,
r.amount,
r.category.trim(),
r.date,
normalizeNote(r.note),
r.created_at || new Date().toISOString()
);
}
});
insertMany(importRecords);
importCount.records = importRecords.length;
}
if (importRecurring && Array.isArray(importRecurring)) {
const insertRecurring = db.prepare(`
INSERT INTO recurring_bills (user_id, type, amount, category, day, note, is_active, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
`);
const insertRecurringMany = db.transaction((bills) => {
for (const b of bills) {
insertRecurring.run(
req.userId,
b.type,
b.amount,
b.category.trim(),
b.day,
normalizeNote(b.note),
b.is_active !== undefined ? b.is_active : 1,
b.created_at || new Date().toISOString()
);
}
});
insertRecurringMany(importRecurring);
importCount.recurring = importRecurring.length;
}
if (importCategories && Array.isArray(importCategories)) {
const insertCategory = db.prepare(`
INSERT INTO categories (user_id, type, name, icon, is_default, created_at)
VALUES (?, ?, ?, ?, 0, ?)
`);
const insertCategoryMany = db.transaction((cats) => {
for (const c of cats) {
insertCategory.run(
req.userId,
c.type,
c.name.trim(),
c.icon.trim(),
c.created_at || new Date().toISOString()
);
}
});
insertCategoryMany(importCategories);
importCount.categories = importCategories.length;
}
console.log(`Data imported: user=${req.userId}, counts=${JSON.stringify(importCount)}`);
res.json({ message: '导入成功', count: importCount });
}));
module.exports = router;