feat: 模型管理初步联调完成

develop2
donghao 11 months ago
parent cff535675c
commit c427830ef6

@ -189,7 +189,7 @@
.anticon.anticon-down.ant-dropdown-trigger.ant-transfer-list-header-dropdown {
display: none;
}
:where(.css-dev-only-do-not-override-1y19ift).ant-pro-steps-form-container {
.ant-pro-steps-form-container {
min-width: 100%;
}
.ant-transfer {

@ -220,7 +220,7 @@
.anticon.anticon-down.ant-dropdown-trigger.ant-transfer-list-header-dropdown {
display: none;
}
:where(.css-dev-only-do-not-override-1y19ift).ant-pro-steps-form-container {
.ant-pro-steps-form-container {
min-width: 100%;
}

@ -187,7 +187,7 @@ const BaseTree: React.FC<BaseTreeProps> = (props) => {
useEffect(() => {
setCurrTreeData(props.treeData);
// TODO 后续改从业务层获取 默认选项
// 从业务层获取 默认选项
setCurrSeleted([props?.treeData[0]?.id]);
console.log(props.treeData, 'props_treeData');
}, [props.treeData]);

@ -0,0 +1,11 @@
/*
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-06-04 15:13:34
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-06-04 15:25:13
* @FilePath: \general-ai-platform-web\src\components\UploadFile\index.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import proFormUploadDraggerToken from './src/formUploadDraggerToken';
export const FormUploadDraggerToken = proFormUploadDraggerToken;

@ -0,0 +1,127 @@
/*
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-06-04 15:14:27
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-06-05 15:37:03
* @FilePath: \general-ai-platform-web\src\components\UploadFile\src\FormUploadDraggerToken.tsx
* @Description:
* // TODO 需要支持多文件上传
*/
import { apiFileDelete, apiFileUpload } from '@/services/business/file';
import { useIntl } from '@umijs/max';
import { RcFile, UploadChangeParam, UploadFile, message } from 'antd';
// import localCacha from '@/utils/localCacha';
import { isSuccessApi } from '@/utils/forApi';
import { ProFormUploadDragger } from '@ant-design/pro-components';
import React, { useState } from 'react';
import { FormUploadDraggerTokenProps } from '../typing';
// import { ProFormUploadDragger, type ProFormUploadDraggerProps } from '@ant-design/pro-components';
// import type { RcFile, UploadChangeParam, UploadFile } from 'antd/es/upload';
const FormUploadDraggerToken: React.FC<FormUploadDraggerTokenProps> = (props) => {
const intl = useIntl();
const { onChange } = props;
const [fileList, setFileList] = useState([
{ status: 'done', url: '/file/' + props.fileValues?.id, ...props.fileValues },
]);
/**
*
*/
const onChangeFile = (info: UploadChangeParam<UploadFile<R<string>>>) => {
// 当上传成功后才开始对数据进行校验
if (info.file.status === 'done') {
const res = info.file.response;
if (res?.code !== 200) {
info.file.status = 'error';
// 查看 antd 源码,可自定义错误信息 官方文档并未给出相关内容 message = file.error?.statusText || file.error?.message || locale.uploadError;
info.file.error = { statusText: res?.msg };
}
}
onChange?.(info);
};
/**
*
*/
const beforeUploadFile = async (file: RcFile) => {
const formData = new FormData();
formData.append('file', file);
const resp = await apiFileUpload(formData);
if (isSuccessApi(resp)) {
setFileList([
{
uid: resp?.data?.result,
name: file?.name,
status: 'done',
url: '/file/' + resp?.data?.result,
},
]);
props.afterUploadFile({ resp, file, fileList });
}
console.log(resp, 'apiFileUpload_resp');
return false; // 阻止自动上传
// if (!accept) return true;
// const suffix = file.name.substring(file.name.lastIndexOf('.'));
// const supportFile = accept.replace(/\s*/g, '').split(','); // 去除 accept 中的空格
// if (supportFile.length > 0) {
// const validate = supportFile.includes(suffix);
// if (!validate) {
// message.error(`支持上传的文件格式:${accept}`);
// return Upload.LIST_IGNORE;
// }
// return true;
// }
};
/**
*/
const onRemoveFile = async (file: UploadFile<R<string>>) => {
console.log(file, 'onRemoveFile_file');
const resp = await apiFileDelete({ file_md5: file?.uid });
console.log(resp, 'apiFileDelete_resp');
props.afterRemoveFile(resp, file);
if (isSuccessApi(resp)) {
message.success(`${file.name} 删除成功`);
} else {
message.error(
resp?.meta?.message ||
intl.formatMessage({ id: 'common.action.failure', defaultMessage: '$$$' }),
);
}
// props.beforeRemoveFile(file);
// rc- 是通过 antd 初次上传的自带uid没有 rc-证明是回显值值是文件id或图片url地址
// 若上传失败,删除时,直接清除页面文件,不走接口
// if (file.uid.indexOf('rc-') !== -1 && file.response?.code !== 200) return true;
// let fileId = '';
// // response 存在,则证明该文件是未提交的数据(上传,然后删除)
// if (file.response?.data) fileId = file.response.data;
// else fileId = file.uid;
// const { code } = await apiFileDelete({ file_md5: fileId });
// requestDelFile?.(code === 200);
// return code === 200;
};
// TODO 组装初始值
return (
<>
<ProFormUploadDragger
fileList={fileList}
onChange={onChangeFile}
beforeUpload={() => false} // 阻止自动上
{...props.proFieldProps}
fieldProps={{
className: 'gn_proFormUploadDragger_formItem',
name: 'files', // 这里可以指定和后端对接的 filename
onRemove: onRemoveFile,
beforeUpload: beforeUploadFile,
}}
/>
<div style={{ color: '#666666', marginTop: '-8px' }}>{props.nextText}</div>
</>
);
};
export default FormUploadDraggerToken;

@ -0,0 +1,15 @@
/*
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-26 11:09:49
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-06-05 14:50:40
* @FilePath: \general-ai-platform-web\src\components\UploadFile\typing.ts
* @Description:
*/
export interface FormUploadDraggerTokenProps extends ProFormUploadDraggerProps {
afterUploadFile?: (data: any) => void; // 上传完成后
afterRemoveFile?: (file: UploadFile<R<string>>) => void; // 删除开始
requestDelFile?: (status: boolean) => void;
nextText?: string | React.ReactNode;
}

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-10 17:21:34
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-31 13:40:48
* @LastEditTime: 2024-06-06 15:07:50
* @FilePath: \general-ai-manage\src\locales\zh-CN\model.ts
* @Description:
*/
@ -41,7 +41,9 @@ export const model_runtimeLib: { [key: string]: string } = {
'model_runtimeLib.table.list.createTime': '创建时间',
'model_runtimeLib.table.list.updateTime': '更新时间',
'model_runtimeLib.table.list.name': '运行库名称',
'model_runtimeLib.list.table.createForm.add': '新建运行库',
'model_runtimeLib.table.list.path': '文件地址',
'model_runtimeLib.list.table.form.action.add': '新建运行库',
'model_runtimeLib.list.table.form.action.edit': '编辑运行库',
'model_runtimeLib.list.table.form.name': '运行库名称',
'model_runtimeLib.list.table.form.rule.required.name': '请填写运行库名称',
'model_runtimeLib.list.table.form.IP': 'IP地址',

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-22 15:23:36
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-20 11:00:25
* @LastEditTime: 2024-06-06 15:46:51
* @FilePath: \general-ai-platform-web\src\pages\Node\BusinessModel\index.tsx
* @Description:
* @
@ -18,7 +18,9 @@
import TableActionCard from '@/components/TableActionCard';
import IsDelete from '@/components/TableActionCard/isDelete';
import { getBusinessModelList } from '@/services/testApi/businessModel';
import { apiModelDeploymentList } from '@/services/business/model';
import { isSuccessApi } from '@/utils/forApi';
import { ExclamationCircleFilled } from '@ant-design/icons';
import type { ActionType, ProColumns } from '@ant-design/pro-components';
import { ProCard, ProTable } from '@ant-design/pro-components';
@ -63,7 +65,7 @@ const BusinessModel: React.FC = () => {
const columns: ProColumns<Record<string, any>>[] = [
{
title: <FormattedMessage id="business_model.table.list.name" defaultMessage="名称" />,
dataIndex: 'name',
dataIndex: 'model_name',
hideInSearch: true,
key: 'fixedName',
fixed: 'left',
@ -74,7 +76,7 @@ const BusinessModel: React.FC = () => {
title: (
<FormattedMessage id="business_model.table.list.createTime" defaultMessage="创建时间" />
),
dataIndex: 'createTime',
dataIndex: 'create_time',
hideInSearch: true,
valueType: 'dateTime',
},
@ -185,7 +187,10 @@ const BusinessModel: React.FC = () => {
pageNo: current,
...rest,
};
let resp = await getBusinessModelList({ ...reqParams });
let resp = await apiModelDeploymentList({ ...reqParams });
if (!isSuccessApi(resp)) {
return { data: [], success: true };
}
console.log(resp, 'getModelVersionList_resp');
return {
data: resp.data?.data,

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-22 15:23:36
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-30 15:25:27
* @LastEditTime: 2024-06-04 16:33:16
* @FilePath: \general-ai-platform-web\src\pages\Business\DeviceGroup\components\deviceList.tsx
* @Description: deviceGroupdg
* @

@ -1,4 +1,6 @@
import { apiFileDelete, apiFileUpload } from '@/services/business/file';
import { FormUploadDraggerToken } from '@/components/UploadFile';
import { apiModelVersionAdd } from '@/services/business/model';
import { isSuccessApi } from '@/utils/forApi';
import {
ProForm,
ProFormInstance,
@ -54,16 +56,14 @@ const CreateForm: React.FC<CreateFormProps> = (props) => {
const [configFileList, setConfigFileList] = useState<UploadFile<any>[]>([]);
// const [form] = Form.useForm<Record<string, any>>();
const [currFormData, setCurrFormData] = useState<Record<string, any>>({});
const [current, setCurrent] = useState(0);
const formBaseRef = useRef<ProFormInstance>();
const formProjectFileRef = useRef<ProFormInstance>();
// const [filePath, setFilePath] = useState('');
const handleFileChange = ({ file }: { file: UploadFile }) => {
const handleConfigFileChange = ({ file }: { file: UploadFile }) => {
console.log(configFileList, 'handleFileChange_configFileList');
let curFile: any;
switch (file.status) {
case 'uploading':
case 'done':
@ -74,29 +74,44 @@ const CreateForm: React.FC<CreateFormProps> = (props) => {
curFile = [];
break;
}
setConfigFileList([...curFile]);
};
// test 测试数据
useEffect(() => {
// if (formBaseRef) {
formBaseRef.current?.setFieldsValue({
version: '0.0.91', // 设备分类的suid
comment:
'测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注',
});
// }
// 初始化赋值
// setCurrFormData({
// version: '1.0.91', // 设备分类的suid 59aa3d0c3162322e190942a9cc9add10
// comment:
// '测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注测试一下备注',
// });
}, [props.createModalOpen]);
return (
<StepsForm<{
name: string;
}>
onFinish={async (values) => {
console.log('All form values:', values, { model_id: props.modelInfo?.model_id });
console.log('All form values:', values, {});
// 在这里处理提交数据例如调用API
message.success('提交成功');
let resp = await apiModelVersionAdd({
...values,
model_id: props.modelInfo?.model_id,
config_str: JSON.stringify(values.config_str_arr),
model_file: currFormData?.model_file,
config_file: '',
});
if (isSuccessApi(resp)) {
message.success(
intl.formatMessage({ id: 'common.action.success', defaultMessage: '$$$' }),
);
props.reload();
props.handleModal();
} else {
message.error(
resp?.meta?.message ||
intl.formatMessage({ id: 'common.action.failure', defaultMessage: '$$$' }),
);
}
return true;
}}
stepsProps={proFormStepsFormProps.stepsProps}
current={current}
@ -165,17 +180,6 @@ const CreateForm: React.FC<CreateFormProps> = (props) => {
initialValue={props.modelInfo?.name}
debounceTime={1000}
disabled={true}
// request={async (keyWord) => {
// const resp = await postAlgorithmModelGetAlgorithmModelFkSelect({
// keyword: keyWord?.keyWords || '',
// });
// return resp.data.list.map((v: any) => {
// return {
// label: v.name,
// value: v.id,
// };
// });
// }}
/>
<ProFormText
width={proFormSmallItemStyleProps.width}
@ -183,6 +187,7 @@ const CreateForm: React.FC<CreateFormProps> = (props) => {
prefix: <span>V</span>,
}}
name="version"
initialValue={currFormData?.version}
label={<FormattedMessage id="model_detail.version.form.name" defaultMessage="版本号" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
@ -207,6 +212,7 @@ const CreateForm: React.FC<CreateFormProps> = (props) => {
<ProFormTextArea
width={proFormSmallItemStyleProps.width}
name="comment"
initialValue={currFormData?.comment}
label={<FormattedMessage id="model_detail.version.form.remark" defaultMessage="备注" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
@ -224,7 +230,6 @@ const CreateForm: React.FC<CreateFormProps> = (props) => {
<StepsForm.StepForm<{
project_file: string;
}>
formRef={formProjectFileRef}
className="gn_form"
name="project_file"
title={
@ -251,78 +256,32 @@ const CreateForm: React.FC<CreateFormProps> = (props) => {
return true;
}}
>
<ProFormUploadDragger
label={<span className="font-bold"></span>}
title={
<FormUploadDraggerToken
proFieldProps={{
label: <span className="font-bold"></span>,
title: (
<div className="gn_uploadfile_title py-[16px] text1 text-center">
<span></span>
<a></a>
</div>
}
description=""
icon={<i className="iconfont icon-shangchuanwenjian text_primary text-[32px]"></i>}
name="model_file_name"
// action={fileApiActionUrl}
onRemove={async (file) => {
// 这里可以添加删除文件的接口调用逻辑
// await deleteFileFromServer(file);
// setFileList((prevList) => {
// const newList = prevList.filter((item) => item.uid !== file.uid);
// return newList;
// });
const currFileId = formProjectFileRef?.current?.getFieldValue('model_file');
const resp = await apiFileDelete({ file_md5: currFileId });
console.log(resp, 'apiFileDelete_resp', file);
message.success('文件已删除');
return true; // 确保文件从文件列表中移除
),
description: '',
icon: <i className="iconfont icon-shangchuanwenjian text_primary text-[32px]"></i>,
name: 'model_file_arr',
max: 1,
}}
onChange={async ({ file, fileList }) => {
// 检查文件状态
console.log(
file,
fileList,
'onChange_ProjectFile',
formProjectFileRef?.current?.getFieldValue('model_file'),
);
if (file.status === 'removed') {
// 删除文件
// setProjectFileList(fileList.filter((item) => item.uid !== file.uid));
// const currFileId = formProjectFileRef?.current?.getFieldValue('model_file')
// const resp = await apiFileDelete({file_md5: currFileId})
// console.log(resp,'apiFileDelete_resp')
// message.success(`${file.name} 删除成功`);
} else {
// 处理上传
// formProjectFileRef?.current?.setFieldValue('model_file_name', [file]);
// handleUpload(file);
}
// setProjectFileList(fileList);
afterUploadFile={({ resp }) => {
setCurrFormData((data) => {
return { ...data, model_file: resp?.data?.result };
});
}}
max={1}
fieldProps={{
className: 'gn_proFormUploadDragger_formItem',
name: 'file',
// beforeUpload: beforeUploadFile,
data: { path: `models/${Date.now()}` },
headers: {
// 'X-CSRFToken': cookie.load('csrftoken'),
// Authorization: `Bearer ${localStorage.getItem('access') || ''}`,
},
beforeUpload: async (file) => {
const formData = new FormData();
formData.append('file', file);
const resp = await apiFileUpload(formData);
formProjectFileRef?.current?.setFieldValue('model_file', resp?.data?.result);
console.log(resp, 'apiFileUpload_resp');
// form.setFieldValue('logo', base64);
return false; // 阻止自动上传
},
afterRemoveFile={() => {
setCurrFormData((data) => {
return { ...data, model_file: '' };
});
}}
nextText="请上传格式为zip.tar.gz的模型文件"
/>
<div style={{ color: '#666666', marginTop: '-8px' }}>zip.tar.gz</div>
</StepsForm.StepForm>
{/* 参数配置 */}
<StepsForm.StepForm<{
@ -347,22 +306,6 @@ const CreateForm: React.FC<CreateFormProps> = (props) => {
let formData1 = formBaseRef.current?.getFieldsValue();
if (formData1?.model_name) {
await waitTime(500);
// formData1.modelConfig = { params: values?.params || [] };
// if (filePath) {
// formData1.path = filePath;
// }
// postModelVersionCreateModelVersion(formData)
// .then(() => {
// message.success(
// intl.formatMessage({ id: 'common.action.success', defaultMessage: '$$$' }),
// );
// props.handleModal();
// props.reload();
// })
// .catch(() => {
// message.error(intl.formatMessage({ id: 'common.action.failure', defaultMessage: '$$$' }));
// return false;
// });
}
return true;
}}
@ -379,11 +322,11 @@ const CreateForm: React.FC<CreateFormProps> = (props) => {
}
description=""
icon={<i className="iconfont icon-shangchuanwenjian text_primary text-[32px]"></i>}
name="config_file"
name="config_file_name"
action={fileApiActionUrl}
fieldProps={{
className: 'gn_proFormUploadDragger_formItem',
onChange: handleFileChange,
onChange: handleConfigFileChange,
onRemove: () => {
let index_ids = actionFormListRef.current?.getList()?.map((v, i) => {
return i;
@ -429,7 +372,7 @@ const CreateForm: React.FC<CreateFormProps> = (props) => {
}}
/>
<div style={{ color: '#666666', marginTop: '-8px', marginBottom: '16px' }}>
zip.tar.gz
.json.yaml.yml
</div>
{/* // TODO label字重与上面统一, 操作按钮需要与输入框对齐 */}

@ -0,0 +1,447 @@
// TODO 上传文件限制为1时还可以上传
import { FormUploadDraggerToken } from '@/components/UploadFile';
import { apiModelVersionEdit } from '@/services/business/model';
import { isSuccessApi } from '@/utils/forApi';
import {
ProForm,
ProFormInstance,
ProFormList,
ProFormText,
ProFormTextArea,
ProFormUploadDragger,
StepsForm,
} from '@ant-design/pro-components';
import { FormListActionType } from '@ant-design/pro-form/lib';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Modal, UploadFile, message } from 'antd';
import yaml from 'js-yaml';
import React, { useEffect, useRef, useState } from 'react';
import {
proFormItemStyleProps,
proFormSmallItemStyleProps,
proFormSmallModelWidth,
proFormStepsFormProps,
} from '../../../../../config/defaultForm';
// import {beforeUploadFile} from "@/utils/common";
// @ts-ignore
import { isValidJson } from '@/utils/is';
import { fileApiActionUrl } from '../../../../../config/defaultApi';
export type UpdateFormProps = {
updateModalOpen: boolean;
values: Record<string, any>;
handleModal: () => void;
modelInfo: Record<string, any>;
reload: any;
};
const waitTime = (time: number = 100) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(true);
}, time);
});
};
// interface ProjectConfig {
// params: Array<object>;
// }
const UpdateForm: React.FC<UpdateFormProps> = (props) => {
const actionFormListRef = useRef<
FormListActionType<{
name: string;
}>
>();
const intl = useIntl();
const [dataFormList] = useState<any>([]);
const dataFormListRef = useRef(dataFormList);
// const [projectFileList, setProjectFileList] = useState<UploadFile<any>[]>([]);
const [configFileList, setConfigFileList] = useState<UploadFile<any>[]>([]);
// const [form] = Form.useForm<Record<string, any>>();
const [currFormData, setCurrFormData] = useState<Record<string, any>>({});
const [current, setCurrent] = useState(0);
const formBaseRef = useRef<ProFormInstance>();
const formProjectFileRef = useRef<ProFormInstance>();
// const [filePath, setFilePath] = useState('');
const handleConfigFileChange = ({ file }: { file: UploadFile }) => {
console.log(configFileList, 'handleFileChange_configFileList');
let curFile: any;
switch (file.status) {
case 'uploading':
case 'done':
curFile = [file];
break;
case 'removed':
default:
curFile = [];
break;
}
setConfigFileList([...curFile]);
};
function resetForm() {
setCurrFormData({});
}
// test 测试数据
useEffect(() => {
// 初始化赋值
if (props.updateModalOpen && props.values?.version_id) {
setCurrFormData({
...props.values,
model_file: props.values?.model_file_md5,
});
console.log(props.values, 'useEffect_values', currFormData);
} else {
resetForm();
}
}, [props.updateModalOpen, props.values]);
// useEffect(() => {
// if (formProjectFileRef) {
// formProjectFileRef.current?.setFieldValue('model_file_arr', [
// ]);
// }
// }, [props.updateModalOpen, props.values, formProjectFileRef]);
return (
<StepsForm<{
name: string;
}>
onFinish={async (values) => {
console.log('All form values:', values, {});
// 在这里处理提交数据例如调用API
let resp = await apiModelVersionEdit({
...values,
model_id: props.modelInfo?.model_id,
config_str: JSON.stringify(values.config_str_arr),
model_file: currFormData?.model_file,
version_id: currFormData?.version_id,
config_file: '',
});
if (isSuccessApi(resp)) {
message.success(
intl.formatMessage({ id: 'common.action.success', defaultMessage: '$$$' }),
);
props.reload();
props.handleModal();
} else {
message.error(
resp?.meta?.message ||
intl.formatMessage({ id: 'common.action.failure', defaultMessage: '$$$' }),
);
}
props.handleModal();
return true;
message.success('提交成功');
}}
stepsProps={proFormStepsFormProps.stepsProps}
current={current}
onCurrentChange={setCurrent}
formProps={{
validateMessages: {
required: '此项为必填项',
},
}}
stepsFormRender={(dom, submitter) => {
return (
<Modal
className="gn_model_steps_form"
title={
<FormattedMessage id="model_detail.version.table.list.add" defaultMessage="新增" />
}
width={proFormSmallModelWidth}
onCancel={() => {
setCurrent(0);
formBaseRef.current?.resetFields();
// setProjectFileList([]);
props.handleModal();
}}
open={props.updateModalOpen}
footer={submitter}
destroyOnClose
>
{dom}
</Modal>
);
}}
>
{/* 版本信息 */}
<StepsForm.StepForm<{
name: string;
}>
className="gn_form"
name="base"
formRef={formBaseRef}
title={
<FormattedMessage id="model_detail.version.stepForm.base" defaultMessage="版本信息" />
}
stepProps={{
description: (
<FormattedMessage
id="model_detail.version.stepForm.base.description"
defaultMessage="填写版本基础信息"
/>
),
}}
onFinish={async () => {
// setFormData(formBaseRef.current?.getFieldsValue());
await waitTime(500);
return true;
}}
>
<ProForm.Group>
{/* 默认填充模型 无需选择 */}
<ProFormText
width={proFormSmallItemStyleProps.width}
name="model_name"
label={
<FormattedMessage id="model_detail.version.form.modelFkId" defaultMessage="$$$" />
}
required={true}
initialValue={props.modelInfo?.name}
debounceTime={1000}
disabled={true}
/>
<ProFormText
width={proFormSmallItemStyleProps.width}
fieldProps={{
prefix: <span>V</span>,
}}
name="version"
initialValue={currFormData?.version}
label={<FormattedMessage id="model_detail.version.form.name" defaultMessage="版本号" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'model_detail.version.form.name',
defaultMessage: '$$$',
})}`}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="model_detail.version.form.required.name"
defaultMessage="name is required"
/>
),
},
]}
/>
<ProFormTextArea
width={proFormSmallItemStyleProps.width}
name="comment"
initialValue={currFormData?.comment}
label={<FormattedMessage id="model_detail.version.form.remark" defaultMessage="备注" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'model_detail.version.form.remark',
defaultMessage: '$$$',
})}`}
required={false}
disabled={false}
/>
</ProForm.Group>
</StepsForm.StepForm>
{/* 版本上传 */}
<StepsForm.StepForm<{
project_file: string;
}>
className="gn_form"
name="project_file"
formRef={formProjectFileRef}
title={
<FormattedMessage
id="model_detail.version.stepForm.project_file"
defaultMessage="版本上传"
/>
}
style={{ width: proFormItemStyleProps.width }}
stepProps={{
description: (
<FormattedMessage
id="model_detail.version.stepForm.project_file.description"
defaultMessage="上传模型文件"
/>
),
}}
onFinish={async (values: any) => {
console.log(values, 'values');
// if ('projectFilePath' in values && values['projectFilePath'].length > 0) {
// let projectFilePath = values['projectFilePath'][0]?.response?.data?.path || '';
// setFilePath(projectFilePath);
// }
return true;
}}
>
<FormUploadDraggerToken
proFieldProps={{
label: <span className="font-bold"></span>,
title: (
<div className="gn_uploadfile_title py-[16px] text1 text-center">
<span></span>
<a></a>
</div>
),
description: '',
icon: <i className="iconfont icon-shangchuanwenjian text_primary text-[32px]"></i>,
name: 'model_file_arr',
max: 1,
initialValue: currFormData?.model_file_md5
? [
{
uid: currFormData?.model_file_md5,
name: currFormData?.model_file_name || currFormData?.model_file_md5,
status: 'done',
url: '/file/' + currFormData?.model_file_md5,
},
]
: [],
}}
afterUploadFile={({ resp, file }) => {
console.log(resp, file, 'afterRemoveFile');
setCurrFormData((data) => {
return { ...data, model_file: resp?.data?.result };
});
}}
afterRemoveFile={() => {
setCurrFormData((data) => {
return { ...data, model_file: '' };
});
}}
nextText="请上传格式为zip.tar.gz的模型文件"
/>
</StepsForm.StepForm>
{/* 参数配置 */}
<StepsForm.StepForm<{
config: string;
}>
className="gn_form"
name="config"
title={
<FormattedMessage id="model_detail.version.stepForm.config" defaultMessage="参数配置" />
}
stepProps={{
description: (
<FormattedMessage
id="model_detail.version.stepForm.config.description"
defaultMessage="参数配置"
/>
),
}}
onFinish={async (values: any) => {
// setConfigFileList([]);
console.log(values, 'config_values');
let formData1 = formBaseRef.current?.getFieldsValue();
if (formData1?.model_name) {
await waitTime(500);
}
return true;
}}
>
<ProFormUploadDragger
width={proFormSmallItemStyleProps.width}
max={1}
label={<span className="font-bold"></span>}
title={
<div className="gn_uploadfile_title py-[16px] text1 text-center">
<span></span>
<a></a>
</div>
}
description=""
icon={<i className="iconfont icon-shangchuanwenjian text_primary text-[32px]"></i>}
name="config_file_name"
action={fileApiActionUrl}
fieldProps={{
className: 'gn_proFormUploadDragger_formItem',
onChange: handleConfigFileChange,
onRemove: () => {
let index_ids = actionFormListRef.current?.getList()?.map((v, i) => {
return i;
});
actionFormListRef.current?.remove(index_ids || []);
},
beforeUpload: (file) => {
if (
!file.name.endsWith('.yaml') &&
!file.name.endsWith('.yml') &&
!file.name.endsWith('.json')
) {
message.error('请上传yaml或json文件').then(() => {});
return false;
} else {
let parsedData = {};
file
.text()
.then((text) => {
if (file.name.endsWith('.yaml') || file.name.endsWith('.yml')) {
parsedData = yaml.load(text) as Record<string, unknown>;
}
if (file.name.endsWith('.json')) {
parsedData = JSON.parse(text) as Record<string, unknown>;
}
if (Object.keys(parsedData).length > 0) {
dataFormListRef.current = Object.entries(parsedData).map(([key, value]) => ({
name: key,
default: value,
}));
dataFormListRef.current.forEach((v: any, i: number) => {
actionFormListRef.current?.add(v, i);
});
}
return true;
})
.catch(() => {
return false;
});
}
},
}}
/>
<div style={{ color: '#666666', marginTop: '-8px', marginBottom: '16px' }}>
.json.yaml.yml
</div>
{/* // TODO label字重与上面统一, 操作按钮需要与输入框对齐 */}
<ProFormList
name="config_str_arr"
label={
<div>
<span className="font-bold"></span>
<div style={{ color: '#333333', padding: '8px 0 4px' }}>
~
</div>
</div>
}
initialValue={
isValidJson(props.values?.config_str) ? JSON.parse(props.values?.config_str) : []
}
actionRef={actionFormListRef}
itemContainerRender={(doms) => {
return <ProForm.Group>{doms}</ProForm.Group>;
}}
alwaysShowItemLabel
>
{() => {
return (
<>
<ProFormText width={268} key="name" name="name" label="键名" />
<ProFormText width={268} key="default" name="default" label="默认值" />
</>
);
}}
</ProFormList>
</StepsForm.StepForm>
</StepsForm>
);
};
export default UpdateForm;

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-08 10:36:06
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-31 14:38:28
* @LastEditTime: 2024-06-05 10:34:16
* @FilePath: \general-ai-manage\src\pages\Model\ModelDetail\index.tsx
* @Description:
* @
@ -14,34 +14,37 @@ import InnerPageBack from '@/components/Back/innerPageBack';
import { CommButton } from '@/components/Button';
import TableActionCard from '@/components/TableActionCard';
import IsDelete from '@/components/TableActionCard/isDelete';
import { apiModelInfo, apiModelVersionList } from '@/services/business/model';
import {
apiModelInfo,
apiModelVersionDelete,
apiModelVersionInfo,
apiModelVersionList,
apiModelVersionSetdefault,
} from '@/services/business/model';
import { isSuccessApi } from '@/utils/forApi';
import type { ActionType, ProColumns } from '@ant-design/pro-components';
import { ProCard, ProDescriptions, ProTable } from '@ant-design/pro-components';
import { FormattedMessage, useParams } from '@umijs/max';
import { Button } from 'antd';
import { FormattedMessage, useIntl, useParams } from '@umijs/max';
import { Button, message } from 'antd';
import { useRef, useState } from 'react';
import { proTablePaginationOptions } from '../../../../config/defaultTable';
import CreateForm from './components/createForm';
import UpdateForm from './components/updateForm';
const ModelDetail: React.FC = () => {
const routeParams = useParams(); // 路由参数读取
// const access = useAccess();
// const intl = useIntl();
const intl = useIntl();
const actionRef = useRef<ActionType>();
const [createModalOpen, setCreateModalOpen] = useState<boolean>(false);
// const [categoryFkIdIds, setCategoryFkIdIds] = useState([]);
// 动态设置每页数量
const [currentPageSize, setCurrentPageSize] = useState<number>(10);
// const [currentRow, setCurrentRow] = useState<Record<string, any>>({});
const [currentRow, setCurrentRow] = useState<Record<string, any>>({});
const [modelInfo, setModelInfo] = useState<Record<string, any>>({});
/**
* @en-US The pop-up window of the distribution update window
* @zh-CN
* */
// const [updateModalOpen, setUpdateModalOpen] = useState<boolean>(false);
const [updateModalOpen, setUpdateModalOpen] = useState<boolean>(false);
// const [showDetail, setShowDetail] = useState<boolean>(false);
/**新增 编辑 删除 */
@ -49,6 +52,19 @@ const ModelDetail: React.FC = () => {
const handleCreateModal = () => {
setCreateModalOpen(!createModalOpen);
};
// 编辑
const handleUpdateModal = () => {
setUpdateModalOpen(!updateModalOpen);
};
// 模型版本信息
async function loadDetail(record) {
const resp = await apiModelVersionInfo({ version_id: record?.version_id });
if (isSuccessApi(resp) && resp?.data) {
setCurrentRow({ ...resp?.data, version_id: record?.version_id });
setUpdateModalOpen(true);
}
}
function reloadList() {
actionRef.current?.reload();
@ -64,11 +80,12 @@ const ModelDetail: React.FC = () => {
title: <FormattedMessage id="model_index.table.list.name" defaultMessage="$$$" />,
dataIndex: 'name',
},
// TODO 缺失默认版本信息字段
{
title: (
<FormattedMessage id="model_index.table.list.defaultVersionFkId" defaultMessage="$$$" />
),
dataIndex: 'default_version',
dataIndex: 'version',
},
{
title: <FormattedMessage id="model_index.table.list.updateTime" defaultMessage="$$$" />,
@ -83,7 +100,7 @@ const ModelDetail: React.FC = () => {
const columns: ProColumns<Record<string, any>>[] = [
{
title: <FormattedMessage id="model_detail.version.table.list.name" defaultMessage="版本号" />,
dataIndex: 'name',
dataIndex: 'version',
hideInSearch: true,
key: 'fixedName',
fixed: 'left',
@ -91,9 +108,9 @@ const ModelDetail: React.FC = () => {
render: (dom, record) => (
<div>
<span>{dom}</span>
<span>V{dom}</span>
<span>
{record.isEnable && (
{record.is_default === 1 && (
<span
style={{
display: 'inline-block',
@ -142,7 +159,7 @@ const ModelDetail: React.FC = () => {
defaultMessage="更新时间"
/>
),
dataIndex: 'updateTime',
dataIndex: 'update_time',
hideInSearch: true,
valueType: 'dateTime',
},
@ -157,7 +174,6 @@ const ModelDetail: React.FC = () => {
<TableActionCard
key="TableActionCardRef"
renderActions={[
// TODO 设为默认交互补充
{
key: 'setDefault',
renderDom: record.isEnable ? (
@ -169,11 +185,25 @@ const ModelDetail: React.FC = () => {
key="setDefault"
type="link"
size="small"
onClick={() => {
// setCurrentRow(record);
// history.push('/home/model-detail');
// doToDetail(record);
// setShowDetail(true);
onClick={async () => {
const resp = await apiModelVersionSetdefault({
model_id: Number(routeParams.id),
version_id: record?.version_id,
});
if (isSuccessApi(resp)) {
message.success(
intl.formatMessage({ id: 'common.action.success', defaultMessage: '$$$' }),
);
reloadList();
} else {
message.error(
resp?.meta?.message ||
intl.formatMessage({
id: 'common.action.failure',
defaultMessage: '$$$',
}),
);
}
}}
>
<FormattedMessage id="pages.searchTable.setDefault" defaultMessage="设为默认" />
@ -181,22 +211,17 @@ const ModelDetail: React.FC = () => {
),
},
{
key: 'updateDetail',
key: 'update',
renderDom: (
<Button
key="updateDetail"
key="update"
type="link"
size="small"
onClick={() => {
// TODO 编辑在新增联调后实现
// setCurrentRow(record);
// history.push('/home/model-detail');
// doToDetail(record);
// setShowDetail(true);
// setUpdateModalOpen(true);
loadDetail(record);
}}
>
<FormattedMessage id="pages.searchTable.updateDetail" defaultMessage="查看" />
<FormattedMessage id="pages.searchTable.update" defaultMessage="查看" />
</Button>
),
},
@ -205,7 +230,16 @@ const ModelDetail: React.FC = () => {
renderDom: (
<IsDelete
deleteApi={() => {
handleDestroy(record).then(() => {});
console.log('删除成功');
apiModelVersionDelete({ version_id: record.version_id }).then(() => {
message.success(
intl.formatMessage({
id: 'common.action.success',
defaultMessage: '$$$',
}),
);
reloadList();
});
}}
></IsDelete>
),
@ -331,6 +365,13 @@ const ModelDetail: React.FC = () => {
modelInfo={modelInfo}
reload={reloadList}
/>
<UpdateForm
updateModalOpen={updateModalOpen}
handleModal={handleUpdateModal}
modelInfo={modelInfo}
values={currentRow}
reload={reloadList}
/>
</div>
);
};

@ -1,5 +1,5 @@
import { CommButton } from '@/components/Button';
import { apiModelHubSync } from '@/services/business/model';
import { apiModelHubAdd, apiModelHubSync } from '@/services/business/model';
import {
ModalForm,
ProForm,
@ -11,6 +11,7 @@ import { FormattedMessage, useIntl } from '@umijs/max';
import { Form, message } from 'antd';
import React, { useState } from 'react';
import { isSuccessApi } from '@/utils/forApi';
import {
proFormSmallItemStyleProps,
proFormSmallModelWidth,
@ -31,7 +32,7 @@ const CreateForm: React.FC<CreateFormProps> = (props) => {
className="gn_form gn_modal_form"
width={proFormSmallModelWidth}
title={intl.formatMessage({
id: 'model_runtimeLib.list.table.createForm.add',
id: 'model_runtimeLib.list.table.form.action.add',
defaultMessage: '新建',
})}
open={props.createModalOpen}
@ -44,16 +45,19 @@ const CreateForm: React.FC<CreateFormProps> = (props) => {
submitTimeout={2000}
onFinish={async (values) => {
console.log(values, 'add_finish_values');
// TODO 对接新增接口
// postModelCategoryCreateModelCategory(values)
// .then(() => {
// message.success(intl.formatMessage({ id: 'common.action.success', defaultMessage: '$$$' }));
// props.reload();
// })
// .catch(() => {
// message.error(intl.formatMessage({ id: 'common.action.failure', defaultMessage: '$$$' }));
// });
let resp = await apiModelHubAdd(values);
if (isSuccessApi(resp)) {
message.success(
intl.formatMessage({ id: 'common.action.success', defaultMessage: '$$$' }),
);
props.reload();
props.handleModal();
} else {
message.error(
resp?.meta?.message ||
intl.formatMessage({ id: 'common.action.failure', defaultMessage: '$$$' }),
);
}
return true;
}}
>
@ -87,8 +91,8 @@ const CreateForm: React.FC<CreateFormProps> = (props) => {
<ProForm.Group>
<ProFormText
width={proFormSmallItemStyleProps.column2Width - 30}
name="ip"
initialValue={'http://127.0.0.1'}
name="host"
initialValue={'192.168.10.94'}
label={
<FormattedMessage id="model_runtimeLib.list.table.form.IP" defaultMessage="IP地址" />
}
@ -115,7 +119,7 @@ const CreateForm: React.FC<CreateFormProps> = (props) => {
<ProFormText
width={proFormSmallItemStyleProps.column2Width - 30}
name="port"
initialValue={'80'}
initialValue={'5000'}
label={
<FormattedMessage id="model_runtimeLib.list.table.form.port" defaultMessage="端口" />
}
@ -151,9 +155,8 @@ const CreateForm: React.FC<CreateFormProps> = (props) => {
color: '#154ddd',
}}
onClick={() => {
const { ip, port } = form.getFieldsValue();
if (ip && port) {
// 访问接口拿数据
const { host, port } = form.getFieldsValue();
if (host && port) {
setOpenFiles(true);
} else {
message.error('请填写IP和端口');
@ -167,7 +170,7 @@ const CreateForm: React.FC<CreateFormProps> = (props) => {
{openFiles ? (
<ProFormSelect
width={proFormSmallItemStyleProps.width}
name="fileName"
name="path"
placeholder={`${intl.formatMessage({
id: 'common.please_select',
defaultMessage: '$$$',
@ -179,9 +182,13 @@ const CreateForm: React.FC<CreateFormProps> = (props) => {
showSearch
debounceTime={500}
request={async () => {
const { data } = await apiModelHubSync();
const { host, port } = form.getFieldsValue();
const { data } = await apiModelHubSync({
host,
port,
});
return data?.data?.map((v: Record<string, any>) => {
return { ...v, label: v.name, value: v.id };
return { ...v, label: v, value: v };
});
}}
rules={[
@ -202,7 +209,7 @@ const CreateForm: React.FC<CreateFormProps> = (props) => {
<ProFormTextArea
width={proFormSmallItemStyleProps.width}
name="remark"
name="comment"
label={
<FormattedMessage id="model_runtimeLib.list.table.form.remark" defaultMessage="简介" />
}

@ -0,0 +1,241 @@
import { CommButton } from '@/components/Button';
import { apiModelHubEdit, apiModelHubSync } from '@/services/business/model';
import {
ModalForm,
ProForm,
ProFormSelect,
ProFormText,
ProFormTextArea,
} from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Form, message } from 'antd';
import React, { useEffect, useState } from 'react';
import { isSuccessApi } from '@/utils/forApi';
import {
proFormSmallItemStyleProps,
proFormSmallModelWidth,
} from '../../../../../config/defaultForm';
export type UpdateFormProps = {
updateModalOpen: boolean;
values: Record<string, any>;
handleModal: () => void;
reload: any;
};
const UpdateForm: React.FC<UpdateFormProps> = (props) => {
const intl = useIntl();
const [openFiles, setOpenFiles] = useState<boolean>(false);
const [form] = Form.useForm<API.ModelCategory>();
function resetForm() {
form.resetFields();
}
useEffect(() => {
if (props.updateModalOpen && props.values?.id) {
form.setFieldsValue({ ...props.values });
console.log(props.values, 'useEffect_values');
} else {
resetForm();
}
}, [props.updateModalOpen, props.values]);
return (
<ModalForm<API.ModelCategory>
className="gn_form gn_modal_form"
width={proFormSmallModelWidth}
title={intl.formatMessage({
id: 'model_runtimeLib.list.table.form.action.edit',
defaultMessage: '编辑',
})}
open={props.updateModalOpen}
form={form}
autoFocusFirstInput
modalProps={{
destroyOnClose: true,
onCancel: () => props.handleModal(),
}}
submitTimeout={2000}
onFinish={async (values) => {
console.log(values, 'add_finish_values');
let resp = await apiModelHubEdit({ ...values, id: props.values.id });
if (isSuccessApi(resp)) {
message.success(
intl.formatMessage({ id: 'common.action.success', defaultMessage: '$$$' }),
);
props.reload();
props.handleModal();
} else {
message.error(
resp?.meta?.message ||
intl.formatMessage({ id: 'common.action.failure', defaultMessage: '$$$' }),
);
}
return true;
}}
>
<ProForm.Group>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="name"
label={
<FormattedMessage id="model_runtimeLib.list.table.form.name" defaultMessage="名称" />
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'model_runtimeLib.list.table.form.name',
defaultMessage: '$$$',
})}`}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="model_runtimeLib.list.table.form.rule.required.name"
defaultMessage="name is required"
/>
),
},
]}
/>
<ProForm.Group>
<ProFormText
width={proFormSmallItemStyleProps.column2Width - 30}
name="host"
initialValue={'192.168.10.94'}
label={
<FormattedMessage id="model_runtimeLib.list.table.form.IP" defaultMessage="IP地址" />
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'model_runtimeLib.list.table.form.IP',
defaultMessage: '$$$',
})}`}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="model_runtimeLib.list.table.form.rule.required.IP"
defaultMessage="name is required"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.column2Width - 30}
name="port"
initialValue={'5000'}
label={
<FormattedMessage id="model_runtimeLib.list.table.form.port" defaultMessage="端口" />
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'model_runtimeLib.list.table.form.port',
defaultMessage: '$$$',
})}`}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="model_runtimeLib.list.table.form.rule.required.port"
defaultMessage="name is required"
/>
),
},
]}
/>
<CommButton
style={{
width: '52px',
height: '32px',
marginTop: '30px',
marginLeft: '-4px',
borderRadius: '4px',
borderColor: '#154ddd',
color: '#154ddd',
}}
onClick={() => {
const { host, port } = form.getFieldsValue();
if (host && port) {
setOpenFiles(true);
} else {
message.error('请填写IP和端口');
}
console.log(form.getFieldsValue(), 'searchIP');
}}
buttonLabel={<FormattedMessage id="pages.searchTable.search" defaultMessage="查询" />}
></CommButton>
</ProForm.Group>
{openFiles ? (
<ProFormSelect
width={proFormSmallItemStyleProps.width}
name="path"
placeholder={`${intl.formatMessage({
id: 'common.please_select',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'model_runtimeLib.list.table.form.fileName',
defaultMessage: '$$$',
})}`}
required={true}
showSearch
debounceTime={500}
request={async () => {
const { host, port } = form.getFieldsValue();
const { data } = await apiModelHubSync({
host,
port,
});
return data?.data?.map((v: Record<string, any>) => {
return { ...v, label: v, value: v };
});
}}
rules={[
{
required: true,
message: (
<FormattedMessage
id="model_runtimeLib.list.table.form.rule.required.fileName"
defaultMessage="name is required"
/>
),
},
]}
/>
) : (
<></>
)}
<ProFormTextArea
width={proFormSmallItemStyleProps.width}
name="comment"
label={
<FormattedMessage id="model_runtimeLib.list.table.form.remark" defaultMessage="简介" />
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'model_runtimeLib.list.table.form.rule.required.remark',
defaultMessage: '$$$',
})}`}
required={false}
disabled={false}
/>
</ProForm.Group>
</ModalForm>
);
};
export default UpdateForm;

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-08 10:36:06
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-31 14:20:31
* @LastEditTime: 2024-06-06 15:13:25
* @FilePath: \general-ai-manage\src\pages\Model\ModelRuntimeLib\index.tsx
* @Description:
* @
@ -11,7 +11,7 @@
*
*/
import { apiModelHubList } from '@/services/business/model';
import { apiModelHubDelete, apiModelHubInfo, apiModelHubList } from '@/services/business/model';
import { isSuccessApi } from '@/utils/forApi';
import { CommButton } from '@/components/Button';
@ -20,17 +20,19 @@ import IsDelete from '@/components/TableActionCard/isDelete';
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 } from '@umijs/max';
import { Button } from 'antd';
import { Access, FormattedMessage, history, useAccess, useIntl } from '@umijs/max';
import { Button, message } from 'antd';
import React, { useEffect, useRef, useState } from 'react';
import { proTableCommonOptions, proTablePaginationOptions } from '../../../../config/defaultTable';
import CreateForm from './components/createForm';
import UpdateForm from './components/updateForm';
import { ReactComponent as ResetIcon } from '/public/home/reset_icon.svg';
import { ReactComponent as SearchIcon } from '/public/home/search_icon.svg';
const ModelRuntimeLib: React.FC = () => {
const access = useAccess();
// const intl = useIntl();
const intl = useIntl();
const actionRef = useRef<ActionType>();
const [querysData, setQuerysData] = useState<Record<string, any>>({}); // 列表查询参数
@ -41,24 +43,25 @@ const ModelRuntimeLib: React.FC = () => {
const [currentRow, setCurrentRow] = useState<Record<string, any>>({});
const [form] = ProForm.useForm(); // form 对象
/**
* @en-US The pop-up window of the distribution update window
* @zh-CN
* */
// const [updateModalOpen, setUpdateModalOpen] = useState<boolean>(false);
const [updateModalOpen, setUpdateModalOpen] = useState<boolean>(false);
// const [showDetail, setShowDetail] = useState<boolean>(false);
/**新增 编辑 删除 */
// 新增
const handleCreateModal = () => {
if (createModalOpen) {
setCreateModalOpen(false);
setCurrentRow(undefined);
} else {
setCreateModalOpen(true);
}
setCreateModalOpen(!createModalOpen);
};
// 编辑
const handleUpdateModal = () => {
setUpdateModalOpen(!updateModalOpen);
};
// 设备节点信息
async function loadDetail(record) {
const resp = await apiModelHubInfo({ id: record?.id });
if (isSuccessApi(resp) && resp?.data) {
setCurrentRow({ ...resp?.data, id: record?.id });
}
}
function reloadList() {
actionRef.current?.reload();
}
@ -68,7 +71,6 @@ const ModelRuntimeLib: React.FC = () => {
reloadList();
}
}, [actionRef, querysData]);
// TODO 完善列表展示字段
const columns: ProColumns<Record<string, any>>[] = [
{
title: <FormattedMessage id="model_runtimeLib.table.list.name" defaultMessage="$$$" />,
@ -77,11 +79,17 @@ const ModelRuntimeLib: React.FC = () => {
key: 'fixedName',
fixed: 'left',
},
{
title: <FormattedMessage id="model_runtimeLib.table.list.path" defaultMessage="创建时间" />,
dataIndex: 'path',
hideInSearch: true,
},
{
title: (
<FormattedMessage id="model_runtimeLib.table.list.createTime" defaultMessage="创建时间" />
),
dataIndex: 'createTime',
dataIndex: 'create_time',
hideInSearch: true,
valueType: 'dateTime',
},
@ -90,7 +98,7 @@ const ModelRuntimeLib: React.FC = () => {
title: (
<FormattedMessage id="model_runtimeLib.table.list.updateTime" defaultMessage="更新时间" />
),
dataIndex: 'updateTime',
dataIndex: 'update_time',
hideInSearch: true,
valueType: 'dateTime',
},
@ -113,8 +121,8 @@ const ModelRuntimeLib: React.FC = () => {
type="link"
size="small"
onClick={() => {
// setUpdateModalOpen(true);
setCurrentRow(record);
loadDetail(record);
setUpdateModalOpen(true);
}}
>
<FormattedMessage id="pages.searchTable.update" defaultMessage="Update" />
@ -126,7 +134,16 @@ const ModelRuntimeLib: React.FC = () => {
renderDom: (
<IsDelete
deleteApi={() => {
handleDestroy(record).then(() => {});
console.log('删除成功');
apiModelHubDelete({ id: record.id }).then(() => {
message.success(
intl.formatMessage({
id: 'common.action.success',
defaultMessage: '$$$',
}),
);
reloadList();
});
}}
></IsDelete>
),
@ -216,7 +233,10 @@ const ModelRuntimeLib: React.FC = () => {
setCreateModalOpen(true);
}}
>
<FormattedMessage id="pages.searchTable.new" defaultMessage="New" />
<FormattedMessage
id="model_runtimeLib.list.table.form.action.add"
defaultMessage="新建"
/>
</Button>
</Access>
}
@ -250,23 +270,18 @@ const ModelRuntimeLib: React.FC = () => {
persistenceKey: 'algorithm_model_list',
persistenceType: 'localStorage',
}}
request={async (params = {}, sort) => {
request={async (params = {}) => {
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 apiModelHubList({ ...reqParams, ...querysData });
if (isSuccessApi(resp)) {
if (!isSuccessApi(resp)) {
return { data: [], success: true };
}
console.log(resp, 'apiEntityNodesDeviceList_resp');
return {
data: resp.data?.data,
success: resp.success,
@ -280,10 +295,15 @@ const ModelRuntimeLib: React.FC = () => {
</ProCard>
<CreateForm
createModalOpen={createModalOpen}
values={currentRow || {}}
handleModal={handleCreateModal}
reload={reloadList}
/>
<UpdateForm
updateModalOpen={updateModalOpen}
handleModal={handleUpdateModal}
values={currentRow}
reload={reloadList}
/>
</div>
);
};

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-05-23 13:50:50
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-30 15:01:21
* @LastEditTime: 2024-06-06 15:39:10
* @FilePath: \general-ai-platform-web\src\services\Business\entity.ts
* @Description: api
*/

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-05-24 17:57:19
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-31 14:19:28
* @LastEditTime: 2024-06-06 15:44:20
* @FilePath: \general-ai-platform-web\src\services\business\model.ts
* @Description: api
*/
@ -15,7 +15,7 @@ import { request } from '@umijs/max';
// 添加企业部署的业务模型
export async function apiModelDeploymentAdd(body: any, options?: { [key: string]: any }) {
return request<API.Response & { data?: API.ENTITY_INDEX_DATA; msg?: string }>(
`/api/v1/model/deployment/add`,
`/api/v1/enterprise/model/deployment/add`,
{
method: 'POST',
headers: {
@ -30,7 +30,7 @@ export async function apiModelDeploymentAdd(body: any, options?: { [key: string]
// 编辑企业部署的业务模型
export async function apiModelDeploymentEdit(body: any, options?: { [key: string]: any }) {
return request<API.Response & { data?: API.ENTITY_INDEX_DATA; msg?: string }>(
`/api/v1/model/deployment/edit`,
`/api/v1/enterprise/model/deployment/edit`,
{
method: 'POST',
headers: {
@ -45,7 +45,7 @@ export async function apiModelDeploymentEdit(body: any, options?: { [key: string
// 企业部署的业务模型列表
export async function apiModelDeploymentList(body: any, options?: { [key: string]: any }) {
return request<API.Response & { data?: API.ENTITY_INDEX_DATA; msg?: string }>(
`/api/v1/model/deployment/list`,
`/api/v1/enterprise/model/deployment/list`,
{
method: 'POST',
headers: {
@ -60,7 +60,7 @@ export async function apiModelDeploymentList(body: any, options?: { [key: string
// // 删除企业部署的业务模型
// export async function apiModelDeploymentDelete(body: any, options?: { [key: string]: any }) {
// return request<API.Response & { data?: API.ENTITY_INDEX_DATA; msg?: string }>(
// `/api/v1/model/deployment/delete`,
// `/api/v1/enterprise/model/deployment/delete`,
// {
// method: 'POST',
// headers: {
@ -76,7 +76,7 @@ export async function apiModelDeploymentList(body: any, options?: { [key: string
// 企业部署的业务模型信息
export async function apiModelDeploymentInfo(body: any, options?: { [key: string]: any }) {
return request<API.Response & { data?: API.ENTITY_INDEX_DATA; msg?: string }>(
`/api/v1/model/deployment/info`,
`/api/v1/enterprise/model/deployment/info`,
{
method: 'POST',
headers: {

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-24 10:11:48
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-27 14:00:45
* @LastEditTime: 2024-06-05 10:47:32
* @FilePath: \general-ai-platform-web\src\utils\forApi.ts
* @Description:
*/
@ -18,6 +18,7 @@ export function isSuccessApi(result: API.API_COMMON_DATA): boolean {
if (meta.code < 300 && meta.code >= 200) {
return true;
}
return false;
}
return false;
}

@ -0,0 +1,22 @@
/*
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-06-05 13:32:31
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-06-06 13:13:25
* @FilePath: \general-ai-platform-web\src\utils\is.ts
* @Description:
*/
/**
* @JSONString
* @param jsonString
* @returns boolean
*/
export function isValidJson(jsonString) {
try {
JSON.parse(jsonString);
return true;
} catch (e) {
return false;
}
}
Loading…
Cancel
Save