Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/backend-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Backend Docker Build and Publish

on:
push:
branches: [main, master, workflow-dev]
branches: [main, master, workflow-dev, dev]
paths:
- "backend/**"
tags: ["v*.*.*"]
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/frontend-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Frontend Docker Build and Publish

on:
push:
branches: [main, master, workflow-dev]
branches: [main, master, workflow-dev, dev]
paths:
- "frontend/**"
tags: ["v*.*.*"]
Expand Down
152 changes: 87 additions & 65 deletions frontend/src/components/DataTable.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { ReactNode, useState, KeyboardEvent } from "react";
import React, { ReactNode, useMemo, useState } from "react";
import {
Table,
TableHeader,
Expand All @@ -19,7 +19,7 @@ import {
DropdownSection,
} from "@heroui/dropdown";
import { Tooltip } from "@heroui/tooltip";
import { NumberInput } from "@heroui/number-input";
import { Input } from "@heroui/input";

import LoadingSpinner from "./LoadingSpinner";
import ErrorDisplay from "./ErrorDisplay";
Expand Down Expand Up @@ -105,6 +105,8 @@ export interface DataTableProps<T> {
selectedKeys?: Selection;
onSelectionChange?: (keys: Set<Key>) => void;
selectionToolbarContent?: ReactNode;
showJumper?: boolean;
showCustomPageSize?: boolean;
}

// 通用DataTable组件
Expand Down Expand Up @@ -142,6 +144,8 @@ export const DataTable = <T extends { id?: number | string }>({
selectedKeys,
onSelectionChange,
selectionToolbarContent,
showJumper = true,
showCustomPageSize = true,
}: DataTableProps<T>) => {
// 获取表头列
const headerColumns = React.useMemo(() => {
Expand All @@ -155,25 +159,46 @@ export const DataTable = <T extends { id?: number | string }>({
// 每页行数
const pageSizeOptions = [5, 10, 15, 30, 50];
const [pageSizeSelectedKeys, setPageSizeSelectedKeys] = useState(
new Set([selectedSize.toString()]),
pageSizeOptions.includes(selectedSize)
? new Set([selectedSize.toString()])
: new Set(["custom"]),
);

// 自定义页面大小
const [customPageSize, setCustomPageSize] = useState<number | null>(null);
const [customPageSize, setCustomPageSize] = useState<string>(
selectedSize.toString(),
);

// 验证自定义页面大小的函数
const validateCustomPageSize = (value: string): boolean => {
return (
value.match(/^\d+$/) &&
Number(value) >= minPageSize &&
Number(value) <= maxPageSize
);
};

// 判断自定义页面大小是否无效
const isInvalidCustomPageSize = useMemo(() => {
return !validateCustomPageSize(customPageSize);
}, [customPageSize, minPageSize, maxPageSize]);

// 处理自定义页面大小应用
const applyCustomPageSize = () => {
if (
customPageSize === null ||
customPageSize < minPageSize ||
customPageSize > maxPageSize
) {
if (isInvalidCustomPageSize) {
return;
}

setSize?.(customPageSize);
setPageSizeSelectedKeys(new Set([customPageSize.toString()]));
setCustomPageSize(selectedSize);
const customPageSizeNumber = Number(customPageSize);

setSize?.(customPageSizeNumber);
if (pageSizeOptions.includes(customPageSizeNumber)) {
setPageSizeSelectedKeys(new Set([customPageSize]));
} else {
setPageSizeSelectedKeys(new Set(["custom"]));
}

setCustomPageSize(customPageSize);
onPageChange(1);
};

Expand All @@ -191,7 +216,7 @@ export const DataTable = <T extends { id?: number | string }>({
{pages > 1 && (
<Pagination
currentPage={page}
showJumper={true}
showJumper={showJumper}
totalPages={pages}
onPageChange={onPageChange}
/>
Expand Down Expand Up @@ -300,6 +325,7 @@ export const DataTable = <T extends { id?: number | string }>({
if (key && key !== "custom") {
setSize(Number(key));
setPageSizeSelectedKeys(new Set([key]));
setCustomPageSize(key);
onPageChange(1);
}
}}
Expand All @@ -309,59 +335,45 @@ export const DataTable = <T extends { id?: number | string }>({
<DropdownItem key={size}>{size}</DropdownItem>
))}
</DropdownSection>
<DropdownSection title="自定义">
<DropdownItem
isReadOnly
endContent={
<Button
color="primary"
size="sm"
variant="flat"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
applyCustomPageSize();
}}
>
应用
</Button>
}
startContent={
<NumberInput
hideStepper
aria-label="自定义页面大小"
className="w-20"
classNames={{
mainWrapper: "h-8",
input: "h-8",
inputWrapper: "h-8 min-h-8",
}}
maxValue={maxPageSize}
minValue={minPageSize}
placeholder={`${minPageSize}-${maxPageSize}`}
radius="sm"
size="sm"
validate={(value) => {
if (value < minPageSize) {
return `页面大小不能小于 ${minPageSize}`;
{showCustomPageSize && (
<DropdownSection title="自定义">
<DropdownItem
isReadOnly
endContent={
<Button
color="primary"
size="sm"
variant="flat"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
applyCustomPageSize();
}}
>
应用
</Button>
}
startContent={
<Input
aria-label="自定义页面大小"
className="w-20"
color={
isInvalidCustomPageSize ? "danger" : "default"
}

if (value > maxPageSize) {
return `页面大小不能大于 ${maxPageSize}`;
}

return null;
}}
value={customPageSize}
onKeyDown={handleKeyDown}
onValueChange={(value) => {
setCustomPageSize(value);
}}
/>
}
textValue="自定义页面大小"
/>
</DropdownSection>
errorMessage={`页面大小必须在 ${minPageSize} 到 ${maxPageSize} 之间`}
isInvalid={isInvalidCustomPageSize}
placeholder={`${minPageSize}-${maxPageSize}`}
radius="sm"
size="sm"
value={customPageSize}
onKeyDown={handleKeyDown}
onValueChange={setCustomPageSize}
/>
}
textValue="自定义页面大小"
/>
</DropdownSection>
)}
</DropdownMenu>
</Dropdown>
)}
Expand Down Expand Up @@ -396,6 +408,16 @@ export const DataTable = <T extends { id?: number | string }>({
selectionMode,
selectedKeys,
selectionToolbarContent,
pages,
setSize,
selectedSize,
pageSizeSelectedKeys,
customPageSize,
isInvalidCustomPageSize,
minPageSize,
maxPageSize,
applyCustomPageSize,
handleKeyDown,
]);

// 渲染表格
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/endpoints/DetailDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ const EndpointDetailDrawer = ({
renderCell={renderCell}
selectedSize={size}
setSize={setSize}
showCustomPageSize={false}
title="可用模型"
total={endpoint.ai_models.total}
onPageChange={handlePageChange}
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/models/DetailDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ const ModelDetailDrawer = ({ id, isOpen, onClose }: ModelDetailProps) => {
renderCell={renderCell}
selectedSize={size}
setSize={setSize}
showCustomPageSize={false}
title="可用端点"
total={model.endpoints.total}
onPageChange={handlePageChange}
Expand Down
56 changes: 29 additions & 27 deletions frontend/src/pages/settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -178,34 +178,36 @@ const Settings = () => {
</form>
</Card>

<Card className="p-6 mt-6">
<h2 className="text-xl font-semibold mb-4">系统设置</h2>
<form onSubmit={handleUpdateEndpointTaskInterval}>
<div className="space-y-3">
<div className="flex justify-between">
<Input
description="设为 0 禁用自动更新"
label="更新端点任务间隔(小时)"
min={0}
type="number"
value={updateEndpointTaskInterval}
onChange={(e) =>
setUpdateEndpointTaskInterval(Number(e.target.value))
}
/>
</div>
<div className="flex justify-between">
<Button
color="primary"
isLoading={isUpdateEndpointTaskIntervalLoading}
type="submit"
>
更新
</Button>
{isAdmin && (
<Card className="p-6 mt-6">
<h2 className="text-xl font-semibold mb-4">系统设置</h2>
<form onSubmit={handleUpdateEndpointTaskInterval}>
<div className="space-y-3">
<div className="flex justify-between">
<Input
description="设为 0 禁用自动更新"
label="更新端点任务间隔(小时)"
min={0}
type="number"
value={updateEndpointTaskInterval}
onChange={(e) =>
setUpdateEndpointTaskInterval(Number(e.target.value))
}
/>
</div>
<div className="flex justify-between">
<Button
color="primary"
isLoading={isUpdateEndpointTaskIntervalLoading}
type="submit"
>
更新
</Button>
</div>
</div>
</div>
</form>
</Card>
</form>
</Card>
)}

<Card className="p-6 mt-6">
<h2 className="text-xl font-semibold mb-4">账户信息</h2>
Expand Down