feat(feedback): 截图上传 + 我的反馈历史 + 后台管理页
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

后端
- 接入阿里云 OSS(ali-oss SDK),bucket=lnh2etest,目录 /dos/feedback/YYYY-MM-DD/
- POST /api/feedback/upload:单图 multipart 上传,限制 5MB,仅 png/jpeg/webp/gif
- bi_user_feedback 增加 screenshots(JSON)、reply_content/reply_user/reply_at、user_id 索引
  老表通过 try-catch 自动 ALTER 兼容
- POST /api/feedback/submit:增加 screenshots[] 字段
- GET /api/feedback/mine:当前用户自己的反馈历史
- PATCH /api/feedback/:id:更新状态 + 回复
- GET /api/feedback/list:增加 status 过滤

前端
- FeedbackFab 改为悬浮按钮 + 弹出菜单:「提个建议」/「我的反馈」
- 弹窗 Step 2 增加截图区:点击选择 / 多张 / 直接 Ctrl+V 粘贴
  缩略图预览 + 单张移除,最多 6 张,上传中转圈
- FeedbackHistoryDrawer 新组件:底部抽屉展示自己的反馈
  含状态徽章(待处理/处理中/已完成/已忽略)、截图缩略图、产品同学回复区
- 新增隐藏后台管理页 /admin/feedback(或 #/admin/feedback)
  状态分类计数 + 列表 + 详情弹窗(改状态 + 写回复,状态选项含徽章色)
  待处理项有快捷按钮(标记处理中 / 忽略)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
kkfluous
2026-04-30 14:06:21 +08:00
parent e8f1604c11
commit 20ebb16e08
8 changed files with 1760 additions and 29 deletions

View File

@@ -6,6 +6,7 @@ import MileageModule from './modules/mileage/MileageModule';
import SchedulingModule from './modules/scheduling/SchedulingModule';
import EnergyModule from './modules/energy/EnergyModule';
import EleImportPage from './modules/ele/EleImportPage';
import FeedbackAdminPage from './modules/admin/FeedbackAdminPage';
import AuthProvider from './auth/AuthProvider';
import { useAuth } from './auth/useAuth';
import UnauthorizedPage from './auth/UnauthorizedPage';
@@ -46,13 +47,16 @@ function AuthGate() {
return <UnauthorizedPage message={error || undefined} />;
}
// 隐藏后端管理页:通过 /ele/import 或 #/ele/import 直接访问,主导航不出现
// 隐藏后端管理页:通过路径或 hash 直接访问,主导航不出现
if (typeof window !== 'undefined') {
const path = window.location.pathname;
const hash = window.location.hash;
if (path === '/ele/import' || hash === '#/ele/import' || hash === '#ele/import') {
return <EleImportPage />;
}
if (path === '/admin/feedback' || hash === '#/admin/feedback' || hash === '#admin/feedback') {
return <FeedbackAdminPage />;
}
}
return <Shell modules={modules} />;