mira-app-server
Version:
Mira Server - standalone server application using mira-app-core
152 lines • 7.98 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.StatisticsRouter = void 0;
const express_1 = require("express");
class StatisticsRouter {
constructor(backend) {
this.backend = backend;
this.router = (0, express_1.Router)();
this.setupRoutes();
}
static getStartTime(req) {
const days = parseInt(req.query.days);
if (days > 0)
return Date.now() - days * 24 * 60 * 60 * 1000;
return undefined;
}
setupRoutes() {
// 上传统计(按用户)
this.router.get('/:libraryId/upload', async (req, res) => {
try {
const { libraryId } = req.params;
const obj = this.backend.libraries?.getLibrary(libraryId);
if (!obj) {
return res.status(404).json({ code: 404, message: 'Library not found', data: null });
}
const startTime = StatisticsRouter.getStartTime(req);
const stats = await obj.libraryService.getUploadStatistics(startTime);
// 把 uploader ID 映射为用户名
const userStorage = this.backend.httpServer?.authRouter.getUserStorage();
const allUsers = userStorage ? await userStorage.getAllUsers() : [];
const userMap = new Map(allUsers.map(u => [u.id, u.username]));
const data = stats.map((row) => ({
uploader: row.uploader,
uploaderName: row.uploader ? (userMap.get(row.uploader) || `User#${row.uploader}`) : '未知',
fileCount: row.file_count,
totalSize: row.total_size,
}));
res.json({ code: 0, message: 'Success', data });
}
catch (error) {
console.error('Error getting upload statistics:', error);
res.status(500).json({ code: 500, message: 'Internal server error', data: null });
}
});
// 每日上传统计(按日期分组)
this.router.get('/:libraryId/upload/daily', async (req, res) => {
try {
const { libraryId } = req.params;
const obj = this.backend.libraries?.getLibrary(libraryId);
if (!obj) {
return res.status(404).json({ code: 404, message: 'Library not found', data: null });
}
const startTime = StatisticsRouter.getStartTime(req);
const stats = await obj.libraryService.getDailyUploadStats(startTime);
res.json({ code: 0, message: 'Success', data: stats });
}
catch (error) {
console.error('Error getting daily upload stats:', error);
res.status(500).json({ code: 500, message: 'Internal server error', data: null });
}
});
// 文件类型统计
this.router.get('/:libraryId/file-types', async (req, res) => {
try {
const { libraryId } = req.params;
const obj = this.backend.libraries?.getLibrary(libraryId);
if (!obj) {
return res.status(404).json({ code: 404, message: 'Library not found', data: null });
}
const startTime = StatisticsRouter.getStartTime(req);
const stats = await obj.libraryService.getFileTypeStatistics(startTime);
res.json({ code: 0, message: 'Success', data: stats });
}
catch (error) {
console.error('Error getting file type statistics:', error);
res.status(500).json({ code: 500, message: 'Internal server error', data: null });
}
});
// 最近上传记录(一周内,按天/用户/文件夹/标签聚合)
this.router.get('/:libraryId/recent-uploads', async (req, res) => {
try {
const { libraryId } = req.params;
const days = parseInt(req.query.days) || 7;
const obj = this.backend.libraries?.getLibrary(libraryId);
if (!obj) {
return res.status(404).json({ code: 404, message: 'Library not found', data: null });
}
const raw = await obj.libraryService.getRecentUploads(days);
// 收集所有 folder_id,批量查名称
const folderIds = [...new Set((raw.byFolder || []).map((r) => r.folder_id).filter(Boolean))];
const folderMap = new Map();
for (const fid of folderIds) {
const folder = await obj.libraryService.getFolder(fid);
if (folder)
folderMap.set(fid, folder.title);
}
const tagMap = new Map();
const allTags = await obj.libraryService.getAllTags();
for (const tag of allTags) {
tagMap.set(tag.id, tag.title);
}
const userStorage = this.backend.httpServer?.authRouter.getUserStorage();
const allUsers = userStorage ? await userStorage.getAllUsers() : [];
const userMap = new Map(allUsers.map(u => [u.id, u.username]));
const userName = (id) => id ? (userMap.get(id) || `User#${id}`) : '未知';
const records = [];
for (const r of (raw.byFolder || [])) {
const folderName = r.folder_id ? (folderMap.get(r.folder_id) || '未分类') : '素材库';
records.push({ date: r.date, userName: userName(r.uploader), uploader: r.uploader, target: folderName, targetType: 'folder', targetId: r.folder_id || null, fileCount: r.file_count });
}
for (const r of (raw.byTag || [])) {
const tagName = r.tag_id ? (tagMap.get(Number(r.tag_id)) || '未知标签') : '未知标签';
records.push({ date: r.date, userName: userName(r.uploader), uploader: r.uploader, target: tagName, targetType: 'tag', targetId: r.tag_id ? Number(r.tag_id) : null, fileCount: r.file_count });
}
// 按日期分组
const grouped = new Map();
for (const r of records) {
if (!grouped.has(r.date))
grouped.set(r.date, []);
grouped.get(r.date).push(r);
}
// 合并同天同用户同目标的记录
const result = [];
for (const [date, items] of grouped) {
const merged = new Map();
for (const item of items) {
const key = `${item.uploader}::${item.targetType}::${item.targetId}`;
const existing = merged.get(key);
if (existing) {
existing.fileCount += item.fileCount;
}
else {
merged.set(key, { userName: item.userName, uploader: item.uploader, target: item.target, targetType: item.targetType, targetId: item.targetId, fileCount: item.fileCount });
}
}
result.push({ date, items: [...merged.values()].sort((a, b) => b.fileCount - a.fileCount) });
}
result.sort((a, b) => b.date.localeCompare(a.date));
res.json({ code: 0, message: 'Success', data: result });
}
catch (error) {
console.error('Error getting recent uploads:', error);
res.status(500).json({ code: 500, message: 'Internal server error', data: null });
}
});
}
getRouter() {
return this.router;
}
}
exports.StatisticsRouter = StatisticsRouter;
//# sourceMappingURL=StatisticsRouter.js.map