feat: complete TanStack dashboard acceptance

This commit is contained in:
2026-09-19 12:09:01 +08:00
parent 45a29ea89d
commit 8d35318c7e
103 changed files with 6061 additions and 1065 deletions
@@ -1,6 +1,6 @@
import { useEffect, useMemo, useRef, useState } from "react";
import { Link, useParams } from "react-router";
import { useDataProvider } from "@refinedev/core";
import { Link, useParams } from "../../shared/router.jsx";
import { useDataProvider } from "../../shared/hooks/dataHooks.js";
import {
Alert,
Button,
+2 -2
View File
@@ -1,6 +1,6 @@
import { useEffect, useMemo, useState } from "react";
import { Link, useNavigate, useParams } from "react-router";
import { useDataProvider, useList, useOne } from "@refinedev/core";
import { Link, useNavigate, useParams } from "../../shared/router.jsx";
import { useDataProvider, useList, useOne } from "../../shared/hooks/dataHooks.js";
import {
Alert,
Button,
@@ -7,8 +7,8 @@ import {
waitFor,
} from "@testing-library/react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { Refine } from "@refinedev/core";
import { MemoryRouter, Route, Routes } from "react-router";
import { TestDataProvider } from "../../test/providerCompat.jsx";
import { MemoryRouter, Route, Routes } from "../../test/routerCompat.jsx";
import {
AccountCreatePage,
AccountDetail,
@@ -85,11 +85,11 @@ const queryClient = () =>
function renderList(dataProvider) {
return render(
<QueryClientProvider client={queryClient()}>
<Refine dataProvider={dataProvider}>
<TestDataProvider dataProvider={dataProvider}>
<MemoryRouter>
<AccountList />
</MemoryRouter>
</Refine>
</TestDataProvider>
</QueryClientProvider>,
);
}
@@ -97,13 +97,13 @@ function renderList(dataProvider) {
function renderDetail(dataProvider) {
return render(
<QueryClientProvider client={queryClient()}>
<Refine dataProvider={dataProvider}>
<TestDataProvider dataProvider={dataProvider}>
<MemoryRouter initialEntries={["/accounts/account-a"]}>
<Routes>
<Route path="/accounts/:id" element={<AccountDetail />} />
</Routes>
</MemoryRouter>
</Refine>
</TestDataProvider>
</QueryClientProvider>,
);
}
@@ -111,13 +111,13 @@ function renderDetail(dataProvider) {
function renderCreate(dataProvider) {
return render(
<QueryClientProvider client={queryClient()}>
<Refine dataProvider={dataProvider}>
<TestDataProvider dataProvider={dataProvider}>
<MemoryRouter initialEntries={["/accounts/new"]}>
<Routes>
<Route path="/accounts/new" element={<AccountCreatePage />} />
</Routes>
</MemoryRouter>
</Refine>
</TestDataProvider>
</QueryClientProvider>,
);
}
@@ -7,8 +7,8 @@ import {
waitFor,
} from "@testing-library/react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { Refine } from "@refinedev/core";
import { MemoryRouter, Route, Routes } from "react-router";
import { TestDataProvider } from "../../test/providerCompat.jsx";
import { MemoryRouter, Route, Routes } from "../../test/routerCompat.jsx";
import { AccountEditPage } from "../accounts/AccountEditPage";
import { AccountList } from "../accounts/AccountsPage";
import { CreatorCompetitorsPage } from "./competitors/CreatorCompetitorsPage";
@@ -90,9 +90,9 @@ function provider(overrides = {}) {
function renderPage(element, dataProvider) {
return render(
<QueryClientProvider client={new QueryClient()}>
<Refine dataProvider={dataProvider}>
<TestDataProvider dataProvider={dataProvider}>
<MemoryRouter>{element}</MemoryRouter>
</Refine>
</TestDataProvider>
</QueryClientProvider>,
);
}
@@ -100,13 +100,13 @@ function renderPage(element, dataProvider) {
function renderAccountPage(dataProvider) {
return render(
<QueryClientProvider client={new QueryClient()}>
<Refine dataProvider={dataProvider}>
<TestDataProvider dataProvider={dataProvider}>
<MemoryRouter initialEntries={["/accounts/account-a/edit"]}>
<Routes>
<Route path="/accounts/:id/edit" element={<AccountEditPage />} />
</Routes>
</MemoryRouter>
</Refine>
</TestDataProvider>
</QueryClientProvider>,
);
}
@@ -498,7 +498,6 @@ describe("creator pages", () => {
expect.objectContaining({
resource: "creator-competitor-preview",
variables: {
account_id: "account-a",
platform: "douyin",
share_url: "https://v.douyin.com/share-a/",
},
@@ -511,7 +510,6 @@ describe("creator pages", () => {
expect.objectContaining({
resource: "creator-competitors",
variables: {
account_id: "account-a",
platform: "douyin",
share_url: "https://v.douyin.com/share-a/",
tags: ["重点监测"],
@@ -1,5 +1,5 @@
import { useEffect, useState } from "react";
import { useDataProvider } from "@refinedev/core";
import { useDataProvider } from "../../../shared/hooks/dataHooks.js";
import {
Alert,
Button,
@@ -64,7 +64,6 @@ export function CreatorCompetitorsPage() {
total: 0,
hasNext: false,
});
const [accounts, setAccounts] = useState([]);
const [platform, setPlatform] = useState("");
const [createOpen, setCreateOpen] = useState(false);
const [shareText, setShareText] = useState("");
@@ -81,7 +80,6 @@ export function CreatorCompetitorsPage() {
const [previewConfirmed, setPreviewConfirmed] = useState(false);
const [error, setError] = useState(null);
const [notice, setNotice] = useState(null);
const [accountError, setAccountError] = useState(null);
const [material, setMaterial] = useState(null);
const [materialPending, setMaterialPending] = useState(false);
const [rewriteRequirement, setRewriteRequirement] = useState("");
@@ -154,15 +152,6 @@ export function CreatorCompetitorsPage() {
publishedAfter,
publishedBefore,
]);
useEffect(() => {
dataProvider
.getList({ resource: "creator-accounts" })
.then((result) => {
setAccountError(null);
setAccounts(result.data);
})
.catch((loadError) => setAccountError(loadError));
}, [dataProvider]);
const extractedShareURL = extractShareURL(shareText);
const sharePlatform = platformForShareURL(extractedShareURL);
const closeCreate = () => {
@@ -183,33 +172,18 @@ export function CreatorCompetitorsPage() {
setNotice({ variant: "warning", text: "链接不是支持的平台分享链接。" });
return;
}
const account = accounts.find(
(value) =>
value.platform === sharePlatform &&
value.authorization_status === "authorized" &&
(value.business_status === "normal" || value.business_status === "muted") &&
value.login_status === "logged_in",
);
if (!account) {
setNotice({
variant: "warning",
text: `没有可用于解析${sharePlatform === "douyin" ? "抖音" : "小红书"}分享内容的已登录账号。`,
});
return;
}
setBusy(true);
setNotice(null);
try {
const result = await dataProvider.create({
resource: "creator-competitor-preview",
variables: {
account_id: account.id,
platform: sharePlatform,
share_url: extractedShareURL,
},
});
const verified = result.data;
setPreview({ ...verified, account_id: account.id, share_url: extractedShareURL });
setPreview({ ...verified, share_url: extractedShareURL });
setPreviewConfirmed(false);
setNotice({
variant: "info",
@@ -233,7 +207,6 @@ export function CreatorCompetitorsPage() {
setNotice(null);
try {
const variables = {
account_id: preview.account_id,
platform: preview.platform,
share_url: preview.share_url || extractedShareURL,
};
@@ -610,12 +583,6 @@ export function CreatorCompetitorsPage() {
/>
</Field>
</div>
{accountError ? (
<Alert variant="warning" className="mb-4">
同平台账号读取失败:
{conflictMessage(accountError, "请重试账号列表")}
</Alert>
) : null}
<PageState
pending={pending}
error={error}
@@ -1,5 +1,5 @@
import { useEffect, useState } from "react";
import { useDataProvider } from "@refinedev/core";
import { useDataProvider } from "../../../shared/hooks/dataHooks.js";
import {
Alert,
Button,
@@ -1,5 +1,5 @@
import { useEffect, useRef, useState } from "react";
import { useDataProvider } from "@refinedev/core";
import { useDataProvider } from "../../../shared/hooks/dataHooks.js";
import {
Alert,
Button,
@@ -1,5 +1,5 @@
import { useState } from "react";
import { useDataProvider, useList } from "@refinedev/core";
import { useDataProvider, useList } from "../../shared/hooks/dataHooks.js";
import {
Alert,
Button,
@@ -8,8 +8,8 @@ import {
within,
} from "@testing-library/react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { Refine } from "@refinedev/core";
import { MemoryRouter } from "react-router";
import { TestDataProvider } from "../../test/providerCompat.jsx";
import { MemoryRouter } from "../../test/routerCompat.jsx";
import { BrowserVersionList } from "./BrowserVersionsPage";
afterEach(() => {
@@ -59,11 +59,11 @@ const renderVersions = (dataProvider) =>
new QueryClient({ defaultOptions: { queries: { retry: false } } })
}
>
<Refine dataProvider={dataProvider}>
<TestDataProvider dataProvider={dataProvider}>
<MemoryRouter>
<BrowserVersionList />
</MemoryRouter>
</Refine>
</TestDataProvider>
</QueryClientProvider>,
);
@@ -1,6 +1,6 @@
import { useEffect, useState } from "react";
import { Link, useNavigate, useParams } from "react-router";
import { useDataProvider, useList, useOne } from "@refinedev/core";
import { Link, useNavigate, useParams } from "../../shared/router.jsx";
import { useDataProvider, useList, useOne } from "../../shared/hooks/dataHooks.js";
import {
Alert,
Button,
@@ -8,8 +8,8 @@ import {
within,
} from "@testing-library/react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { Refine } from "@refinedev/core";
import { MemoryRouter } from "react-router";
import { TestDataProvider } from "../../test/providerCompat.jsx";
import { MemoryRouter } from "../../test/routerCompat.jsx";
import { BrowserCreatePage, BrowserList } from "./BrowsersPage";
afterEach(() => {
@@ -126,22 +126,22 @@ const queryClient = () =>
const renderList = (dataProvider) =>
render(
<QueryClientProvider client={queryClient()}>
<Refine dataProvider={dataProvider}>
<TestDataProvider dataProvider={dataProvider}>
<MemoryRouter>
<BrowserList />
</MemoryRouter>
</Refine>
</TestDataProvider>
</QueryClientProvider>,
);
const renderCreate = (dataProvider) =>
render(
<QueryClientProvider client={queryClient()}>
<Refine dataProvider={dataProvider}>
<TestDataProvider dataProvider={dataProvider}>
<MemoryRouter initialEntries={["/browsers/new"]}>
<BrowserCreatePage />
</MemoryRouter>
</Refine>
</TestDataProvider>
</QueryClientProvider>,
);
@@ -1,5 +1,5 @@
import { useEffect, useState } from "react";
import { useDataProvider, useList } from "@refinedev/core";
import { useDataProvider, useList } from "../../shared/hooks/dataHooks.js";
import {
Alert,
Button,
@@ -8,8 +8,8 @@ import {
within,
} from "@testing-library/react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { Refine } from "@refinedev/core";
import { MemoryRouter } from "react-router";
import { TestDataProvider } from "../../test/providerCompat.jsx";
import { MemoryRouter } from "../../test/routerCompat.jsx";
import { GatewayList } from "./GatewaysPage";
afterEach(() => {
@@ -63,11 +63,11 @@ const renderGateways = (dataProvider) =>
new QueryClient({ defaultOptions: { queries: { retry: false } } })
}
>
<Refine dataProvider={dataProvider}>
<TestDataProvider dataProvider={dataProvider}>
<MemoryRouter>
<GatewayList />
</MemoryRouter>
</Refine>
</TestDataProvider>
</QueryClientProvider>,
);
@@ -1,6 +1,6 @@
import { useEffect, useMemo, useState } from "react";
import { Link, useParams } from "react-router";
import { useDataProvider, useList, useOne } from "@refinedev/core";
import { Link, useParams } from "../../shared/router.jsx";
import { useDataProvider, useList, useOne } from "../../shared/hooks/dataHooks.js";
import {
Alert,
Button,
@@ -8,8 +8,8 @@ import {
within,
} from "@testing-library/react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { Refine } from "@refinedev/core";
import { MemoryRouter } from "react-router";
import { TestDataProvider } from "../../test/providerCompat.jsx";
import { MemoryRouter } from "../../test/routerCompat.jsx";
import { NetworkExitList } from "./NetworkExitsPage";
afterEach(() => {
@@ -60,11 +60,11 @@ const renderExits = (dataProvider) =>
new QueryClient({ defaultOptions: { queries: { retry: false } } })
}
>
<Refine dataProvider={dataProvider}>
<TestDataProvider dataProvider={dataProvider}>
<MemoryRouter>
<NetworkExitList />
</MemoryRouter>
</Refine>
</TestDataProvider>
</QueryClientProvider>,
);
+2 -2
View File
@@ -1,6 +1,6 @@
import { useEffect, useState } from 'react'
import { Link, useSearchParams } from 'react-router'
import { useList } from '@refinedev/core'
import { Link, useSearchParams } from '../../shared/router.jsx'
import { useList } from '../../shared/hooks/dataHooks.js'
import { Alert, Button, PageHeader, PageState, Table } from '../../shared/ui/ui.jsx'
import { useTitle } from '../../shared/hooks/hooks.js'
@@ -1,8 +1,8 @@
import { afterEach, describe, expect, it, vi } from 'vitest'
import { cleanup, fireEvent, render, screen, waitFor, within } from '@testing-library/react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { Refine } from '@refinedev/core'
import { MemoryRouter } from 'react-router'
import { TestDataProvider } from '../../test/providerCompat.jsx'
import { MemoryRouter } from '../../test/routerCompat.jsx'
import { AuditPage, auditCSV } from './AuditPage'
afterEach(() => { cleanup(); vi.restoreAllMocks() })
@@ -12,9 +12,9 @@ const httpQuery = () => new QueryClient({ defaultOptions: { queries: { retry: fa
function renderAudit(dataProvider, initialEntry = '/audit?task_id=task-a') {
return render(
<QueryClientProvider client={httpQuery()}>
<Refine dataProvider={dataProvider}>
<TestDataProvider dataProvider={dataProvider}>
<MemoryRouter initialEntries={[initialEntry]}><AuditPage /></MemoryRouter>
</Refine>
</TestDataProvider>
</QueryClientProvider>,
)
}
+2 -2
View File
@@ -1,6 +1,6 @@
import { useState } from 'react'
import { useNavigate, useParams } from 'react-router'
import { useDataProvider, useList, useOne } from '@refinedev/core'
import { useNavigate, useParams } from '../../shared/router.jsx'
import { useDataProvider, useList, useOne } from '../../shared/hooks/dataHooks.js'
import {
Alert, Button, Card, CardContent, Checkbox, ConfirmDialog, DetailList, Field, Input, Modal,
PageHeader, PageState, StatusPill, conflictMessage,
@@ -1,8 +1,8 @@
import { afterEach, describe, expect, it, vi } from 'vitest'
import { cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { Refine } from '@refinedev/core'
import { MemoryRouter, Route, Routes } from 'react-router'
import { TestDataProvider } from '../../test/providerCompat.jsx'
import { MemoryRouter, Route, Routes } from '../../test/routerCompat.jsx'
import { DraftPage } from './DraftPage'
afterEach(() => { cleanup(); vi.restoreAllMocks() })
@@ -30,9 +30,9 @@ function provider(record = draft, overrides = {}) {
const renderDraft = (dataProvider, id = 'draft-a') => render(
<QueryClientProvider client={new QueryClient({ defaultOptions: { queries: { retry: false } } })}>
<Refine dataProvider={dataProvider}>
<TestDataProvider dataProvider={dataProvider}>
<MemoryRouter initialEntries={[`/drafts/${id}`]}><Routes><Route path="/drafts/:id" element={<DraftPage />} /></Routes></MemoryRouter>
</Refine>
</TestDataProvider>
</QueryClientProvider>,
)
+2 -2
View File
@@ -1,6 +1,6 @@
import { useState } from 'react'
import { Link, useNavigate, useParams } from 'react-router'
import { useDataProvider, useList, useOne } from '@refinedev/core'
import { Link, useNavigate, useParams } from '../../shared/router.jsx'
import { useDataProvider, useList, useOne } from '../../shared/hooks/dataHooks.js'
import {
Alert, Button, Card, CardContent, DetailList, Field, PageHeader, PageState, Select, StatusPill,
} from '../../shared/ui/ui.jsx'
@@ -1,8 +1,8 @@
import { afterEach, describe, expect, it, vi } from 'vitest'
import { cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { Refine } from '@refinedev/core'
import { MemoryRouter, Route, Routes } from 'react-router'
import { TestDataProvider } from '../../test/providerCompat.jsx'
import { MemoryRouter, Route, Routes } from '../../test/routerCompat.jsx'
import { TaskDetail, TaskList } from './TasksPage'
afterEach(() => { cleanup(); vi.restoreAllMocks() })
@@ -27,19 +27,19 @@ const queryClient = () => new QueryClient({ defaultOptions: { queries: { retry:
const renderTask = dataProvider => render(
<QueryClientProvider client={queryClient()}>
<Refine dataProvider={dataProvider}>
<TestDataProvider dataProvider={dataProvider}>
<MemoryRouter initialEntries={['/tasks/task-a']}>
<Routes><Route path="/tasks/:id" element={<TaskDetail />} /></Routes>
</MemoryRouter>
</Refine>
</TestDataProvider>
</QueryClientProvider>,
)
const renderTasks = dataProvider => render(
<QueryClientProvider client={queryClient()}>
<Refine dataProvider={dataProvider}>
<TestDataProvider dataProvider={dataProvider}>
<MemoryRouter><TaskList /></MemoryRouter>
</Refine>
</TestDataProvider>
</QueryClientProvider>,
)
+2 -2
View File
@@ -1,5 +1,5 @@
import { Link, useParams } from 'react-router'
import { useOne } from '@refinedev/core'
import { Link, useParams } from '../../shared/router.jsx'
import { useOne } from '../../shared/hooks/dataHooks.js'
import { Alert, Button, Card, CardContent, DetailList, PageHeader, PageState } from '../../shared/ui/ui.jsx'
import { useTitle } from '../../shared/hooks/hooks.js'