feat: 统一全链路时区为 UTC+8 (Asia/Shanghai)
Deploy to Server / deploy (push) Successful in 1m36s

- schema.sql created_at DEFAULT 改为 datetime(now,+8 hours)
- Dockerfile runtime 安装 tzdata ENV TZ=Asia/Shanghai 并软链 /etc/localtime
- docker-compose.yml 挂载宿主机 localtime 并传 TZ=Asia/Shanghai
- server index.ts 入口设置 process.env.TZ
- client utils/export 新增 utc8Now/utc8Input/utc8DateStamp/utc8DateTimeStamp
- Activities 默认活动开始/结束时间改用 UTC+8
- 导出文件名日期戳和报告生成时间统一 utc8DateStamp/utc8DateTimeStamp
This commit is contained in:
Trae Assistant
2026-10-05 09:09:01 +08:00
parent 7f9bf15b7d
commit 30021d7b46
8 changed files with 53 additions and 18 deletions
+4 -4
View File
@@ -1,7 +1,7 @@
import { ReactNode, useRef, useState } from 'react';
import Button from '../../components/Button';
import { exportApi, errMsg } from '../../api';
import { exportToExcel, exportTableToImage, formatDateRange } from '../../utils/export';
import { exportToExcel, exportTableToImage, formatDateRange, utc8DateStamp, utc8DateTimeStamp } from '../../utils/export';
import type { ExportResult } from '../../types';
import {
IconExport,
@@ -226,12 +226,12 @@ export default function Export() {
});
sheets.push({ name: '活动时长总表(矩阵)', data });
}
exportToExcel(sheets, `义工数据-全部导出-${new Date().toISOString().slice(0, 10)}.xlsx`);
exportToExcel(sheets, `义工数据-全部导出-${utc8DateStamp()}.xlsx`);
};
const doImage = async () => {
if (!previewRef.current) return;
await exportTableToImage(previewRef.current, `义工数据-全部导出-${new Date().toISOString().slice(0, 10)}.png`);
await exportTableToImage(previewRef.current, `义工数据-全部导出-${utc8DateStamp()}.png`);
};
return (
@@ -315,7 +315,7 @@ export default function Export() {
<div ref={previewRef} className="card bg-white p-3 md:p-6 space-y-8">
<div className="border-b border-gray-200 pb-4 text-center">
<div className="text-xl md:text-2xl font-semibold tracking-tight text-gray-800">宣传部义工时长记录系统 · 数据导出报告</div>
<div className="muted mt-1.5">义工数据汇总导出 | 生成时间:{new Date().toLocaleString('zh-CN')}</div>
<div className="muted mt-1.5">义工数据汇总导出 | 生成时间:{utc8DateTimeStamp()}</div>
</div>
{preview.users?.length ? (