diff --git a/src/modules/admin/FeedbackAdminPage.tsx b/src/modules/admin/FeedbackAdminPage.tsx index 0d1c2a6..e119e21 100644 --- a/src/modules/admin/FeedbackAdminPage.tsx +++ b/src/modules/admin/FeedbackAdminPage.tsx @@ -1,6 +1,6 @@ import { useCallback, useEffect, useState } from 'react'; import { motion, AnimatePresence } from 'motion/react'; -import { Inbox, RotateCcw, X, Send, CheckCircle2, AlertCircle, Image as ImageIcon, Loader2 } from 'lucide-react'; +import { Inbox, RotateCcw, X, Send, CheckCircle2, AlertCircle, Image as ImageIcon, Loader2, ArrowLeft } from 'lucide-react'; import { fetchJson } from '../../auth/api-client'; interface FeedbackItem { @@ -129,16 +129,27 @@ export default function FeedbackAdminPage() {
-
-
+
+ +
-
+

用户反馈管理

查看、回复、跟进用户提交的建议

-
diff --git a/src/modules/ele/EleImportPage.tsx b/src/modules/ele/EleImportPage.tsx index 3cdcd93..5d6bd00 100644 --- a/src/modules/ele/EleImportPage.tsx +++ b/src/modules/ele/EleImportPage.tsx @@ -2,7 +2,7 @@ import { useCallback, useEffect, useRef, useState } from 'react'; import { motion, AnimatePresence } from 'motion/react'; import { Upload, FileSpreadsheet, RotateCcw, CheckCircle2, AlertCircle, - Truck, ExternalLink, Layers, Zap, + Truck, ExternalLink, Layers, Zap, ArrowLeft, } from 'lucide-react'; import { fetchJson } from '../../auth/api-client'; import { useAuth } from '../../auth/useAuth'; @@ -138,16 +138,26 @@ export default function EleImportPage() {
-
-
+
+ +
-
+

充电记录导入

每日上传 xlsx · 订单编号去重 · 系统车辆自动匹配

- {user?.userName || ''} + {user?.userName || ''}
{/* 上传区 */} diff --git a/src/server/routes/feedback/index.ts b/src/server/routes/feedback/index.ts index 04507a9..fb779a6 100644 --- a/src/server/routes/feedback/index.ts +++ b/src/server/routes/feedback/index.ts @@ -54,6 +54,9 @@ const VALID_STATUS = new Set(['open', 'in_progress', 'done', 'rejected']); const VALID_TYPES = new Set(['dimension', 'bug', 'ux', 'other']); +// 写入时间戳一律用东八区 CST,避免依赖 MySQL/容器时区设置 +const CST_NOW = `DATE_ADD(UTC_TIMESTAMP(), INTERVAL 8 HOUR)`; + app.post('/submit', async (c) => { await ensureTable(); const body = await c.req.json().catch(() => ({})) as { @@ -79,7 +82,7 @@ app.post('/submit', async (c) => { const [r] = await pool.query( `INSERT INTO bi_user_feedback (type, module, content, contact, screenshots, user_id, user_name, user_agent, created_at) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW())`, + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ${CST_NOW})`, [type, moduleVal, content, contact, JSON.stringify(screenshots), user?.userId || null, user?.userName || null, userAgent], ); return c.json({ ok: true, id: r.insertId }); @@ -174,7 +177,7 @@ app.patch('/:id', async (c) => { } if (typeof body.reply === 'string') { const reply = body.reply.trim().slice(0, 2000); - fields.push('reply_content = ?', 'reply_user = ?', 'reply_at = NOW()'); + fields.push('reply_content = ?', 'reply_user = ?', `reply_at = ${CST_NOW}`); const user = (c as { get?: (k: string) => unknown }).get?.('user') as AuthUser | undefined; params.push(reply || null, user?.userName || user?.userId || null); }