fix: 活动矩阵备注修复 + 时长统一保留 1 位小数 + Excel 导出自定义样式
Deploy to Server / deploy (push) Successful in 1m37s

- 后端 activity_matrix 新增 _remarks 映射,不再依赖 hours 数组独立哈希
  (避免 include_hours=false 时矩阵备注全丢)
- 前端预览矩阵 & Excel 矩阵 & 一键总表统一直读 u._remarks[activityId]
  单元格格式:时长(1位) + 换行 + 「备注:xxx」
- 全局 toFixed(2) → toFixed(1):
  · Export.tsx 明细/MiniTable/矩阵/KPI
  · Hours.tsx 批量设置提示/Excel 导出/卡片汇总
  · Users.tsx 列表累计时长/详情卡片/活动明细
  · user/Dashboard.tsx 累计时长卡片/活动明细表
- Excel 导出自定义样式(utils/export.ts):
  · 表头主题色 #275354 填充 + 白字 + 加粗 + 居中
  · 首行冻结(姓名+义工号两列粘性 xSplit=2)+ 整表 autofilter
  · 全列列宽自适应(按表头+前 2000 行内容最大换行宽度,关键字段保底)
  · 矩阵单元格居中 + 数值格式 0.0 + wrapText 备注换行
  · 交替行底色 ALT_ROW=#F7FAFA,总时长列字加粗主题色 + 浅底色 #EDF7F7
  · 行高按每行最大换行数量线性放大(16+(n-1)*14,最低 18)
  · 所有实体单元格补空值保留边框,避免边角缺失
  · XLSX.write 启用 cellStyles=true;MIME 改为标准 openxmlformats-officedocument
- 矩阵 sheet 通过 hint.matrixColStart/End 精确识别矩阵单元格区间启用数值格式
- 修复 doExcel() sheets 数组类型声明过窄(增加 hint 可选字段)
This commit is contained in:
Trae Assistant
2026-10-05 10:12:46 +08:00
parent 4df87b4576
commit b145cbd167
6 changed files with 307 additions and 90 deletions
+11 -3
View File
@@ -112,12 +112,17 @@ router.post('/', authMiddleware, (req: AuthRequest, res) => {
`).all() as any[];
const users = withGroupNames(userRows);
const hoursRows = db.prepareCompat(`
SELECT user_id, activity_id, hours FROM hours
SELECT user_id, activity_id, hours, remark FROM hours
`).all() as any[];
const matrix: Record<string, number> = {};
const remarkMatrix: Record<string, string> = {};
for (const r of hoursRows) {
const key = `${r.user_id}|${r.activity_id}`;
matrix[key] = (matrix[key] || 0) + Number(r.hours || 0);
if (r.remark) {
const exist = remarkMatrix[key];
remarkMatrix[key] = exist ? `${exist};${String(r.remark)}` : String(r.remark);
}
}
result.activity_matrix = {
activities,
@@ -128,12 +133,15 @@ router.post('/', authMiddleware, (req: AuthRequest, res) => {
name: u.name,
volunteer_no: u.volunteer_no,
group_name: u.group_name,
_remarks: {} as Record<string, string>,
};
for (const a of activities) {
row[String(a.id)] = Number((matrix[`${u.id}|${a.id}`] || 0).toFixed(2));
row[String(a.id)] = Number((matrix[`${u.id}|${a.id}`] || 0).toFixed(1));
const rmk = remarkMatrix[`${u.id}|${a.id}`];
if (rmk) (row._remarks as any)[String(a.id)] = rmk;
}
row._total = Number(
activities.reduce((s: number, a: any) => s + (Number(row[String(a.id)]) || 0), 0).toFixed(2)
activities.reduce((s: number, a: any) => s + (Number(row[String(a.id)]) || 0), 0).toFixed(1)
);
return row;
}),