feat(web): 完善选股详情图表与案例图

This commit is contained in:
yuxuanhui
2026-09-01 13:37:19 +08:00
parent 9145fe4b2c
commit feb8fd4feb
27 changed files with 788 additions and 25 deletions
@@ -16,6 +16,7 @@ import { SelectionResultsPage } from "./selection-results-page"
const routerNavigate = vi.hoisted(() => vi.fn())
const useSelectionResults = vi.fn()
const useSelectionChart = vi.fn()
const useSelectionRun = vi.fn()
const useTriggerSelectionRun = vi.fn()
const mutate = vi.fn()
@@ -23,6 +24,7 @@ const reset = vi.fn()
vi.mock("@/features/selection/api/selection.query", () => ({
useSelectionResults: (...args: unknown[]) => useSelectionResults(...args),
useSelectionChart: (...args: unknown[]) => useSelectionChart(...args),
useSelectionRun: (...args: unknown[]) => useSelectionRun(...args),
useTriggerSelectionRun: () => useTriggerSelectionRun(),
}))
@@ -110,6 +112,11 @@ const selectedResult: SelectionResults = {
describe("SelectionResultsPage", () => {
beforeEach(() => {
useSelectionChart.mockReturnValue({
data: undefined,
isError: false,
isPending: false,
})
useSelectionResults.mockReturnValue({
data: selectedResult,
isError: false,
@@ -167,12 +174,23 @@ describe("SelectionResultsPage", () => {
})
expect(within(detailPanel).getByText("关键指标")).toBeInTheDocument()
expect(within(detailPanel).getByText("图形相似度评分")).toBeInTheDocument()
expect(
within(detailPanel).getByText("暂无可用行情数据。"),
).toBeInTheDocument()
expect(
within(detailPanel).getByText("最佳案例:华纳药厂"),
).toBeInTheDocument()
expect(within(detailPanel).getByText("价格形态")).toBeInTheDocument()
expect(within(detailPanel).getAllByText("J 值")).toHaveLength(2)
expect(within(detailPanel).getByText("RSI")).toBeInTheDocument()
const caseImages = within(detailPanel).getAllByRole("img", {
name: "华纳药厂 B1 参考案例图",
})
expect(caseImages).toHaveLength(1)
expect(caseImages[0]).toHaveAttribute(
"src",
"/patterns/b1-cases/case_001_688799_华纳药厂_2025-05-12.jpg",
)
})
it.each<{
@@ -184,14 +202,23 @@ describe("SelectionResultsPage", () => {
score: null,
},
{
expected: "未匹配到 60.00 分以上案例。",
expected: "低于匹配阈值",
score: {
breakdown: null,
case: null,
reason: "未匹配到评分阈值以上案例",
breakdown: {
kdj_state: 42,
price_shape: 44,
trend_structure: 40,
volume_pattern: 43,
},
case: {
breakout_date: "2025-07-23",
id: "case_004",
name: "方正科技",
},
reason: null,
status: "below_threshold",
threshold: 60,
value: null,
value: 42.5,
version: "zhixing_b1_pattern_fastdtw_v1",
},
},
@@ -225,9 +252,51 @@ describe("SelectionResultsPage", () => {
const table = screen.getByRole("table")
expect(within(table).getByText("原始 B1")).toBeInTheDocument()
expect(within(table).getByText("12")).toBeInTheDocument()
if (score?.status === "below_threshold") {
const detailPanel = screen.getByRole("complementary", {
name: "当前股票详情",
})
const images = within(detailPanel).getAllByRole("img", {
name: "方正科技 B1 参考案例图",
})
expect(images).toHaveLength(1)
expect(images[0]).toHaveAttribute(
"src",
"/patterns/b1-cases/case_004_600601_方正科技_2025-07-23.jpg",
)
expect(within(detailPanel).getAllByText("42.50 分")).toHaveLength(2)
} else {
const detailPanel = screen.getByRole("complementary", {
name: "当前股票详情",
})
expect(within(detailPanel).queryByRole("img")).not.toBeInTheDocument()
}
},
)
it("shows chart loading and error states for the selected stock", () => {
useSelectionChart.mockReturnValue({
data: undefined,
isError: false,
isPending: true,
})
const view = render(<SelectionResultsPage />)
expect(screen.getByText("正在加载行情图表…")).toBeInTheDocument()
expect(useSelectionChart).toHaveBeenLastCalledWith(
"000001.SZ",
"2026-08-08",
)
useSelectionChart.mockReturnValue({
data: undefined,
isError: true,
isPending: false,
})
view.rerender(<SelectionResultsPage />)
expect(screen.getByText("行情图表暂时不可用。")).toBeInTheDocument()
})
it("opens execution status details in a drawer and restores trigger focus", async () => {
useSelectionResults.mockReturnValue({
data: {