chore: batch start/stop models

This commit is contained in:
jialin
2025-02-17 13:49:55 +08:00
parent 8f7968302d
commit 68a62d689c
10 changed files with 93 additions and 15 deletions
+2 -2
View File
@@ -1,8 +1,8 @@
import { createFromIconfontCN } from '@ant-design/icons'; import { createFromIconfontCN } from '@ant-design/icons';
import './iconfont/iconfont.js'; // import './iconfont/iconfont.js';
const IconFont = createFromIconfontCN({ const IconFont = createFromIconfontCN({
scriptUrl: '' scriptUrl: '//at.alicdn.com/t/c/font_4613488_djdkmiu9k3b.js'
}); });
export default IconFont; export default IconFont;
@@ -174,12 +174,16 @@ const TableRow: React.FC<
if (e.target.checked) { if (e.target.checked) {
// update selectedRowKeys // update selectedRowKeys
rowSelection?.onChange( rowSelection?.onChange(
_.uniq([...rowSelection?.selectedRowKeys, record[rowKey]]) _.uniq([...rowSelection?.selectedRowKeys, record[rowKey]]),
_.uniqBy([...rowSelection?.selectedRows, record], rowKey)
); );
} else { } else {
// update selectedRowKeys // update selectedRowKeys
rowSelection?.onChange( rowSelection?.onChange(
rowSelection?.selectedRowKeys.filter((key) => key !== record[rowKey]) rowSelection?.selectedRowKeys.filter((key) => key !== record[rowKey]),
rowSelection?.selectedRows.filter(
(row) => row[rowKey] !== record[rowKey]
)
); );
} }
}; };
+5 -2
View File
@@ -62,11 +62,14 @@ const SealTable: React.FC<SealTableProps & { pagination: PaginationProps }> = (
const handleSelectAllChange = (e: any) => { const handleSelectAllChange = (e: any) => {
if (e.target.checked) { if (e.target.checked) {
rowSelection?.onChange(props.dataSource.map((record) => record[rowKey])); rowSelection?.onChange(
props.dataSource.map((record) => record[rowKey]),
props.dataSource
);
setSelectAll(true); setSelectAll(true);
setIndeterminate(false); setIndeterminate(false);
} else { } else {
rowSelection?.onChange([]); rowSelection?.onChange([], []);
setSelectAll(false); setSelectAll(false);
setIndeterminate(false); setIndeterminate(false);
} }
+2 -1
View File
@@ -36,7 +36,8 @@ export interface TableHeaderProps {
export interface RowSelectionProps { export interface RowSelectionProps {
selectedRowKeys: React.Key[]; selectedRowKeys: React.Key[];
onChange: (selectedRowKeys: React.Key[]) => void; selectedRows: any[];
onChange: (selectedRowKeys: React.Key[], selectedRows: any[]) => void;
} }
export interface SealTableProps { export interface SealTableProps {
childParentKey?: string; childParentKey?: string;
+11 -1
View File
@@ -2,29 +2,39 @@ import { useState } from 'react';
export default function useTableRowSelection() { export default function useTableRowSelection() {
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]); const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
const [selectedRows, setSelectedRows] = useState<any[]>([]);
const onSelectChange = (selectedRowKeys: React.Key[]) => { const onSelectChange = (
selectedRowKeys: React.Key[],
selectedRows: any[]
) => {
setSelectedRowKeys(selectedRowKeys); setSelectedRowKeys(selectedRowKeys);
setSelectedRows(selectedRows);
}; };
const clearSelections = () => { const clearSelections = () => {
setSelectedRowKeys([]); setSelectedRowKeys([]);
setSelectedRows([]);
}; };
const removeSelectedKey = (rowKey: React.Key | React.Key[]) => { const removeSelectedKey = (rowKey: React.Key | React.Key[]) => {
if (Array.isArray(rowKey)) { if (Array.isArray(rowKey)) {
setSelectedRowKeys((keys) => keys.filter((key) => !rowKey.includes(key))); setSelectedRowKeys((keys) => keys.filter((key) => !rowKey.includes(key)));
setSelectedRows((rows) => rows.filter((row) => !rowKey.includes(row.id)));
return; return;
} }
setSelectedRowKeys((keys) => keys.filter((key) => key !== rowKey)); setSelectedRowKeys((keys) => keys.filter((key) => key !== rowKey));
setSelectedRows((rows) => rows.filter((row) => row.id !== rowKey));
}; };
const removeSelectedKeys = (rowKeys: React.Key[]) => { const removeSelectedKeys = (rowKeys: React.Key[]) => {
setSelectedRowKeys((keys) => keys.filter((key) => !rowKeys.includes(key))); setSelectedRowKeys((keys) => keys.filter((key) => !rowKeys.includes(key)));
setSelectedRows((rows) => rows.filter((row) => !rowKeys.includes(row.id)));
}; };
const rowSelection = { const rowSelection = {
selectedRowKeys, selectedRowKeys,
selectedRows,
clearSelections, clearSelections,
onChange: onSelectChange, onChange: onSelectChange,
removeSelectedKeys, removeSelectedKeys,
+4
View File
@@ -197,6 +197,9 @@ export default {
'common.stop.confirm': 'Are you sure you want to stop the selected {type}?', 'common.stop.confirm': 'Are you sure you want to stop the selected {type}?',
'common.stop.single.confirm': 'common.stop.single.confirm':
'Are you sure you want to stop <span style="font-size: 13px;font-weight: 700">{name}</span>?', 'Are you sure you want to stop <span style="font-size: 13px;font-weight: 700">{name}</span>?',
'common.start.confirm': 'Are you sure you want to start the selected {type}?',
'common.start.single.confirm':
'Are you sure you want to start <span style="font-size: 13px;font-weight: 700">{name}</span>?',
'common.filter.name': 'Filter by name', 'common.filter.name': 'Filter by name',
'common.form.password': 'Password', 'common.form.password': 'Password',
'common.form.username': 'Username', 'common.form.username': 'Username',
@@ -208,6 +211,7 @@ export default {
'common.button.version': 'Version', 'common.button.version': 'Version',
'common.title.delete.confirm': 'Confirm delete', 'common.title.delete.confirm': 'Confirm delete',
'common.title.stop.confirm': 'Confirm stop', 'common.title.stop.confirm': 'Confirm stop',
'common.title.start.confirm': 'Confirm start',
'common.title.recreate.confirm': 'Confirm recreate', 'common.title.recreate.confirm': 'Confirm recreate',
'common.button.addLabel': 'Add Labels', 'common.button.addLabel': 'Add Labels',
'common.button.addSelector': 'Add Selectors', 'common.button.addSelector': 'Add Selectors',
+5 -1
View File
@@ -190,6 +190,9 @@ export default {
'common.stop.confirm': '停止选中的{type},确定吗?', 'common.stop.confirm': '停止选中的{type},确定吗?',
'common.stop.single.confirm': 'common.stop.single.confirm':
'停止 <span style="font-size: 13px;font-weight: 700">{name}</span>,确定吗?', '停止 <span style="font-size: 13px;font-weight: 700">{name}</span>,确定吗?',
'common.start.confirm': '启动选中的{type},确定吗?',
'common.start.single.confirm':
'启动 <span style="font-size: 13px;font-weight: 700">{name}</span>,确定吗?',
'common.filter.name': '名称查询', 'common.filter.name': '名称查询',
'common.form.password': '密码', 'common.form.password': '密码',
'common.form.username': '用户名', 'common.form.username': '用户名',
@@ -200,7 +203,8 @@ export default {
'common.button.docs': '文档', 'common.button.docs': '文档',
'common.button.version': '版本', 'common.button.version': '版本',
'common.title.delete.confirm': '确认删除', 'common.title.delete.confirm': '确认删除',
'common.title.stop.confirm': '确认', 'common.title.stop.confirm': '确认停止',
'common.title.start.confirm': '确认启动',
'common.title.recreate.confirm': '确认重新创建', 'common.title.recreate.confirm': '确认重新创建',
'common.button.addLabel': '添加标签', 'common.button.addLabel': '添加标签',
'common.button.addSelector': '添加选择器', 'common.button.addSelector': '添加选择器',
+54 -2
View File
@@ -45,7 +45,7 @@ import {
updateModel updateModel
} from '../apis'; } from '../apis';
import { import {
InstanceRealLogStatus, InstanceRealtimeLogStatus,
getSourceRepoConfigValue, getSourceRepoConfigValue,
modelCategories, modelCategories,
modelCategoriesMap, modelCategoriesMap,
@@ -472,7 +472,9 @@ const Models: React.FC<ModelsProps> = ({
status: row.state, status: row.state,
id: row.id, id: row.id,
modelId: row.model_id, modelId: row.model_id,
tail: InstanceRealLogStatus.includes(row.state) ? undefined : PageSize tail: InstanceRealtimeLogStatus.includes(row.state)
? undefined
: PageSize
}); });
setOpenLogModal(true); setOpenLogModal(true);
onViewLogs(); onViewLogs();
@@ -739,6 +741,32 @@ const Models: React.FC<ModelsProps> = ({
} }
}; };
const handleStartBatch = async () => {
modalRef.current.show({
content: 'models.table.models',
title: 'common.title.start.confirm',
okText: 'common.button.start',
operation: 'common.start.confirm',
async onOk() {
await handleBatchRequest(rowSelection.selectedRows, handleStartModel);
rowSelection.clearSelections();
}
});
};
const handleStopBatch = async () => {
modalRef.current.show({
content: 'models.table.models',
title: 'common.title.stop.confirm',
okText: 'common.button.stop',
operation: 'common.stop.confirm',
async onOk() {
await handleBatchRequest(rowSelection.selectedRows, handleStopModel);
rowSelection.clearSelections();
}
});
};
return ( return (
<> <>
<PageContainer <PageContainer
@@ -820,6 +848,30 @@ const Models: React.FC<ModelsProps> = ({
</span> </span>
</Button> </Button>
</Access> </Access>
<Button
icon={<IconFont type="icon-outline-play"></IconFont>}
onClick={handleStartBatch}
disabled={!rowSelection.selectedRows.length}
>
<span>
{intl?.formatMessage?.({ id: 'common.button.start' })}
{rowSelection.selectedRows.length > 0 && (
<span>({rowSelection.selectedRows?.length})</span>
)}
</span>
</Button>
<Button
icon={<IconFont type="icon-stop1"></IconFont>}
onClick={handleStopBatch}
disabled={!rowSelection.selectedRows.length}
>
<span>
{intl?.formatMessage?.({ id: 'common.button.stop' })}
{rowSelection.selectedRows.length > 0 && (
<span>({rowSelection.selectedRows?.length})</span>
)}
</span>
</Button>
</Space> </Space>
} }
></PageTools> ></PageTools>
@@ -4,7 +4,7 @@ import { useIntl } from '@umijs/max';
import { Modal } from 'antd'; import { Modal } from 'antd';
import React, { useCallback, useEffect, useState } from 'react'; import React, { useCallback, useEffect, useState } from 'react';
import { MODELS_API } from '../apis'; import { MODELS_API } from '../apis';
import { InstanceRealLogStatus } from '../config'; import { InstanceRealtimeLogStatus } from '../config';
type ViewModalProps = { type ViewModalProps = {
open: boolean; open: boolean;
@@ -35,10 +35,10 @@ const ViewCodeModal: React.FC<ViewModalProps> = (props) => {
const updateHandler = (list: any) => { const updateHandler = (list: any) => {
const data = list?.find((item: any) => item.data?.id === props.id); const data = list?.find((item: any) => item.data?.id === props.id);
// state in InstanceRealLogStatus will not enable scorll load, because it is in the trasisition state // state in InstanceRealtimeLogStatus will not enable scorll load, because it is in the trasisition state
if (data) { if (data) {
setEnableScorllLoad( setEnableScorllLoad(
() => !InstanceRealLogStatus.includes(data?.data?.state) () => !InstanceRealtimeLogStatus.includes(data?.data?.state)
); );
} }
}; };
+1 -1
View File
@@ -196,7 +196,7 @@ export const InstanceStatusMap = {
Unreachable: 'unreachable' Unreachable: 'unreachable'
}; };
export const InstanceRealLogStatus = [ export const InstanceRealtimeLogStatus = [
InstanceStatusMap.Downloading, InstanceStatusMap.Downloading,
InstanceStatusMap.Initializing InstanceStatusMap.Initializing
]; ];