fix: 项目表格列优化 — 描述列可见、标题简化、操作列自适应宽度
This commit is contained in:
@@ -46,7 +46,7 @@ bun run dev config.yaml
|
||||
- **Admin(管理台)**:全局管理视角,包含总览和项目管理。默认入口,访问 `/` 即可进入。
|
||||
- **Workbench(工作台)**:项目维度视角,通过 `/workbench/:projectId` 进入指定项目的工作台。URL 可保存为浏览器书签,下次直接进入。仅 active 状态的项目可进入工作台,archived 项目不可访问。
|
||||
|
||||
从项目管理页面的 active 项目行可点击"进入工作台"跳转到对应项目的工作台。
|
||||
从项目管理页面的 active 项目行可点击"工作台"跳转到对应项目的工作台。
|
||||
|
||||
## 模型管理
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { DeleteOutlined, EditOutlined, InboxOutlined, LoginOutlined, RedoOutline
|
||||
import { App as AntApp, Button, Popconfirm, Space, Table, Tag } from "antd";
|
||||
import { useNavigate } from "react-router";
|
||||
|
||||
import type { Project, ProjectListResponse } from "../../../../shared/api";
|
||||
import type { Project, ProjectListResponse, ProjectStatus } from "../../../../shared/api";
|
||||
|
||||
interface ProjectTableProps {
|
||||
data: ProjectListResponse | undefined;
|
||||
@@ -16,11 +16,12 @@ interface ProjectTableProps {
|
||||
onRestore: (id: string) => Promise<unknown>;
|
||||
page: number;
|
||||
pageSize: number;
|
||||
status: ProjectStatus;
|
||||
}
|
||||
|
||||
const COLUMNS: ColumnsType<Project> = [
|
||||
{ dataIndex: "name", ellipsis: true, title: "项目名称", width: 160 },
|
||||
{ dataIndex: "description", ellipsis: true, title: "项目描述" },
|
||||
{ dataIndex: "name", ellipsis: true, title: "名称", width: 140 },
|
||||
{ dataIndex: "description", ellipsis: true, title: "描述" },
|
||||
{
|
||||
align: "center",
|
||||
dataIndex: "status",
|
||||
@@ -31,21 +32,21 @@ const COLUMNS: ColumnsType<Project> = [
|
||||
return <Tag color="blue">进行中</Tag>;
|
||||
},
|
||||
title: "状态",
|
||||
width: 100,
|
||||
width: 90,
|
||||
},
|
||||
{
|
||||
align: "center",
|
||||
dataIndex: "createdAt",
|
||||
render: (_value, record: Project) => formatDatetime(record.createdAt),
|
||||
title: "创建时间",
|
||||
width: 185,
|
||||
width: 180,
|
||||
},
|
||||
{
|
||||
align: "center",
|
||||
dataIndex: "updatedAt",
|
||||
render: (_value, record: Project) => formatDatetime(record.updatedAt),
|
||||
title: "更新时间",
|
||||
width: 185,
|
||||
width: 180,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -59,6 +60,7 @@ export function ProjectTable({
|
||||
onRestore,
|
||||
page,
|
||||
pageSize,
|
||||
status,
|
||||
}: ProjectTableProps) {
|
||||
const { message } = AntApp.useApp();
|
||||
const navigate = useNavigate();
|
||||
@@ -92,7 +94,6 @@ export function ProjectTable({
|
||||
|
||||
const operationColumn: ColumnsType<Project>[number] = {
|
||||
dataIndex: "op",
|
||||
fixed: "right",
|
||||
render: (_value, record: Project) => {
|
||||
if (record.status === "active") {
|
||||
return (
|
||||
@@ -103,7 +104,7 @@ export function ProjectTable({
|
||||
size="small"
|
||||
type="link"
|
||||
>
|
||||
进入工作台
|
||||
工作台
|
||||
</Button>
|
||||
<Button icon={<EditOutlined />} onClick={() => onEdit(record)} size="small" type="link">
|
||||
编辑
|
||||
@@ -140,7 +141,7 @@ export function ProjectTable({
|
||||
);
|
||||
},
|
||||
title: "操作",
|
||||
width: 280,
|
||||
width: status === "active" ? 260 : 160,
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -157,7 +158,6 @@ export function ProjectTable({
|
||||
total: data?.total ?? 0,
|
||||
}}
|
||||
rowKey="id"
|
||||
scroll={{ x: 900 }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ export function ProjectToolbar({
|
||||
onSearchClear();
|
||||
}}
|
||||
onSearch={(value) => onSearch(value)}
|
||||
placeholder="搜索项目名称或描述"
|
||||
placeholder="搜索名称或描述"
|
||||
value={draftKeyword}
|
||||
/>
|
||||
{activeTab === "active" && (
|
||||
|
||||
@@ -73,6 +73,7 @@ export function ProjectsPage() {
|
||||
onRestore={(id) => restoreMutation.mutateAsync(id)}
|
||||
page={page}
|
||||
pageSize={pageSize}
|
||||
status={tabValue}
|
||||
/>
|
||||
|
||||
<ProjectFormModal
|
||||
|
||||
@@ -125,7 +125,7 @@ describe("ProjectsPage", () => {
|
||||
|
||||
expect(screen.getByText("已归档")).not.toBeNull();
|
||||
expect(screen.getByRole("button", { name: /新建项目/ })).not.toBeNull();
|
||||
expect(screen.getByPlaceholderText("搜索项目名称或描述")).not.toBeNull();
|
||||
expect(screen.getByPlaceholderText("搜索名称或描述")).not.toBeNull();
|
||||
expect(calls.some((call) => call.url.includes("status=active"))).toBe(true);
|
||||
});
|
||||
|
||||
@@ -135,7 +135,7 @@ describe("ProjectsPage", () => {
|
||||
renderWithProviders(createElement(App), { initialRoute: "/projects" });
|
||||
await waitFor(() => expect(screen.getByText("活跃项目")).not.toBeNull());
|
||||
|
||||
fireEvent.change(screen.getByPlaceholderText("搜索项目名称或描述"), { target: { value: "归档" } });
|
||||
fireEvent.change(screen.getByPlaceholderText("搜索名称或描述"), { target: { value: "归档" } });
|
||||
fireEvent.click(screen.getByRole("button", { name: /搜\s*索/ }));
|
||||
await waitFor(() => expect(calls.some((call) => call.url.includes("keyword=%E5%BD%92%E6%A1%A3"))).toBe(true));
|
||||
fireEvent.click(screen.getByText("已归档"));
|
||||
@@ -152,11 +152,11 @@ describe("ProjectsPage", () => {
|
||||
renderWithProviders(createElement(App), { initialRoute: "/projects" });
|
||||
await waitFor(() => expect(screen.getByText("活跃项目")).not.toBeNull());
|
||||
|
||||
fireEvent.change(screen.getByPlaceholderText("搜索项目名称或描述"), { target: { value: "归档" } });
|
||||
fireEvent.change(screen.getByPlaceholderText("搜索名称或描述"), { target: { value: "归档" } });
|
||||
fireEvent.click(screen.getByRole("button", { name: /搜\s*索/ }));
|
||||
await waitFor(() => expect(calls.some((call) => call.url.includes("keyword=%E5%BD%92%E6%A1%A3"))).toBe(true));
|
||||
|
||||
fireEvent.change(screen.getByPlaceholderText("搜索项目名称或描述"), { target: { value: "" } });
|
||||
fireEvent.change(screen.getByPlaceholderText("搜索名称或描述"), { target: { value: "" } });
|
||||
fireEvent.click(screen.getByRole("button", { name: /搜\s*索/ }));
|
||||
await waitFor(() => expect(screen.getByText("活跃项目")).not.toBeNull());
|
||||
});
|
||||
@@ -255,11 +255,12 @@ describe("ProjectsPage", () => {
|
||||
onRestore,
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
status: "active",
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
fireEvent.click(screen.getByRole("button", { name: /进入工作台/ }));
|
||||
fireEvent.click(screen.getByRole("button", { name: /工作台/ }));
|
||||
expect(screen.getByText("当前路径:/workbench/p1")).not.toBeNull();
|
||||
|
||||
fireEvent.click(screen.getByRole("button", { name: /归档/ }));
|
||||
|
||||
Reference in New Issue
Block a user