- 后端 POST /api/export 新增 include_activity_matrix:部员×活动矩阵行,列=所有活动(start_time DESC排),_total尾列 - 前端 Export 新增 06 卡片「活动时长总表(矩阵)」:部员+义工号 左固定列,活动列160px宽表头显示日期副标题,值>0高亮主色+浅底,总时长bg-primary-50 - Excel 新增「活动时长总表(矩阵)」Sheet:列名=活动标题,末列总时长 - 移除Brand组件所有img Logo渲染,纯标题,减小侧栏移动端头部视觉噪音 - 前后端 tsc --noEmit exit 0 + vite build exit 0;浏览器 E2E 验证矩阵张三/校园志愿宣传活动=2.00/总时长 2.00 h
This commit is contained in:
@@ -5,7 +5,7 @@ import { authMiddleware, AuthRequest } from '../middleware/auth';
|
||||
const router = Router();
|
||||
|
||||
router.post('/', authMiddleware, (req: AuthRequest, res) => {
|
||||
const { include_users, include_activities, include_hours, include_user_totals, include_user_activities } = req.body || {};
|
||||
const { include_users, include_activities, include_hours, include_user_totals, include_user_activities, include_activity_matrix } = req.body || {};
|
||||
const db = getDb();
|
||||
const result: any = {};
|
||||
|
||||
@@ -65,6 +65,37 @@ router.post('/', authMiddleware, (req: AuthRequest, res) => {
|
||||
return { ...u, activities: acts };
|
||||
});
|
||||
}
|
||||
if (include_activity_matrix) {
|
||||
const activities = db.prepareCompat(`
|
||||
SELECT id, title, start_time FROM activities ORDER BY start_time DESC, id DESC
|
||||
`).all() as any[];
|
||||
const users = db.prepareCompat(`
|
||||
SELECT u.id, u.class, u.name, u.volunteer_no, g.name AS group_name
|
||||
FROM users u LEFT JOIN work_groups g ON u.group_id = g.id
|
||||
ORDER BY u.class, u.name
|
||||
`).all() as any[];
|
||||
const hoursRows = db.prepareCompat(`
|
||||
SELECT user_id, activity_id, hours FROM hours
|
||||
`).all() as any[];
|
||||
const matrix: Record<string, number> = {};
|
||||
for (const r of hoursRows) {
|
||||
const key = `${r.user_id}|${r.activity_id}`;
|
||||
matrix[key] = (matrix[key] || 0) + Number(r.hours || 0);
|
||||
}
|
||||
result.activity_matrix = {
|
||||
activities,
|
||||
users: users.map((u) => {
|
||||
const row: Record<string, any> = { id: u.id, class: u.class, name: u.name, volunteer_no: u.volunteer_no, group_name: u.group_name };
|
||||
for (const a of activities) {
|
||||
row[String(a.id)] = Number((matrix[`${u.id}|${a.id}`] || 0).toFixed(2));
|
||||
}
|
||||
row._total = Number(
|
||||
activities.reduce((s: number, a: any) => s + (Number(row[String(a.id)]) || 0), 0).toFixed(2)
|
||||
);
|
||||
return row;
|
||||
}),
|
||||
};
|
||||
}
|
||||
res.json(result);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user