feat(ws-4/m3): 对话式前端工作台(替代交易/排行榜 UI) - #5
Merged
Merged
Conversation
- 首页 / 改造为对话工作台(3 栏:会话侧栏 / 消息流 / 研究检视),集成 ConversationProvider - 新增对话领域类型 types/conversation.ts(对齐 api-contract §5 的 11 类 WS 事件) - 新增 conversation.ts API 客户端 + ConversationWebSocket(JWT 子协议、心跳、自动重连、消息队列) - 新增 conversation-context.tsx(useReducer 管理流式消息 / 阶段进展 / 报告) - 新增 analysis/ 组件:报告卡片(5 级评级 + 5 段 + MD/JSON/PDF 导出)、阶段进展块、评级刻度、数据快照 - 新增 conversation/ 组件:会话侧栏、消息流/气泡、输入区(流式/停止)、未登录引导、检视面板 - 下线模拟交易 / 交易排行榜 / 仪表盘路由与组件,统一 not-found.tsx 引导回对话工作台(适配 output:'export' 静态导出,不使用 redirects()) - AppNavbar 移除排行榜/盯盘入口,新建分析→新建对话;8 个页面 Footer 引用迁移至 common/Footer - 登录/注册后跳转目标改为 / 构建通过(next build 静态导出),无新增 npm 依赖。 Refs: WS-4 M3
There was a problem hiding this comment.
Pull request overview
本 PR 将 Web 前端首页 / 重构为“对话式分析工作台”,并清理已下线/未规划的模拟交易、实时排名、仪表盘等相关 UI 与路由,以对齐 WS-4/M3 端到端联调目标与既有静态导出约束。
Changes:
- 新增对话域类型、HTTP API client、WebSocket client 与 Context(Provider + hook),打通会话/消息/报告/技能健康等数据流。
- 新增对话式工作台 UI(三栏布局:会话侧栏 / 消息流+输入 / 研究检视),支持流式消息、阶段进展与报告卡片展示与导出。
- 移除 leaderboard / intraday-trading / dashboard 相关页面、hook 与组件,并更新导航与回跳路径到
/(配合全局 not-found 引导)。
Reviewed changes
Copilot reviewed 61 out of 63 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| web/frontend/src/types/conversation.ts | 新增会话/消息/报告/WS 事件类型定义(对齐对话协议) |
| web/frontend/src/lib/conversation.ts | 新增对话相关 HTTP API client 与 WS client(流式通信、心跳、重连、队列) |
| web/frontend/src/lib/conversation-context.tsx | 新增 ConversationProvider:会话列表、消息流、阶段进展与报告状态管理 |
| web/frontend/src/hooks/useConversationWebSocket.ts | 新增 WS React wrapper hook(自动连接/断开、stop/retryStage) |
| web/frontend/src/hooks/useLeaderboardWebSocket.ts | 删除:旧实时排名 WS hook |
| web/frontend/src/hooks/useIntradayWebSocket.ts | 删除:旧智能盯盘 WS hook |
| web/frontend/src/hooks/useIntradayTrading.ts | 删除:旧智能盯盘 React Query hooks |
| web/frontend/src/components/conversation/StreamingCursor.tsx | 新增:消息流“生成中”光标组件 |
| web/frontend/src/components/conversation/SessionSidebar.tsx | 新增:会话侧栏(列表/搜索/新建/移动端抽屉关闭) |
| web/frontend/src/components/conversation/SessionItem.tsx | 新增:会话条目(选择/重命名/删除) |
| web/frontend/src/components/conversation/PromptChips.tsx | 新增:空态推荐提示词 chips |
| web/frontend/src/components/conversation/MessageFlow.tsx | 新增:消息流容器(空态、滚动到底部、生成中提示) |
| web/frontend/src/components/conversation/MessageBubble.tsx | 新增:消息气泡(Markdown、阶段进展块、报告卡片块) |
| web/frontend/src/components/conversation/LoginNudge.tsx | 新增:未登录输入区引导登录组件 |
| web/frontend/src/components/conversation/InspectorPanel.tsx | 新增:右侧检视(当前标的/评级、技能健康) |
| web/frontend/src/components/conversation/index.ts | 新增:conversation 组件导出汇总 |
| web/frontend/src/components/conversation/ConversationWorkbench.tsx | 新增:首页工作台三栏布局 + 移动端侧栏/检视抽屉 |
| web/frontend/src/components/conversation/Composer.tsx | 新增:输入框(Enter 发送、Shift+Enter 换行、停止按钮) |
| web/frontend/src/components/analysis/StageRow.tsx | 新增:单阶段进展行渲染 |
| web/frontend/src/components/analysis/StageProgress.tsx | 新增:阶段进展容器渲染 |
| web/frontend/src/components/analysis/SectionAccordion.tsx | 新增:报告分段折叠面板 |
| web/frontend/src/components/analysis/ReportCard.tsx | 新增:报告卡片(评级、要点、数据快照、分段内容、来源链接) |
| web/frontend/src/components/analysis/RatingScale.tsx | 新增:五级评级刻度展示组件 |
| web/frontend/src/components/analysis/ExportMenu.tsx | 新增:报告导出菜单(MD/JSON/PDF) |
| web/frontend/src/components/analysis/DataSnapshot.tsx | 新增:报告数据来源快照展示 |
| web/frontend/src/components/analysis/index.ts | 新增:analysis 组件导出汇总 |
| web/frontend/src/components/common/Footer.tsx | 新增:公共 Footer(替换 leaderboard/Footer 引用) |
| web/frontend/src/components/common/AppNavbar.tsx | 更新:移除 leaderboard / intraday 导航入口,“新建分析”改为回到 / 新建对话 |
| web/frontend/src/components/auth/RegisterForm.tsx | 更新:注册后回跳从 /dashboard 改为 / |
| web/frontend/src/components/auth/LoginForm.tsx | 更新:登录后回跳从 /dashboard 改为 / |
| web/frontend/src/components/leaderboard/UserPositionsPanel.tsx | 删除:旧排行榜用户持仓面板 |
| web/frontend/src/components/leaderboard/MarketTabs.tsx | 删除:旧排行榜市场切换 tabs |
| web/frontend/src/components/leaderboard/LeaderboardChart.tsx | 删除:旧排行榜趋势图实现 |
| web/frontend/src/components/leaderboard/HeroSection.tsx | 删除:旧 leaderboard Hero |
| web/frontend/src/components/leaderboard/Header.tsx | 删除:旧 leaderboard 顶部导航 |
| web/frontend/src/components/leaderboard/DecisionHistoryPanel.tsx | 删除:旧排行榜决策历史面板 |
| web/frontend/src/components/leaderboard/AnalysisCardsGrid.tsx | 删除:旧首页/排行榜分析卡片网格 |
| web/frontend/src/components/leaderboard/AnalysisCard.tsx | 删除:旧分析卡片组件 |
| web/frontend/src/components/intraday/TodayOrders.tsx | 删除:旧智能盯盘今日订单 |
| web/frontend/src/components/intraday/PromptConfigTab.tsx | 删除:旧智能盯盘提示词配置 |
| web/frontend/src/components/intraday/PositionOverview.tsx | 删除:旧智能盯盘持仓概览 |
| web/frontend/src/components/intraday/AccountTrendModal.tsx | 删除:旧智能盯盘账户趋势弹窗 |
| web/frontend/src/components/intraday/AccountInfo.tsx | 删除:旧智能盯盘账户信息 |
| web/frontend/src/components/home/HeroSection.tsx | 删除:旧首页 Hero(非工作台形态) |
| web/frontend/src/components/home/FeaturesShowcase.tsx | 删除:旧首页功能展示模块 |
| web/frontend/src/app/page.tsx | 更新:首页改为挂载 ConversationProvider + ConversationWorkbench |
| web/frontend/src/app/not-found.tsx | 新增:全局 404 引导旧路由回到 /(静态导出约束下替代 redirects) |
| web/frontend/src/app/leaderboard/page.tsx | 删除:旧实时排名页面 |
| web/frontend/src/app/intraday-trading/page.tsx | 删除:旧智能盯盘页面 |
| web/frontend/src/app/dashboard/page.tsx | 删除:旧仪表盘页面 |
| web/frontend/src/app/scheduled-tasks/page.tsx | 更新:Footer 引用调整 + 回跳入口改为 / |
| web/frontend/src/app/profile/page.tsx | 更新:Footer 引用调整为 common/Footer |
| web/frontend/src/app/history/progress/page.tsx | 更新:Footer 引用调整为 common/Footer |
| web/frontend/src/app/history/page.tsx | 更新:Footer 引用调整 + “返回配置”回跳改为 / |
| web/frontend/src/app/history/detail/page.tsx | 更新:Footer 引用调整 + 新建分析回跳改为 / |
| web/frontend/src/app/analysis/page.tsx | 更新:Footer 引用调整 + 回跳路径从 /dashboard 改为 / |
| web/frontend/src/app/admin/users/page.tsx | 更新:Footer 引用调整为 common/Footer |
| web/frontend/src/app/admin/llm-config/page.tsx | 更新:Footer 引用调整为 common/Footer |
| web/frontend/next.config.ts | 轻微格式调整(空白行变更) |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+361
to
+362
| dispatch({ type: 'SET_MESSAGES', messages: [...stream.messages, userMsg] }); | ||
| dispatch({ type: 'INIT_ASSISTANT', id: `pending-${sessionId}-${Date.now()}` }); |
Comment on lines
+366
to
+372
| dispatch({ | ||
| type: 'SET_MESSAGES', | ||
| messages: [ | ||
| ...stream.messages.filter((m) => m.id !== clientMessageId), | ||
| { ...res.data, content_blocks: res.data.content_blocks ?? [{ type: 'text', content: res.data.content }] }, | ||
| ], | ||
| }); |
Comment on lines
+80
to
+93
| case 'INIT_ASSISTANT': { | ||
| if (state.messages.some((m) => m.id === action.id)) { | ||
| return { ...state, activeAssistantId: action.id }; | ||
| } | ||
| const msg: Message = { | ||
| id: action.id, | ||
| session_id: '', | ||
| role: 'assistant', | ||
| content: '', | ||
| content_blocks: [], | ||
| created_at: new Date().toISOString(), | ||
| }; | ||
| return { ...state, messages: [...state.messages, msg], activeAssistantId: action.id }; | ||
| } |
Comment on lines
+107
to
+108
| return { ...state, messages, activeAssistantId: id }; | ||
| } |
Comment on lines
+145
to
+153
| const token = getAuthToken(); | ||
| const base = buildWebSocketUrl(`/ws/conversation/${this.sessionId}`); | ||
| const url = token ? `${base}?token=${token}` : base; | ||
| this.ws = new WebSocket(url); | ||
|
|
||
| this.ws.onopen = () => { | ||
| this.reconnectAttempts = 0; | ||
| if (token) this.sendRaw({ type: 'auth', token }); | ||
| this.startHeartbeat(); |
Comment on lines
+260
to
+272
| export type ConversationWsEvent = | ||
| | TokenEvent | ||
| | StageStartEvent | ||
| | StageUpdateEvent | ||
| | StageCompleteEvent | ||
| | StageWarningEvent | ||
| | StageErrorEvent | ||
| | AnalysisCompleteEvent | ||
| | ReportReadyEvent | ||
| | StopAckEvent | ||
| | GlobalErrorEvent | ||
| | PongEvent | ||
| | PingEvent; |
Comment on lines
+81
to
+83
| if (b.type === 'stage_progress') { | ||
| return <StageProgress key={i} blocks={[b]} />; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
概述
WS-4 M3 前端实现:将首页
/改造为对话式分析工作台,替换已下线/未规划的模拟交易与交易排行榜 UI。后端对话契约(api-contract.md §5)已由 M2 实现,本 PR 打通端到端联调。实施范围(按 tech spec §7 顺序)
/改为三栏布局(会话侧栏 / 消息流 / 研究检视),挂载ConversationProvider。SessionSidebar列表 / 新建 / 选择 / 重命名 / 删除(移动端抽屉)。MessageFlow/MessageBubble/Composer,基于 WebSocket 流式 token,支持「停止」与乐观消息。StageProgress/StageRow,消费stage_start/update/complete/warning/error等 WS 事件。ReportCard含 5 级评级刻度 + 5 个分析段落(市场技术/基本面/情绪/新闻宏观/风险)+ 关键要点 + 数据快照 + 反思,支持 MD / JSON / PDF 导出(ExportMenu)。LoginNudge。关键文件
src/types/conversation.ts(对齐 11 类 WS 事件)src/lib/conversation.ts(conversationAPI/messageAPI/reportAPI/skillsAPI+ConversationWebSocket:JWT 子协议、30s 心跳、最多 5 次自动重连、连接前消息队列)src/lib/conversation-context.tsx(useReducer 管理流式消息 / 阶段进展 / 报告)src/components/analysis/*、src/components/conversation/*、src/hooks/useConversationWebSocket.ts约束遵循
leaderboard、intraday、dashboard路由与组件;AppNavbar移除相关入口)。package-lock.json变动)。output: 'export'静态导出:旧路由清理采用「删除文件 +not-found.tsx引导回/」方案,未使用next.config的redirects()(静态导出不支持)。验证
next build静态导出通过(16 个页面全部预渲染)。tsc --noEmit本 PR 新增文件零类型错误(仓库既有文件存在无关的历史类型错误,已被typescript.ignoreBuildErrors跳过)。待办(非本 PR)
M3 实现完成,提请开发组长进行 M3 Gate 评审。 🔍