You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
430 lines
14 KiB
TypeScript
430 lines
14 KiB
TypeScript
/*
|
|
* @Author: donghao donghao@supervision.ltd
|
|
* @Date: 2024-04-07 14:02:00
|
|
* @LastEditors: donghao donghao@supervision.ltd
|
|
* @LastEditTime: 2024-07-25 10:47:10
|
|
* @FilePath: \general-ai-manage\src\pages\ModelIndex\ModelIndex.tsx
|
|
* @Description: 模型列表首页
|
|
* @交互说明
|
|
* 1. 模型列表分页展示、关键词检索
|
|
* 2. 新增、删除(模型)功能
|
|
* 3. 更新模型分类功能
|
|
* 4. 模型详情配置入口
|
|
*
|
|
*/
|
|
import { CommButton } from '@/components/Button';
|
|
import CategorizeUpdate from '@/components/CategorizeUpdate';
|
|
import TableActionCard from '@/components/TableActionCard';
|
|
import IsDelete from '@/components/TableActionCard/isDelete';
|
|
import {
|
|
apiModelClassificationAdd,
|
|
apiModelClassificationDelete,
|
|
apiModelClassificationEdit,
|
|
apiModelClassificationList,
|
|
apiModelDelete,
|
|
apiModelInfo,
|
|
apiModelList,
|
|
} from '@/services/business/model';
|
|
import { isSuccessApi } from '@/utils/forApi';
|
|
import { ReactComponent as ResetIcon } from '/public/home/reset_icon.svg';
|
|
import { ReactComponent as SearchIcon } from '/public/home/search_icon.svg';
|
|
|
|
import { SearchOutlined } from '@ant-design/icons';
|
|
import type { ActionType, ProColumns } from '@ant-design/pro-components';
|
|
import { ProCard, ProForm, ProFormText, ProTable } from '@ant-design/pro-components';
|
|
import { Access, FormattedMessage, history, useAccess, useIntl } from '@umijs/max';
|
|
import { Button, message } from 'antd';
|
|
import React, { useEffect, useRef, useState } from 'react';
|
|
import {
|
|
proTableCommonOptions,
|
|
proTableDefaultOptions,
|
|
proTablePaginationOptions,
|
|
} from '../../../../config/defaultTable';
|
|
import CreateForm from './components/createForm';
|
|
import UpdateForm from './components/updateForm';
|
|
|
|
import './index.less';
|
|
const ModelIndex: React.FC = () => {
|
|
const access = useAccess();
|
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
const intl = useIntl();
|
|
const actionRef = useRef<ActionType>();
|
|
const [querysData, setQuerysData] = useState<Record<string, any>>({}); // 列表查询参数
|
|
const [createModalOpen, setCreateModalOpen] = useState<boolean>(false);
|
|
const [updateModalOpen, setUpdateModalOpen] = useState<boolean>(false);
|
|
const [currentRow, setCurrentRow] = useState<Record<string, any>>({});
|
|
|
|
// 设置分类
|
|
const [industryOpen, setIndustryOpen] = useState<boolean>(false);
|
|
// const [categoryFkIdIds, setCategoryFkIdIds] = useState([]);
|
|
// 动态设置每页数量
|
|
const [currentPageSize, setCurrentPageSize] = useState<number>(10);
|
|
const [form] = ProForm.useForm(); // form 对象
|
|
/**新增 设置行业分类 删除 */
|
|
// 新增
|
|
const handleCreateModal = () => {
|
|
setCreateModalOpen(!createModalOpen);
|
|
};
|
|
// 编辑
|
|
const handleUpdateModal = () => {
|
|
setUpdateModalOpen(!updateModalOpen);
|
|
};
|
|
// 设置行业分类
|
|
const handleSetIndustry = () => {
|
|
setIndustryOpen(!industryOpen);
|
|
};
|
|
|
|
// 模型信息
|
|
async function loadDetail(record) {
|
|
const resp = await apiModelInfo({ id: record?.id });
|
|
if (isSuccessApi(resp) && resp?.data) {
|
|
setCurrentRow({ ...resp?.data, id: record?.id });
|
|
}
|
|
}
|
|
|
|
function reloadList() {
|
|
actionRef.current?.reload();
|
|
}
|
|
// const [showDetail, setShowDetail] = useState<boolean>(false);
|
|
const columns: ProColumns<Record<string, any>>[] = [
|
|
{
|
|
title: <FormattedMessage id="model_index.table.list.name" defaultMessage="$$$" />,
|
|
dataIndex: 'name',
|
|
hideInSearch: true,
|
|
key: 'fixedName',
|
|
fixed: 'left',
|
|
},
|
|
{
|
|
title: <FormattedMessage id="model_index.table.list.type" defaultMessage="$$$" />,
|
|
dataIndex: 'model_type',
|
|
hideInSearch: true,
|
|
render: (dom, record) => {
|
|
let activeName = 'active_primary';
|
|
switch (record.model_type) {
|
|
case '机器学习':
|
|
activeName = 'active3';
|
|
break;
|
|
default:
|
|
activeName = 'active_primary';
|
|
break;
|
|
}
|
|
return (
|
|
<div className={`gn_list_type_tag flex items-center justify-center ${activeName}`}>
|
|
<span className="dot"></span>
|
|
<span>{dom}</span>
|
|
</div>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
title: <FormattedMessage id="model_index.table.list.industry" defaultMessage="$$$" />,
|
|
dataIndex: 'classification_name',
|
|
hideInSearch: true,
|
|
},
|
|
{
|
|
title: (
|
|
<FormattedMessage id="model_index.table.list.defaultVersionFkId" defaultMessage="$$$" />
|
|
),
|
|
dataIndex: 'default_version',
|
|
hideInSearch: true,
|
|
render: (dom, record) => (
|
|
<div>
|
|
{record?.default_version ? <span>V</span> : <></>}
|
|
<span>{dom}</span>
|
|
</div>
|
|
),
|
|
},
|
|
|
|
{
|
|
title: <FormattedMessage id="model_index.table.list.updateTime" defaultMessage="$$$" />,
|
|
dataIndex: 'update_time',
|
|
sorter: true,
|
|
hideInSearch: true,
|
|
valueType: 'dateTime',
|
|
render: (dom, record) => {
|
|
if (record.update_time === 'None') {
|
|
return '-';
|
|
}
|
|
return dom;
|
|
},
|
|
},
|
|
|
|
{
|
|
title: <FormattedMessage id="pages.searchTable.titleOption" defaultMessage="Operating" />,
|
|
dataIndex: 'option',
|
|
valueType: 'option',
|
|
fixed: 'right',
|
|
key: 'option',
|
|
render: (_, record) => [
|
|
<TableActionCard
|
|
key="TableActionCardRef"
|
|
renderActions={[
|
|
{
|
|
key: 'detail',
|
|
renderDom: (
|
|
<Button
|
|
key="detail"
|
|
type="link"
|
|
size="small"
|
|
onClick={() => {
|
|
// setCurrentRow(record);
|
|
history.push(`/home/model-detail/${record.id}`);
|
|
}}
|
|
>
|
|
<FormattedMessage id="model_index.table.list.detail" defaultMessage="详情配置" />
|
|
</Button>
|
|
),
|
|
},
|
|
{
|
|
key: 'update',
|
|
renderDom: (
|
|
<Button
|
|
key="update"
|
|
type="link"
|
|
size="small"
|
|
onClick={() => {
|
|
loadDetail(record);
|
|
setUpdateModalOpen(true);
|
|
}}
|
|
>
|
|
<FormattedMessage id="pages.searchTable.update" defaultMessage="Update" />
|
|
</Button>
|
|
),
|
|
},
|
|
{
|
|
key: 'destroy',
|
|
renderDom: (
|
|
<IsDelete
|
|
deleteApi={() => {
|
|
console.log('删除成功');
|
|
apiModelDelete({ id: record.id }).then(() => {
|
|
message.success(
|
|
intl.formatMessage({
|
|
id: 'common.action.success',
|
|
defaultMessage: '$$$',
|
|
}),
|
|
);
|
|
reloadList();
|
|
});
|
|
}}
|
|
></IsDelete>
|
|
),
|
|
},
|
|
]}
|
|
></TableActionCard>,
|
|
],
|
|
},
|
|
];
|
|
|
|
// 筛选查询
|
|
useEffect(() => {
|
|
if (actionRef) {
|
|
reloadList();
|
|
}
|
|
}, [actionRef, querysData]);
|
|
|
|
return (
|
|
<div className="modelIndex_page home_container gn_table_card_wrap">
|
|
<ProCard
|
|
className="gn_card"
|
|
style={{ backgroundColor: 'white' }}
|
|
title={
|
|
<div className="gn_form gn_table_query_filter">
|
|
<ProForm
|
|
className="gn_search_from"
|
|
form={form}
|
|
layout="horizontal"
|
|
submitter={{
|
|
render: () => (
|
|
<div style={{ textAlign: 'center', marginLeft: 12 }}>
|
|
<CommButton
|
|
type="primary"
|
|
htmlType="submit"
|
|
prevIcon={<SearchIcon />}
|
|
buttonLabel={
|
|
<FormattedMessage id="pages.searchTable.search" defaultMessage="查询" />
|
|
}
|
|
></CommButton>
|
|
<CommButton
|
|
style={{ marginLeft: 12 }}
|
|
htmlType="button"
|
|
prevIcon={<ResetIcon />}
|
|
buttonLabel={
|
|
<FormattedMessage id="pages.searchTable.reset" defaultMessage="重置" />
|
|
}
|
|
onClick={() => {
|
|
form.resetFields(); // 点击重置按钮时重置表单数据
|
|
setQuerysData(() => {}); // 清空筛选项
|
|
}}
|
|
></CommButton>
|
|
</div>
|
|
),
|
|
}}
|
|
onFinish={async (values) => {
|
|
console.log(values, 'filter_finish_values');
|
|
setQuerysData(() => values);
|
|
return true;
|
|
}}
|
|
>
|
|
<ProFormText
|
|
label={
|
|
<FormattedMessage id="model_index.table.list.name" defaultMessage="模型名称" />
|
|
}
|
|
labelClassName="label_set_1"
|
|
fieldProps={{
|
|
style: {
|
|
width: 280,
|
|
},
|
|
prefix: <SearchOutlined style={{ color: 'rgba(0,0,0,.25)' }} />,
|
|
}}
|
|
name="name"
|
|
placeholder="请输入模型名称"
|
|
/>
|
|
</ProForm>
|
|
</div>
|
|
}
|
|
extra={
|
|
<Access accessible={access.canUpdate(history.location.pathname)} key={`model-index-add`}>
|
|
<Button
|
|
type="primary"
|
|
key="primary"
|
|
onClick={() => {
|
|
setCreateModalOpen(true);
|
|
}}
|
|
>
|
|
<FormattedMessage id="model_index.table.list.add" defaultMessage="New" />
|
|
</Button>
|
|
<Button
|
|
className="ml-[12px]"
|
|
key="setIndustry"
|
|
onClick={() => {
|
|
setIndustryOpen(true);
|
|
}}
|
|
>
|
|
<FormattedMessage id="model_index.table.list.setIndustry" defaultMessage="行业类别" />
|
|
</Button>
|
|
</Access>
|
|
}
|
|
>
|
|
<div className="gn_scroll_list_wrap" style={{ maxHeight: 'calc(100vh - 292px)' }}>
|
|
<ProTable
|
|
{...proTableDefaultOptions}
|
|
className="gn_pro_table"
|
|
cardProps={{
|
|
bodyStyle: {
|
|
padding: '0',
|
|
},
|
|
}}
|
|
search={false}
|
|
scroll={{ x: proTableCommonOptions.commscrollX }}
|
|
options={{ fullScreen: false, setting: false, density: false, reload: false }}
|
|
actionRef={actionRef}
|
|
rowKey="id"
|
|
onDataSourceChange={(data) => {
|
|
console.log(data, 'onDataSourceChange_data');
|
|
// let CategoryFkIdIds: any = data.map((v) => {
|
|
// return v.categoryFkId;
|
|
// });
|
|
// setCategoryFkIdIds(CategoryFkIdIds);
|
|
}}
|
|
pagination={{
|
|
...proTablePaginationOptions,
|
|
pageSize: currentPageSize,
|
|
onChange: (pageNo, pageSize) => setCurrentPageSize(pageSize),
|
|
}}
|
|
columnsState={{
|
|
persistenceKey: 'algorithm_model_list',
|
|
persistenceType: 'localStorage',
|
|
}}
|
|
request={async (params = {}, sort) => {
|
|
const { current, ...rest } = params;
|
|
const reqParams = {
|
|
pageNo: current,
|
|
desc: false,
|
|
orderKey: '',
|
|
...rest,
|
|
};
|
|
if (sort && Object.keys(sort).length) {
|
|
reqParams.orderKey = Object.keys(sort)[0];
|
|
let sort_select = sort[reqParams.orderKey];
|
|
reqParams.desc = sort_select === 'descend';
|
|
}
|
|
let resp = await apiModelList({ ...reqParams, ...querysData });
|
|
if (!isSuccessApi(resp)) {
|
|
return { data: [], success: true };
|
|
}
|
|
return {
|
|
data: resp.data.data,
|
|
success: resp.success,
|
|
total: resp.data.count,
|
|
current: current,
|
|
pageSize: currentPageSize,
|
|
};
|
|
}}
|
|
columns={columns}
|
|
/>
|
|
</div>
|
|
</ProCard>
|
|
<CreateForm
|
|
createModalOpen={createModalOpen}
|
|
handleModal={handleCreateModal}
|
|
reload={reloadList}
|
|
/>
|
|
<UpdateForm
|
|
updateModalOpen={updateModalOpen}
|
|
handleModal={handleUpdateModal}
|
|
values={currentRow}
|
|
reload={reloadList}
|
|
/>
|
|
<CategorizeUpdate
|
|
visible={industryOpen}
|
|
handleModal={handleSetIndustry}
|
|
values={{ industry: [{ name: '', value: '' }] }}
|
|
apiRequest={async () => {
|
|
let resp = await apiModelClassificationList();
|
|
return {
|
|
data: resp.data,
|
|
};
|
|
}}
|
|
beforeCloseRequest={async (params, successRes) => {
|
|
let resp = await apiModelClassificationDelete({ id: params.id });
|
|
if (isSuccessApi(resp)) {
|
|
successRes(resp);
|
|
}
|
|
}}
|
|
beforeAddRequest={async (params, successRes) => {
|
|
let resp = await apiModelClassificationAdd({ name: params });
|
|
if (isSuccessApi(resp)) {
|
|
successRes(resp);
|
|
}
|
|
}}
|
|
beforeEditRequest={async (params, successRes) => {
|
|
let resp = await apiModelClassificationEdit({
|
|
id: params.id,
|
|
name: params.editInputValue,
|
|
});
|
|
if (isSuccessApi(resp)) {
|
|
successRes(resp);
|
|
}
|
|
}}
|
|
modalFormProps={{
|
|
categorizeFormProps: {
|
|
label: (
|
|
<FormattedMessage id="model_index.create.form.industry" defaultMessage="行业类别" />
|
|
),
|
|
name: 'industry',
|
|
},
|
|
categorizeModelProps: {
|
|
title: intl.formatMessage({
|
|
id: 'model_index.table.list.setIndustry',
|
|
defaultMessage: '新建',
|
|
}),
|
|
},
|
|
}}
|
|
/>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default ModelIndex;
|