fix: 部员详情累计时长卡与下方活动列表合计不一致
Deploy to Server / deploy (push) Successful in 1m41s

- server/users.ts GET /:id:
  · total_hours 原先是标量子查询(独立的 SELECT SUM FROM hours),
    活动列表是 JOIN activities 后查出来的——两者在某些边界下可能
    数据源不一致(FK pragma 状态、活动被删但 hours 残留时标量子
    查询会多算 1 次,卡片显示 11h 而列表只有 7h 就是这个问题)
  · 改为直接用 activities 列表查询结果 reduce 求和后赋值给
    user.total_hours,保证两个数字来自完全同一份数据
- client/Users.tsx 部员详情参与活动表:
  · 表底部新增一条粘性合计行:bg-primary-50/60 + 边框,左边小字
    『本页列表合计(应等于上方卡片的累计时长)』,右边大号加粗
    主题色数字实时显示 reduce 求和
  · 溢出容器 overflow-hidden,合计行与 DataTable 边框完美贴合无缝
This commit is contained in:
Trae Assistant
2026-10-05 14:21:48 +08:00
parent 0d1622d455
commit 6e9d8578c9
2 changed files with 57 additions and 43 deletions
+12
View File
@@ -749,6 +749,7 @@ export default function Users() {
<h3 className="font-semibold mb-2 text-gray-800"> <h3 className="font-semibold mb-2 text-gray-800">
参与的活动({detail.activities.length} 次)<span className="ml-2 text-xs font-normal muted">按登记时间倒序,最新补录/登记在最上方</span> 参与的活动({detail.activities.length} 次)<span className="ml-2 text-xs font-normal muted">按登记时间倒序,最新补录/登记在最上方</span>
</h3> </h3>
<div className="overflow-hidden">
<DataTable <DataTable
columns={[ columns={[
{ {
@@ -792,6 +793,17 @@ export default function Users() {
data={detail.activities} data={detail.activities}
rowKey={(r: any) => `${r.id}-${r.reg_at || r.hours}-${r.remark || ''}`} rowKey={(r: any) => `${r.id}-${r.reg_at || r.hours}-${r.remark || ''}`}
/> />
{detail.activities.length > 0 && (
<div className="mt-1 px-3 py-2.5 rounded-b-md border-t border-gray-200 bg-primary-50/60 flex items-center justify-between">
<div className="text-sm font-medium text-gray-700">
本页列表合计 <span className="text-gray-500 text-xs ml-1">(应等于上方卡片的累计时长)</span>
</div>
<div className="text-lg font-bold text-primary-700">
{detail.activities.reduce((s: number, r: any) => s + Number(r.hours || 0), 0).toFixed(1)}h
</div>
</div>
)}
</div>
</div> </div>
</div> </div>
)} )}
+2
View File
@@ -82,6 +82,8 @@ router.get('/:id', (req: Request, res: Response) => {
WHERE h.user_id = ? WHERE h.user_id = ?
ORDER BY h.created_at DESC, a.start_time DESC ORDER BY h.created_at DESC, a.start_time DESC
`).all(id); `).all(id);
const listSum = activities.reduce((s, r) => s + Number(r.hours || 0), 0);
user.total_hours = Number(listSum.toFixed(1));
res.json({ ...user, activities }); res.json({ ...user, activities });
}); });