feat: 完善节点模块,初步完成联调

develop2
donghao 1 year ago
parent 120b162a40
commit a00eeb2ffd

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd * @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-28 15:30:31 * @Date: 2024-04-28 15:30:31
* @LastEditors: donghao donghao@supervision.ltd * @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-09 14:35:52 * @LastEditTime: 2024-06-20 14:19:19
* @FilePath: \general-ai-platform-web\src\enums\server.ts * @FilePath: \general-ai-platform-web\src\enums\server.ts
* @Description: * @Description:
*/ */
@ -14,12 +14,12 @@ export const serverStateEnums: DICTENUM.DICT_TAB_ITEM[] = [
}, },
{ {
label: '在线', label: '在线',
key: '1', key: '1001',
className: 'online_info', className: 'online_info',
}, },
{ {
label: '离线', label: '离线',
key: '2', key: '1002',
className: 'outline_info', className: 'outline_info',
}, },
]; ];

@ -2,14 +2,15 @@
* @Author: donghao donghao@supervision.ltd * @Author: donghao donghao@supervision.ltd
* @Date: 2024-05-09 15:21:03 * @Date: 2024-05-09 15:21:03
* @LastEditors: donghao donghao@supervision.ltd * @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-06-11 14:52:12 * @LastEditTime: 2024-06-20 15:03:24
* @FilePath: \general-ai-platform-web\src\locales\zh-CN\server.ts * @FilePath: \general-ai-platform-web\src\locales\zh-CN\server.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/ */
// 服务器状态 // 服务器状态
export const server_state: { [key: string]: string } = { export const server_state: { [key: string]: string } = {
'server_state.create.form.add': '新建服务器', 'server_state.create.form.action.add': '新建服务器',
'server_state.create.form.action.edit': '编辑服务器',
'server_state.table.list.add': '新建服务器', 'server_state.table.list.add': '新建服务器',
'server_state.table.form.name': '服务器名称', 'server_state.table.form.name': '服务器名称',
'server_state.table.form.rule.required.name': '请填写服务器名称', 'server_state.table.form.rule.required.name': '请填写服务器名称',

@ -1,18 +1,21 @@
import { apiServerAdd } from '@/services/business/server';
import { isSuccessApi } from '@/utils/forApi';
import { ModalForm, ProForm, ProFormText } from '@ant-design/pro-components'; import { ModalForm, ProForm, ProFormText } from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max'; import { FormattedMessage, useIntl } from '@umijs/max';
import { Form } from 'antd'; import { Form, message } from 'antd';
import React from 'react'; import React from 'react';
import { import {
proFormSmallItemStyleProps, proFormSmallItemStyleProps,
proFormSmallModelWidth, proFormSmallModelWidth,
} from '../../../../../config/defaultForm'; } from '../../../../../config/defaultForm';
export type CreateDeviceFormProps = { export type CreateServerFormProps = {
createModalOpen: boolean; createModalOpen: boolean;
handleModal: () => void; handleModal: () => void;
commInfo: Record<string, any>;
reload: any; reload: any;
}; };
const CreateServerForm: React.FC<CreateDeviceFormProps> = (props) => { const CreateServerForm: React.FC<CreateServerFormProps> = (props) => {
const intl = useIntl(); const intl = useIntl();
const [form] = Form.useForm<API.ModelCategory>(); const [form] = Form.useForm<API.ModelCategory>();
@ -21,7 +24,7 @@ const CreateServerForm: React.FC<CreateDeviceFormProps> = (props) => {
className="gn_modal_form gn_form" className="gn_modal_form gn_form"
width={proFormSmallModelWidth} width={proFormSmallModelWidth}
title={intl.formatMessage({ title={intl.formatMessage({
id: 'server_state.create.form.add', id: 'server_state.create.form.action.add',
defaultMessage: '新建', defaultMessage: '新建',
})} })}
open={props.createModalOpen} open={props.createModalOpen}
@ -33,8 +36,23 @@ const CreateServerForm: React.FC<CreateDeviceFormProps> = (props) => {
}} }}
submitTimeout={2000} submitTimeout={2000}
onFinish={async (values) => { onFinish={async (values) => {
console.log(values, 'add_finish_values'); console.log(values, 'apiServerAdd_values');
// TODO 对接新增接口 let resp = await apiServerAdd({
...values,
entity_id: props?.commInfo?.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: '$$$' }),
);
}
props.handleModal(); props.handleModal();
return true; return true;
}} }}
@ -67,6 +85,7 @@ const CreateServerForm: React.FC<CreateDeviceFormProps> = (props) => {
<ProFormText <ProFormText
width={proFormSmallItemStyleProps.column2Width} width={proFormSmallItemStyleProps.column2Width}
name="ip" name="ip"
initialValue={'http://192.168.10.1'}
label={<FormattedMessage id="server_state.table.form.ip" defaultMessage="IP" />} label={<FormattedMessage id="server_state.table.form.ip" defaultMessage="IP" />}
placeholder={`${intl.formatMessage({ placeholder={`${intl.formatMessage({
id: 'common.please_input', id: 'common.please_input',
@ -79,7 +98,7 @@ const CreateServerForm: React.FC<CreateDeviceFormProps> = (props) => {
<ProFormText <ProFormText
width={proFormSmallItemStyleProps.column2Width} width={proFormSmallItemStyleProps.column2Width}
name="userName" name="username"
label={<FormattedMessage id="server_state.table.form.userName" defaultMessage="用户名" />} label={<FormattedMessage id="server_state.table.form.userName" defaultMessage="用户名" />}
placeholder={`${intl.formatMessage({ placeholder={`${intl.formatMessage({
id: 'common.please_input', id: 'common.please_input',
@ -92,7 +111,7 @@ const CreateServerForm: React.FC<CreateDeviceFormProps> = (props) => {
<ProFormText.Password <ProFormText.Password
width={proFormSmallItemStyleProps.column2Width} width={proFormSmallItemStyleProps.column2Width}
label={<FormattedMessage id="server_state.table.form.pwd" defaultMessage="密码" />} label={<FormattedMessage id="server_state.table.form.pwd" defaultMessage="密码" />}
name="pwd" name="passwd"
placeholder={`${intl.formatMessage({ placeholder={`${intl.formatMessage({
id: 'common.please_input', id: 'common.please_input',
defaultMessage: '$$$', defaultMessage: '$$$',
@ -104,7 +123,8 @@ const CreateServerForm: React.FC<CreateDeviceFormProps> = (props) => {
<ProFormText <ProFormText
width={proFormSmallItemStyleProps.width} width={proFormSmallItemStyleProps.width}
name="defaultPort" name="port"
initialValue={8080}
label={ label={
<FormattedMessage id="server_state.table.form.defaultPort" defaultMessage="默认端口" /> <FormattedMessage id="server_state.table.form.defaultPort" defaultMessage="默认端口" />
} }

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd * @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-08 16:57:30 * @Date: 2024-04-08 16:57:30
* @LastEditors: donghao donghao@supervision.ltd * @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-06-18 11:43:19 * @LastEditTime: 2024-06-20 15:39:47
* @FilePath: \general-ai-manage\src\pages\Project\BusinessProject\components\detailServerState.tsx * @FilePath: \general-ai-manage\src\pages\Project\BusinessProject\components\detailServerState.tsx
* @Description: * @Description:
* @ * @
@ -19,11 +19,17 @@ import { proFormMaxModelWidth } from '../../../../../config/defaultForm';
import DetailServerStateLog from './detailServerStateLog'; import DetailServerStateLog from './detailServerStateLog';
type DetailServerStateProps = { type DetailServerStateProps = {
info: Record<string, any>; info: Record<string, any>;
commInfo: Record<string, any>;
detailOpen: boolean; detailOpen: boolean;
closeModal: () => void; closeModal: () => void;
}; };
const DetailServerState: React.FC<DetailServerStateProps> = ({ info, detailOpen, closeModal }) => { const DetailServerState: React.FC<DetailServerStateProps> = ({
info,
commInfo,
detailOpen,
closeModal,
}) => {
/**state */ /**state */
const intl = useIntl(); const intl = useIntl();
const [tabKey, setTabKey] = useState<string>(bsServerDetailEnums[0].key); const [tabKey, setTabKey] = useState<string>(bsServerDetailEnums[0].key);
@ -35,11 +41,11 @@ const DetailServerState: React.FC<DetailServerStateProps> = ({ info, detailOpen,
const ModelDetailColumns = [ const ModelDetailColumns = [
{ {
title: <FormattedMessage id="server_state.table.form.name" defaultMessage="服务器名称" />, title: <FormattedMessage id="server_state.table.form.name" defaultMessage="服务器名称" />,
dataIndex: 'deviceSort', dataIndex: 'name',
}, },
{ {
title: <FormattedMessage id="server_state.table.form.ip" defaultMessage="IP" />, title: <FormattedMessage id="server_state.table.form.ip" defaultMessage="IP" />,
dataIndex: 'IP', dataIndex: 'ip',
}, },
{ {
title: ( title: (
@ -49,34 +55,35 @@ const DetailServerState: React.FC<DetailServerStateProps> = ({ info, detailOpen,
}, },
{ {
title: <FormattedMessage id="server_state.table.form.userName" defaultMessage="用户名" />, title: <FormattedMessage id="server_state.table.form.userName" defaultMessage="用户名" />,
dataIndex: 'userName', dataIndex: 'username',
},
{
title: <FormattedMessage id="server_state.table.form.pwd" defaultMessage="密码" />,
dataIndex: 'pwd',
render: () => {
return '*********';
},
}, },
// {
// title: <FormattedMessage id="server_state.table.form.pwd" defaultMessage="密码" />,
// dataIndex: 'passwd',
// render: () => {
// return '*********';
// },
// },
]; ];
// TODO 切换详情展示,未能渲染出来信息环形图
// 硬件信息环形图 // 硬件信息环形图
const fetchOptionByData = (record) => { const fetchOptionByData = (record) => {
const totalCount = 100 * Math.floor(Math.random() * 15); const totalCount = 100;
const currData = [ const currData = [
{ {
value: record?.percent * totalCount, value: record?.percent * totalCount,
name: `${intl.formatMessage({ name: `${intl.formatMessage({
id: 'server_state.table.detail.echarts.used', id: 'server_state.table.detail.echarts.used',
defaultMessage: '已占用', defaultMessage: '已占用',
})}${record?.percent * 100}%`, })}${Math.floor(record?.percent * totalCount)}%`,
}, },
{ {
value: totalCount - record?.percent * totalCount, value: totalCount - record?.percent * totalCount,
name: `${intl.formatMessage({ name: `${intl.formatMessage({
id: 'server_state.table.detail.echarts.free', id: 'server_state.table.detail.echarts.free',
defaultMessage: '未占用', defaultMessage: '未占用',
})}${100 - record?.percent * 100}%`, })}${100 - Math.floor(record?.percent * totalCount)}%`,
}, },
]; ];
@ -96,7 +103,7 @@ const DetailServerState: React.FC<DetailServerStateProps> = ({ info, detailOpen,
}, },
tooltip: { tooltip: {
trigger: 'item', trigger: 'item',
formatter: '{a} <br/>{b} : {c} ({d}%)', formatter: '{a} <br/>{b}',
}, },
legend: { legend: {
orient: 'horizontal', orient: 'horizontal',
@ -153,104 +160,14 @@ const DetailServerState: React.FC<DetailServerStateProps> = ({ info, detailOpen,
}; };
}; };
// 模型列表信息
// const columns: ProColumns<Record<string, any>>[] = [
// {
// title: <FormattedMessage id="base_model.table.list.name" defaultMessage="基础模型名称" />,
// dataIndex: 'name',
// hideInSearch: true,
// key: 'fixedName',
// fixed: 'left',
// width: '45%',
// },
// {
// title: <FormattedMessage id="base_model.table.list.version" defaultMessage="版本" />,
// dataIndex: 'version',
// hideInSearch: true,
// width: '20%',
// },
// {
// title: (
// <FormattedMessage id="base_model.table.list.runtimeLibFile" defaultMessage="运行库镜像" />
// ),
// dataIndex: 'runtimeLibFile',
// hideInSearch: true,
// render: (dom, record) => {
// return (
// <div>
// {record.runtimeLibFile ? (
// dom
// ) : (
// <div className={`gn_list_type_tag flex items-center justify-center active2`}>
// <span className="dot"></span>
// <span>
// <FormattedMessage
// id="base_model.table.list.undeployed.runtimeLibFile"
// defaultMessage="未部署"
// />
// </span>
// </div>
// )}
// </div>
// );
// },
// },
// ];
// 将数据组装成reactDom
// function toListDomByData(record) {
// let startList = [...record];
// let finalList = startList.map((item) => ({
// content: (
// <div>
// <div className="gn_list_card_title pb-[12px]">
// <span></span>
// <span>{item.name}</span>
// </div>
// <ProTable
// className="gn_pro_table mb-[16px]"
// cardProps={{
// bodyStyle: { padding: 0, margin: 0 },
// }}
// // 标题栏
// search={false}
// options={{ fullScreen: false, setting: false, density: false, reload: false }}
// rowKey="id"
// onDataSourceChange={(data) => {
// console.log(data, 'onDataSourceChange_data');
// }}
// pagination={false}
// dataSource={item.list}
// columns={columns}
// />
// </div>
// ),
// }));
// setModelData(finalList);
// console.log(finalList, 'toListDomByData_finalList');
// }
// 基础模型列表数据api
// async function fetchData() {
// const resp = await getModelGroupBaseModelList();
// if (isSuccessApi(resp)) {
// toListDomByData(resp.data.data);
// }
// }
useEffect(() => { useEffect(() => {
setForceRender(detailOpen); setForceRender(detailOpen);
}, [detailOpen]); }, [detailOpen]);
// 初始化加载
// useEffect(() => {
// fetchData();
// }, []);
return ( return (
<Modal <Modal
width={proFormMaxModelWidth} width={proFormMaxModelWidth}
title={info?.deviceSort} title={info?.name}
open={detailOpen} open={detailOpen}
onCancel={closeModal} onCancel={closeModal}
footer={null} footer={null}
@ -282,7 +199,7 @@ const DetailServerState: React.FC<DetailServerStateProps> = ({ info, detailOpen,
</p> </p>
<div className="mb-[8px] mt-[12px] gn_active_descriptions gn_descriptions bg_active_4"> <div className="mb-[8px] mt-[12px] gn_active_descriptions gn_descriptions bg_active_4">
<ProDescriptions <ProDescriptions
column={5} column={4}
columns={ModelDetailColumns} columns={ModelDetailColumns}
dataSource={info} dataSource={info}
></ProDescriptions> ></ProDescriptions>
@ -315,52 +232,11 @@ const DetailServerState: React.FC<DetailServerStateProps> = ({ info, detailOpen,
})} })}
</ul> </ul>
</li> </li>
{/* 服务器信息暂时不需要当前任务模块 */}
{/* <li className="pb-[8px] bs_server_task_wrap">
<p className="head4">
<FormattedMessage
id="server_state.table.detail.title.task"
defaultMessage="当前任务"
/>
</p>
<div className="mt-[12px]">
<ProList<{ title: string }>
className="gn_pro_list"
itemLayout="vertical"
itemCardProps={{
ghost: true,
bodyStyle: { padding: 0, margin: 0 },
style: {
width: '100%',
border: 0,
},
}}
cardProps={{
style: { padding: 0, margin: 0 }, // 设置卡片的内外边距为 0
bodyStyle: {
padding: 0,
margin: 0,
height: 'calc(300px)',
overflow: 'scroll',
},
}}
rowKey="id"
dataSource={modelData}
pagination={false}
rowSelection={false}
metas={{
content: {
style: { margin: 0, padding: 0 },
},
}}
/>
</div>
</li> */}
</ul> </ul>
</ProCard> </ProCard>
</div> </div>
)} )}
{tabKey === '1' && <DetailServerStateLog />} {tabKey === '1' && <DetailServerStateLog commInfo={commInfo} />}
</ProCard> </ProCard>
</Modal> </Modal>
); );

@ -2,21 +2,24 @@
* @Author: donghao donghao@supervision.ltd * @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-22 15:23:36 * @Date: 2024-04-22 15:23:36
* @LastEditors: donghao donghao@supervision.ltd * @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-13 10:44:03 * @LastEditTime: 2024-06-20 17:14:08
* @FilePath: \general-ai-platform-web\src\pages\Business\BusinessState\components\detailServerStateLog.tsx * @FilePath: \general-ai-platform-web\src\pages\Business\BusinessState\components\detailServerStateLog.tsx
* @Description: * @Description:
* @ * @
* 1 * 1
*/ */
import { getServerStateLogList } from '@/services/testApi/businessState'; import { apiServerLog } from '@/services/business/server';
import { isSuccessApi } from '@/utils/forApi';
import type { ActionType, ProColumns } from '@ant-design/pro-components'; import type { ActionType, ProColumns } from '@ant-design/pro-components';
import { ProCard, ProTable } from '@ant-design/pro-components'; import { ProCard, ProTable } from '@ant-design/pro-components';
import { FormattedMessage } from '@umijs/max'; import { FormattedMessage } from '@umijs/max';
import { useRef, useState } from 'react'; import { useRef, useState } from 'react';
import { proTablePaginationOptions } from '../../../../../config/defaultTable'; import { proTablePaginationOptions } from '../../../../../config/defaultTable';
type DetailServerStateLogProps = {
const DetailServerStateLog: React.FC = () => { commInfo: Record<string, any>;
};
const DetailServerStateLog: React.FC<DetailServerStateLogProps> = (props) => {
const actionRef = useRef<ActionType>(); const actionRef = useRef<ActionType>();
// 动态设置每页数量 // 动态设置每页数量
const [currentPageSize, setCurrentPageSize] = useState<number>(10); const [currentPageSize, setCurrentPageSize] = useState<number>(10);
@ -24,7 +27,7 @@ const DetailServerStateLog: React.FC = () => {
const columns: ProColumns<Record<string, any>>[] = [ const columns: ProColumns<Record<string, any>>[] = [
{ {
title: <FormattedMessage id="server_state.table.stateLog.list.ip" defaultMessage="名称" />, title: <FormattedMessage id="server_state.table.stateLog.list.ip" defaultMessage="名称" />,
dataIndex: 'IP', dataIndex: 'ip',
hideInSearch: true, hideInSearch: true,
key: 'fixedName', key: 'fixedName',
fixed: 'left', fixed: 'left',
@ -74,11 +77,15 @@ const DetailServerStateLog: React.FC = () => {
request={async (params = {}) => { request={async (params = {}) => {
const { current, ...rest } = params; const { current, ...rest } = params;
const reqParams = { const reqParams = {
entity_id: props?.commInfo?.id,
pageNo: current, pageNo: current,
...rest, ...rest,
}; };
let resp = await getServerStateLogList({ ...reqParams }); let resp = await apiServerLog({ ...reqParams });
console.log(resp, 'getServerStateLogList_resp'); console.log(resp, 'apiServerLog_resp');
if (!isSuccessApi(resp)) {
return { data: [], success: true };
}
return { return {
data: resp.data?.data, data: resp.data?.data,
success: resp.success, success: resp.success,

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd * @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-08 16:57:30 * @Date: 2024-04-08 16:57:30
* @LastEditors: donghao donghao@supervision.ltd * @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-22 16:20:48 * @LastEditTime: 2024-06-20 15:07:58
* @FilePath: \general-ai-manage\src\pages\Business\BusinessState\components\serverStateCard.tsx * @FilePath: \general-ai-manage\src\pages\Business\BusinessState\components\serverStateCard.tsx
* @Description: * @Description:
*/ */
@ -25,7 +25,7 @@ const ServerStateCard: React.FC<ServerStateCardProps> = ({ info, renderActions,
// 动效类型 // 动效类型
const fetchAnimatePicByType = () => { const fetchAnimatePicByType = () => {
switch (info?.state) { switch (Number(info?.status)) {
case '1': case '1':
return <AnimatePic value={onlineAnimateJson} />; return <AnimatePic value={onlineAnimateJson} />;
default: default:
@ -41,16 +41,16 @@ const ServerStateCard: React.FC<ServerStateCardProps> = ({ info, renderActions,
}} }}
className={`bs_card_box `} className={`bs_card_box `}
> >
<div className={`bs_card_body ${formatStateByVal(info?.state)?.className}`}> <div className={`bs_card_body ${formatStateByVal(Number(info?.status))?.className}`}>
<div className="flex justify-between w-full p-[12px] bs_card_header"> <div className="flex justify-between w-full p-[12px] bs_card_header">
<div className="flex items-center title_box"> <div className="flex items-center title_box">
<div className="bs_card_name single_line head4">{info?.deviceSort}</div> <div className="bs_card_name single_line head4">{info?.name}</div>
<div <div
className={`gn_card_tag ml-[8px] text-white ${ className={`gn_card_tag ml-[8px] text-white ${
info?.state === '1' ? 'bg_active_1' : 'bg_gray_color_1' Number(info?.status) === 1001 ? 'bg_active_1' : 'bg_gray_color_1'
}`} }`}
> >
{formatStateByVal(info?.state).label} {formatStateByVal(info?.status + '')?.label}
</div> </div>
</div> </div>
<span> <span>

@ -0,0 +1,157 @@
import { apiServerEdit } from '@/services/business/server';
import { isSuccessApi } from '@/utils/forApi';
import { ModalForm, ProForm, ProFormText } from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Form, message } from 'antd';
import React, { useEffect } from 'react';
import {
proFormSmallItemStyleProps,
proFormSmallModelWidth,
} from '../../../../../config/defaultForm';
export type UpdateServerFormProps = {
updateModalOpen: boolean;
handleModal: () => void;
values: Record<string, any>;
commInfo: Record<string, any>;
reload: any;
};
const UpdateServerForm: React.FC<UpdateServerFormProps> = (props) => {
const intl = useIntl();
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_modal_form gn_form"
width={proFormSmallModelWidth}
title={intl.formatMessage({
id: 'server_state.create.form.action.edit',
defaultMessage: '编辑',
})}
open={props.updateModalOpen}
form={form}
autoFocusFirstInput
modalProps={{
destroyOnClose: true,
onCancel: () => props.handleModal(),
}}
submitTimeout={2000}
onFinish={async (values) => {
console.log(values, 'apiServerEdit_values');
let resp = await apiServerEdit({
...values,
entity_id: props?.commInfo?.id,
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: '$$$' }),
);
}
props.handleModal();
return true;
}}
>
<ProForm.Group>
<ProFormText
width={proFormSmallItemStyleProps.column2Width}
name="name"
label={<FormattedMessage id="server_state.table.form.name" defaultMessage="名称" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'server_state.table.form.name',
defaultMessage: '$$$',
})}`}
required={true}
rules={[
{
required: true,
message: (
<FormattedMessage
id="server_state.table.form.rule.required.name"
defaultMessage="名称必填"
/>
),
},
]}
/>
<ProFormText
width={proFormSmallItemStyleProps.column2Width}
name="ip"
initialValue={'http://192.168.10.1'}
label={<FormattedMessage id="server_state.table.form.ip" defaultMessage="IP" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'server_state.table.form.ip',
defaultMessage: '$$$',
})}`}
/>
<ProFormText
width={proFormSmallItemStyleProps.column2Width}
name="username"
label={<FormattedMessage id="server_state.table.form.userName" defaultMessage="用户名" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'server_state.table.form.userName',
defaultMessage: '$$$',
})}`}
/>
{/* // TODO 密码默认渲染*** */}
<ProFormText.Password
width={proFormSmallItemStyleProps.column2Width}
label={<FormattedMessage id="server_state.table.form.pwd" defaultMessage="密码" />}
name="passwd"
initialValue={'******'}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'server_state.table.form.pwd',
defaultMessage: '$$$',
})}`}
/>
<ProFormText
width={proFormSmallItemStyleProps.width}
name="port"
initialValue={8080}
label={
<FormattedMessage id="server_state.table.form.defaultPort" defaultMessage="默认端口" />
}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'server_state.table.form.defaultPort',
defaultMessage: '$$$',
})}`}
/>
</ProForm.Group>
</ModalForm>
);
};
export default UpdateServerForm;

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd * @Author: donghao donghao@supervision.ltd
* @Date: 2024-05-10 10:47:45 * @Date: 2024-05-10 10:47:45
* @LastEditors: donghao donghao@supervision.ltd * @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-06-19 11:29:16 * @LastEditTime: 2024-06-20 14:33:07
* @FilePath: \general-ai-platform-web\src\pages\Business\BusinessState\deviceSate.tsx * @FilePath: \general-ai-platform-web\src\pages\Business\BusinessState\deviceSate.tsx
* @Description: * @Description:
* @ * @
@ -235,11 +235,6 @@ const DeviceSate: React.FC = () => {
setCurrentPage(1); setCurrentPage(1);
console.log(key); console.log(key);
}; };
// function reloadList() {
// setTabKey('0');
// setCurrentPage(1);
// }
// 设备节点树 // 设备节点树
async function loadDeviceTree() { async function loadDeviceTree() {
const resp = await apiEntityNodes({ entity_id: commInfo.id }); const resp = await apiEntityNodes({ entity_id: commInfo.id });
@ -247,7 +242,6 @@ const DeviceSate: React.FC = () => {
setDeviceTreeList(resp?.data?.data); setDeviceTreeList(resp?.data?.data);
} }
} }
// 初始化加载 & 筛选查询 // 初始化加载 & 筛选查询
useEffect(() => { useEffect(() => {
fetchData(); fetchData();
@ -312,13 +306,6 @@ const DeviceSate: React.FC = () => {
id: 'device_group_list.table.list.deviceNode', id: 'device_group_list.table.list.deviceNode',
defaultMessage: '节点', defaultMessage: '节点',
})}`} })}`}
// treeData={deviceTreeList}
// fieldNames= {{
// label: 'name',
// value: 'id',
// children: 'children',
// }}
fieldProps={{ fieldProps={{
multiple: true, multiple: true,
treeData: deviceTreeList, treeData: deviceTreeList,

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd * @Author: donghao donghao@supervision.ltd
* @Date: 2024-05-07 13:38:03 * @Date: 2024-05-07 13:38:03
* @LastEditors: donghao donghao@supervision.ltd * @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-22 16:45:57 * @LastEditTime: 2024-06-20 15:29:43
* @FilePath: \general-ai-platform-web\src\pages\Business\BusinessState\index.tsx * @FilePath: \general-ai-platform-web\src\pages\Business\BusinessState\index.tsx
* @Description: businessStatebs * @Description: businessStatebs
* @ * @
@ -12,20 +12,27 @@
import { CommButton, TextButton } from '@/components/Button'; import { CommButton, TextButton } from '@/components/Button';
import IsDelete from '@/components/TableActionCard/isDelete'; import IsDelete from '@/components/TableActionCard/isDelete';
import { serverStateEnums } from '@/enums/server'; import { serverStateEnums } from '@/enums/server';
import { getServerStateList } from '@/services/testApi/businessState'; import { useBusinessInfo } from '@/hooks/useBusinessInfo';
import { isSuccessApi } from '@/utils/forApi'; import { isSuccessApi } from '@/utils/forApi';
import { mathSumByNumberArr } from '@/utils/forMath';
import { ProCard, ProList } from '@ant-design/pro-components'; import { ProCard, ProList } from '@ant-design/pro-components';
import { FormattedMessage } from '@umijs/max'; import { FormattedMessage, useIntl } from '@umijs/max';
import { Tabs } from 'antd'; import { Tabs, message } from 'antd';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { proTablePaginationOptions } from '../../../../config/defaultTable'; import { proTablePaginationOptions } from '../../../../config/defaultTable';
import CreateServerForm from './components/createServerForm'; import CreateServerForm from './components/createServerForm';
import DetailServerState from './components/detailServerState'; import DetailServerState from './components/detailServerState';
import ServerStateCard from './components/serverStateCard'; import ServerStateCard from './components/serverStateCard';
import UpdateServerForm from './components/updateServerForm';
import './index.less'; import './index.less';
import { apiServerDelete, apiServerInfo, apiServerList } from '@/services/business/server';
const BusinessState: React.FC = () => { const BusinessState: React.FC = () => {
/**state */ /**state */
const intl = useIntl();
const { getStoreBusinessInfo } = useBusinessInfo();
const [commInfo] = useState<Record<string, any>>({ ...getStoreBusinessInfo() }); // 通用信息
// 列表 // 列表
const [serverList, setServerList] = useState<Record<string, any>[]>([]); // 列表数据 const [serverList, setServerList] = useState<Record<string, any>[]>([]); // 列表数据
const [currentRow, setCurrentRow] = useState<Record<string, any>>(); const [currentRow, setCurrentRow] = useState<Record<string, any>>();
@ -33,6 +40,8 @@ const BusinessState: React.FC = () => {
const [currentPage, setCurrentPage] = useState<number>(1); const [currentPage, setCurrentPage] = useState<number>(1);
const [total, setTotal] = useState<number>(1); const [total, setTotal] = useState<number>(1);
const [createModalOpen, setCreateModalOpen] = useState<boolean>(false); const [createModalOpen, setCreateModalOpen] = useState<boolean>(false);
const [updateModalOpen, setUpdateModalOpen] = useState<boolean>(false);
// 详情展示 // 详情展示
const [detailOpen, setDetailOpen] = useState<boolean>(false); const [detailOpen, setDetailOpen] = useState<boolean>(false);
@ -43,16 +52,70 @@ const BusinessState: React.FC = () => {
const handleCreateModal = () => { const handleCreateModal = () => {
setCreateModalOpen(!createModalOpen); setCreateModalOpen(!createModalOpen);
}; };
// 编辑
const handleUpdateModal = () => {
setUpdateModalOpen(!updateModalOpen);
};
// 组装进度展示信息
function toProgressListByItem(record) {
const { cpu, gpu, mem, storage } = record;
return [
{
label: 'CPU',
percent: cpu / 100,
strokeColor: 'rgb(243,48,5)',
usedColors: ['#FFAB00', '#FF4409'],
freeColors: ['#477BFF', '#0048FE'],
},
{
label: '内存',
percent: mem / 100,
strokeColor: 'rgb(33,169,122)',
usedColors: ['#47A3FF', '#0D6EFF'],
freeColors: ['#00C45A ', '#4AE003'],
},
{
label: '存储',
percent: storage / 100,
strokeColor: 'rgb(33,169,122)',
usedColors: ['#FF8110', '#EB0404'],
freeColors: ['#4200FF', '#9520F0'],
},
{
label: 'GPU',
percent: gpu / 100,
strokeColor: 'rgb(250,173,20)',
usedColors: ['#AE47FF', '#F008AF'],
freeColors: ['#FF4D00', '#F2B721'],
},
];
}
// 服务器详细信息
async function loadDetail(record) {
const resp = await apiServerInfo({ server_id: record?.id });
if (isSuccessApi(resp) && resp?.data) {
setCurrentRow({
...resp?.data,
id: record?.id,
progressData: toProgressListByItem(resp?.data),
});
}
}
// 将数据组装成reactDom // 将数据组装成reactDom
function toListDomByData(record) { function toListDomByData(record) {
let startList = [...record]; let startList = [...record];
startList = startList.map((item) => {
item.progressData = toProgressListByItem(item);
return item;
});
let finalList = startList.map((item) => ({ let finalList = startList.map((item) => ({
content: ( content: (
<ServerStateCard <ServerStateCard
info={item} info={item}
fetchDetail={() => { fetchDetail={() => {
setCurrentRow(item); loadDetail(item);
setDetailOpen(true); setDetailOpen(true);
}} }}
renderActions={[ renderActions={[
@ -62,7 +125,9 @@ const BusinessState: React.FC = () => {
<span <span
onClick={(e) => { onClick={(e) => {
e.stopPropagation(); e.stopPropagation();
setCurrentRow(item); // setCurrentRow(item);
loadDetail(item);
setUpdateModalOpen(true);
console.log('编辑'); console.log('编辑');
}} }}
> >
@ -94,8 +159,17 @@ const BusinessState: React.FC = () => {
></TextButton> ></TextButton>
} }
deleteApi={() => { deleteApi={() => {
// TODO 调用删除接口 console.log('删除成功');
// handleDestroy(record).then(() => {}); apiServerDelete({ id: item.id }).then(() => {
message.success(
intl.formatMessage({
id: 'common.action.success',
defaultMessage: '$$$',
}),
);
// eslint-disable-next-line @typescript-eslint/no-use-before-define
reloadList();
});
}} }}
/> />
</span> </span>
@ -111,25 +185,29 @@ const BusinessState: React.FC = () => {
// 企业列表数据api // 企业列表数据api
async function fetchData() { async function fetchData() {
const resp = await getServerStateList({ const resp = await apiServerList({
pageNo: currentPage, pageNo: currentPage,
pageSize: currentPageSize, pageSize: currentPageSize,
status: tabKey, status: Number(tabKey),
entity_id: commInfo.id,
}); });
if (isSuccessApi(resp)) { if (isSuccessApi(resp)) {
toListDomByData(resp.data.data); toListDomByData(resp.data.data);
const currCounts = { ...resp.data.status };
const currTotalCount = mathSumByNumberArr(Object.values(currCounts));
setTabs(() => { setTabs(() => {
const finalArr = []; const finalArr = [];
JSON.parse(JSON.stringify(serverStateEnums)).forEach((item) => { JSON.parse(JSON.stringify(serverStateEnums)).forEach((item) => {
switch (item.key) { switch (item.key) {
case '0': case '1001':
item.label = `${serverStateEnums[0].label}${resp.data.count}`; item.label = `${serverStateEnums[1].label}${currCounts[serverStateEnums[1].key]}`;
break; break;
case '1': case '1002':
item.label = `${serverStateEnums[1].label}${resp.data.onlineCount}`; item.label = `${serverStateEnums[2].label}${currCounts[serverStateEnums[2].key]}`;
break; break;
case '2': case '0':
item.label = `${serverStateEnums[2].label}${resp.data.outlineCount}`; default:
item.label = `${serverStateEnums[0].label}${currTotalCount}`;
break; break;
} }
finalArr.push(item); finalArr.push(item);
@ -138,9 +216,9 @@ const BusinessState: React.FC = () => {
}); });
setTotal(() => { setTotal(() => {
switch (tabKey) { switch (tabKey) {
case '1': case '1001':
return resp.data.onlineCount; return resp.data.onlineCount;
case '2': case '1002':
return resp.data.outlineCount; return resp.data.outlineCount;
default: default:
return resp.data.count; return resp.data.count;
@ -157,6 +235,7 @@ const BusinessState: React.FC = () => {
function reloadList() { function reloadList() {
setTabKey('0'); setTabKey('0');
setCurrentPage(1); setCurrentPage(1);
fetchData();
} }
// 初始化加载 & 筛选查询 // 初始化加载 & 筛选查询
@ -225,11 +304,20 @@ const BusinessState: React.FC = () => {
<CreateServerForm <CreateServerForm
createModalOpen={createModalOpen} createModalOpen={createModalOpen}
handleModal={handleCreateModal} handleModal={handleCreateModal}
commInfo={commInfo}
reload={reloadList}
/>
<UpdateServerForm
updateModalOpen={updateModalOpen}
handleModal={handleUpdateModal}
values={currentRow}
commInfo={commInfo}
reload={reloadList} reload={reloadList}
/> />
<DetailServerState <DetailServerState
detailOpen={detailOpen} detailOpen={detailOpen}
info={currentRow} info={currentRow}
commInfo={commInfo}
closeModal={() => { closeModal={() => {
setDetailOpen(false); setDetailOpen(false);
}} }}

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd * @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-30 10:02:29 * @Date: 2024-04-30 10:02:29
* @LastEditors: donghao donghao@supervision.ltd * @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-30 16:21:27 * @LastEditTime: 2024-06-20 11:30:56
* @FilePath: \general-ai-platform-web\src\pages\Business\DeviceGroup\components\alarmSetForm.tsx * @FilePath: \general-ai-platform-web\src\pages\Business\DeviceGroup\components\alarmSetForm.tsx
* @Description: * @Description:
* @ * @
@ -34,6 +34,7 @@ const AlarmSetForm: React.FC<AlarmSetFormProps> = (props) => {
function fetchInitialValues(record) { function fetchInitialValues(record) {
const { is_sms, is_email, sms_to, email_to, ...restParams } = record; const { is_sms, is_email, sms_to, email_to, ...restParams } = record;
console.log(is_sms, 'fetchInitialValues');
form.setFieldsValue({ form.setFieldsValue({
...restParams, ...restParams,
ways: [ ways: [
@ -52,18 +53,10 @@ const AlarmSetForm: React.FC<AlarmSetFormProps> = (props) => {
} }
async function loadData() { async function loadData() {
// TODO 确认入参是否正确
const resp = await apiEntityNodesAlert({ node_id: props.values.node_id }); const resp = await apiEntityNodesAlert({ node_id: props.values.node_id });
if (isSuccessApi(resp) && resp?.data) { if (isSuccessApi(resp) && resp?.data) {
fetchInitialValues(resp?.data); fetchInitialValues(resp?.data);
} }
fetchInitialValues({
is_sms: 1,
is_email: 0,
sms_to: '用户A',
email_to: '',
freq: 'T',
});
} }
useEffect(() => { useEffect(() => {
loadData(); loadData();

@ -1,42 +1,34 @@
import { CommButton } from '@/components/Button'; import { CommButton } from '@/components/Button';
import { getModelRuntimeLibFilesList } from '@/services/testApi/model'; import { FormUploadDraggerToken } from '@/components/UploadFile';
import { apiModelHubSync } from '@/services/business/model';
import { import {
ProForm, ProForm,
ProFormInstance, ProFormInstance,
ProFormList,
ProFormSelect, ProFormSelect,
ProFormText, ProFormText,
ProFormUploadDragger,
StepsForm, StepsForm,
} from '@ant-design/pro-components'; } from '@ant-design/pro-components';
import { FormListActionType } from '@ant-design/pro-form/lib';
import { apiEntityNodesDeviceBasemodelCustomConfig } from '@/services/business/entity';
import { isSuccessApi } from '@/utils/forApi';
import { FormattedMessage, useIntl } from '@umijs/max'; import { FormattedMessage, useIntl } from '@umijs/max';
import { Modal, UploadFile, message } from 'antd'; import { Modal, message } from 'antd';
import yaml from 'js-yaml'; import React, { useRef, useState } from 'react';
import React, { useEffect, useRef, useState } from 'react';
import { import {
proFormSmallItemStyleProps, proFormSmallItemStyleProps,
proFormSmallModelWidth, proFormSmallModelWidth,
proFormStepsFormProps, proFormStepsFormProps,
} from '../../../../../config/defaultForm'; } from '../../../../../config/defaultForm';
// import {beforeUploadFile} from "@/utils/common"; // import {beforeUploadFile} from "@/utils/common";
// @ts-ignore
export type FormValueType = {
target?: string;
template?: string;
type?: string;
time?: string;
frequency?: string;
} & Partial<API.ModelVersion>;
export type CreateModelParamsProps = { export type CreateModelParamsProps = {
createModalOpen: boolean; createModalOpen: boolean;
handleModal: () => void; handleModal: () => void;
values: Partial<API.ModelVersion>; commInfo: Record<string, any>;
nodeInfo: Record<string, any>;
deviceInfo: Record<string, any>;
reload: any; reload: any;
currentDefaultFieldsData?: Record<string, any>;
}; };
const waitTime = (time: number = 100) => { const waitTime = (time: number = 100) => {
return new Promise((resolve) => { return new Promise((resolve) => {
@ -45,61 +37,67 @@ const waitTime = (time: number = 100) => {
}, time); }, time);
}); });
}; };
// interface ProjectConfig {
// params: Array<object>;
// }
const CreateModelParams: React.FC<CreateModelParamsProps> = (props) => {
const actionFormListRef = useRef<
FormListActionType<{
name: string;
}>
>();
const CreateModelParams: React.FC<CreateModelParamsProps> = (props) => {
const intl = useIntl(); const intl = useIntl();
const [isHasModelFkId, setIsHasModelFkId] = useState<boolean>(false);
const [dataFormList] = useState<any>([]); const [currFormData, setCurrFormData] = useState<Record<string, any>>({});
const dataFormListRef = useRef(dataFormList);
const [fileList, setFileList] = useState<UploadFile<any>[]>([]);
// const [form] = Form.useForm<API.ModelVersion>();
const [current, setCurrent] = useState(0); const [current, setCurrent] = useState(0);
const formRef = useRef<ProFormInstance>(); const formRef = useRef<ProFormInstance>();
const [filePath] = useState('');
const [openFiles, setOpenFiles] = useState<boolean>(false); const [openFiles, setOpenFiles] = useState<boolean>(false);
const handleFileChange = ({ file }: { file: UploadFile }) => {
let curFile: any;
switch (file.status) {
case 'uploading':
case 'done':
curFile = [file];
break;
case 'removed':
default:
curFile = [];
break;
}
setFileList([...curFile]);
};
useEffect(() => {
if (props.currentDefaultFieldsData) {
// 如果是在模型详情新增版本ModelFkId不可编辑
console.log(props.values, isHasModelFkId, 'currentDefaultFieldsData');
setIsHasModelFkId(true);
} else {
setIsHasModelFkId(false);
}
}, []);
return ( return (
// TODO stepForm 中上传文件新增参数与UI图不一致
<StepsForm<{ <StepsForm<{
name: string; name: string;
}> }>
onFinish={async (values) => {
console.log(
'commInfo:',
props.commInfo,
'nodeInfo:',
props.nodeInfo,
'deviceInfo:',
props.deviceInfo,
'info:',
props.info,
'apiEntityNodesDeviceBasemodelCustomConfig_values',
values,
{
...values,
base_model_id: props?.info?.base_model_id,
busi_model_id: props?.info?.busi_model_id,
node_id: props?.nodeInfo?.id,
device_id: props?.deviceInfo?.id,
busi_conf_file: currFormData?.busi_conf_file,
model_conf_file: currFormData?.model_conf_file,
},
);
// 在这里处理提交数据
let resp = await apiEntityNodesDeviceBasemodelCustomConfig({
...values,
base_model_id: props?.info?.base_model_id,
busi_model_id: props?.info?.busi_model_id,
node_id: props?.nodeInfo?.id,
device_id: props?.deviceInfo?.id,
busi_conf_file: currFormData?.busi_conf_file,
model_conf_file: currFormData?.model_conf_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} stepsProps={proFormStepsFormProps.stepsProps}
current={current} current={current}
onCurrentChange={setCurrent} onCurrentChange={setCurrent}
@ -119,7 +117,6 @@ const CreateModelParams: React.FC<CreateModelParamsProps> = (props) => {
onCancel={() => { onCancel={() => {
setCurrent(0); setCurrent(0);
formRef.current?.resetFields(); formRef.current?.resetFields();
setFileList([]);
props.handleModal(); props.handleModal();
}} }}
open={props.createModalOpen} open={props.createModalOpen}
@ -149,121 +146,41 @@ const CreateModelParams: React.FC<CreateModelParamsProps> = (props) => {
), ),
}} }}
onFinish={async (values: any) => { onFinish={async (values: any) => {
setFileList([]); console.log(values, 'values');
let formData = formRef.current?.getFieldsValue();
if (formData?.modelFkId) {
await waitTime(500);
formData.modelConfig = { params: values?.params || [] };
if (filePath) {
formData.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; return true;
}} }}
> >
<ProFormUploadDragger <FormUploadDraggerToken
width={proFormSmallItemStyleProps.width} proFieldProps={{
title={ label: (
<div className="flex">
<span className="font-bold"></span>
<div style={{ color: '#666666' }}>zip.tar.gz</div>
</div>
),
title: (
<div className="gn_uploadfile_title py-[16px] text1 text-center"> <div className="gn_uploadfile_title py-[16px] text1 text-center">
<span></span> <span></span>
<a></a> <a></a>
</div> </div>
} ),
description="" description: '',
icon={<i className="iconfont icon-shangchuanwenjian text_primary text-[32px]"></i>} icon: <i className="iconfont icon-shangchuanwenjian text_primary text-[32px]"></i>,
max={1} name: 'busi_conf_file_arr',
label={<span className="font-bold"></span>} max: 1,
value={fileList} }}
name="dragger" afterUploadFile={({ resp }) => {
fieldProps={{ setCurrFormData((data) => {
className: 'gn_proFormUploadDragger_formItem', return { ...data, busi_conf_file: resp?.data?.result };
onChange: handleFileChange,
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; afterRemoveFile={() => {
}) setCurrFormData((data) => {
.catch(() => { return { ...data, busi_conf_file: '' };
return false;
}); });
}
},
}} }}
openPreviewFile={true}
/> />
<div style={{ color: '#666666', margin: '-8px 0 16px' }}>
zip.tar.gz
</div>
{/* // TODO label字重与上面统一, 操作按钮需要与输入框对齐 */}
<ProFormList
name="params"
label={
<div>
<span className="font-bold"></span>
<div style={{ color: '#333333', padding: '8px 0 4px' }}>
~
</div>
</div>
}
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.StepForm>
{/* 运行库选择 runtimeLib */} {/* 运行库选择 runtimeLib */}
<StepsForm.StepForm<{ <StepsForm.StepForm<{
@ -290,8 +207,8 @@ const CreateModelParams: React.FC<CreateModelParamsProps> = (props) => {
<ProForm.Group> <ProForm.Group>
<ProFormText <ProFormText
width={proFormSmallItemStyleProps.column2Width - 30} width={proFormSmallItemStyleProps.column2Width - 30}
name="ip" name="host"
initialValue={'http://127.0.0.1'} initialValue={'192.168.10.94'}
label={ label={
<FormattedMessage id="model_runtimeLib.list.table.form.IP" defaultMessage="IP地址" /> <FormattedMessage id="model_runtimeLib.list.table.form.IP" defaultMessage="IP地址" />
} }
@ -318,7 +235,7 @@ const CreateModelParams: React.FC<CreateModelParamsProps> = (props) => {
<ProFormText <ProFormText
width={proFormSmallItemStyleProps.column2Width - 30} width={proFormSmallItemStyleProps.column2Width - 30}
name="port" name="port"
initialValue={'80'} initialValue={'5000'}
label={ label={
<FormattedMessage id="model_runtimeLib.list.table.form.port" defaultMessage="端口" /> <FormattedMessage id="model_runtimeLib.list.table.form.port" defaultMessage="端口" />
} }
@ -354,8 +271,8 @@ const CreateModelParams: React.FC<CreateModelParamsProps> = (props) => {
color: '#154ddd', color: '#154ddd',
}} }}
onClick={() => { onClick={() => {
const { ip, port } = formRef.current?.getFieldsValue(); const { host, port } = formRef.current?.getFieldsValue();
if (ip && port) { if (host && port) {
// 访问接口拿数据 // 访问接口拿数据
setOpenFiles(true); setOpenFiles(true);
} else { } else {
@ -369,7 +286,7 @@ const CreateModelParams: React.FC<CreateModelParamsProps> = (props) => {
{openFiles ? ( {openFiles ? (
<ProFormSelect <ProFormSelect
width={proFormSmallItemStyleProps.width} width={proFormSmallItemStyleProps.width}
name="fileName" name="model_hub_image"
placeholder={`${intl.formatMessage({ placeholder={`${intl.formatMessage({
id: 'common.please_select', id: 'common.please_select',
defaultMessage: '$$$', defaultMessage: '$$$',
@ -381,9 +298,13 @@ const CreateModelParams: React.FC<CreateModelParamsProps> = (props) => {
showSearch showSearch
debounceTime={500} debounceTime={500}
request={async () => { request={async () => {
const { data } = await getModelRuntimeLibFilesList(); const { host, port } = formRef.current?.getFieldsValue();
const { data } = await apiModelHubSync({
host,
port,
});
return data?.data?.map((v: Record<string, any>) => { return data?.data?.map((v: Record<string, any>) => {
return { ...v, label: v.name, value: v.id }; return { ...v, label: v, value: v };
}); });
}} }}
rules={[ rules={[
@ -418,122 +339,41 @@ const CreateModelParams: React.FC<CreateModelParamsProps> = (props) => {
), ),
}} }}
onFinish={async (values: any) => { onFinish={async (values: any) => {
setFileList([]); console.log(values, 'values');
let formData = formRef.current?.getFieldsValue();
if (formData?.modelFkId) {
await waitTime(500);
formData.modelConfig = { params: values?.params || [] };
if (filePath) {
formData.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; return true;
}} }}
> >
{/* // TODO 上传文案需要和UI稿对比 */} <FormUploadDraggerToken
<ProFormUploadDragger proFieldProps={{
width={proFormSmallItemStyleProps.width} label: (
max={1} <div className="flex">
label={<span className="font-bold"></span>} <span className="font-bold"></span>
title={ <div style={{ color: '#666666' }}>zip.tar.gz</div>
</div>
),
title: (
<div className="gn_uploadfile_title py-[16px] text1 text-center"> <div className="gn_uploadfile_title py-[16px] text1 text-center">
<span></span> <span></span>
<a></a> <a></a>
</div> </div>
} ),
description="" description: '',
icon={<i className="iconfont icon-shangchuanwenjian text_primary text-[32px]"></i>} icon: <i className="iconfont icon-shangchuanwenjian text_primary text-[32px]"></i>,
value={fileList} name: 'model_conf_file_arr',
name="dragger" max: 1,
fieldProps={{ }}
className: 'gn_proFormUploadDragger_formItem', afterUploadFile={({ resp }) => {
onChange: handleFileChange, setCurrFormData((data) => {
onRemove: () => { return { ...data, model_conf_file: resp?.data?.result };
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; afterRemoveFile={() => {
}) setCurrFormData((data) => {
.catch(() => { return { ...data, model_conf_file: '' };
return false;
}); });
}
},
}} }}
openPreviewFile={true}
/> />
<div style={{ color: '#666666', margin: '-8px 0 16px' }}>
zip.tar.gz
</div>
{/* // TODO label字重与上面统一, 操作按钮需要与输入框对齐 */}
<ProFormList
name="params"
label={
<div>
<span className="font-bold"></span>
<div style={{ color: '#333333', padding: '8px 0 4px' }}>
~
</div>
</div>
}
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.StepForm>
</StepsForm> </StepsForm>
); );

@ -314,7 +314,11 @@ const DeviceList: React.FC<DeviceListProps> = (props) => {
size={16} size={16}
title="模型列表" title="模型列表"
></InnerPageBack> ></InnerPageBack>
<ModelSetting info={currentRow}></ModelSetting> <ModelSetting
info={currentRow}
commInfo={props.commInfo}
nodeInfo={props.nodeInfo}
></ModelSetting>
</> </>
) : ( ) : (
<></> <></>

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd * @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-30 10:02:29 * @Date: 2024-04-30 10:02:29
* @LastEditors: donghao donghao@supervision.ltd * @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-06-19 16:07:50 * @LastEditTime: 2024-06-20 10:29:40
* @FilePath: \general-ai-platform-web\src\pages\Business\DeviceGroup\components\modelSetting.tsx * @FilePath: \general-ai-platform-web\src\pages\Business\DeviceGroup\components\modelSetting.tsx
* @Description: * @Description:
* @ * @
@ -22,6 +22,8 @@ import CreateModelParams from './createModelParams';
type ModelSettingProps = { type ModelSettingProps = {
info: Record<string, any>; info: Record<string, any>;
commInfo: Record<string, any>;
nodeInfo: Record<string, any>;
}; };
const ModelSetting: React.FC<ModelSettingProps> = (props) => { const ModelSetting: React.FC<ModelSettingProps> = (props) => {
@ -33,7 +35,7 @@ const ModelSetting: React.FC<ModelSettingProps> = (props) => {
const [createModalOpen, setCreateModalOpen] = useState<boolean>(false); const [createModalOpen, setCreateModalOpen] = useState<boolean>(false);
// const [categoryFkIdIds, setCategoryFkIdIds] = useState([]); // const [categoryFkIdIds, setCategoryFkIdIds] = useState([]);
// 动态设置每页数量 // 动态设置每页数量
// const [currentRow, setCurrentRow] = useState<Record<string, any>>({}); const [currentRow, setCurrentRow] = useState<Record<string, any>>({});
/**配置参数 */ /**配置参数 */
const handleCreateModal = () => { const handleCreateModal = () => {
@ -88,7 +90,7 @@ const ModelSetting: React.FC<ModelSettingProps> = (props) => {
valueType: 'option', valueType: 'option',
fixed: 'right', fixed: 'right',
key: 'option', key: 'option',
render: () => [ render: (_, record) => [
<TableActionCard <TableActionCard
key="TableActionCardRef" key="TableActionCardRef"
renderActions={[ renderActions={[
@ -100,6 +102,11 @@ const ModelSetting: React.FC<ModelSettingProps> = (props) => {
type="link" type="link"
size="small" size="small"
onClick={() => { onClick={() => {
setCurrentRow({
...record,
base_model_id: record.model_id,
busi_model_id: record?.parentInfo?.busi_model_id,
});
handleCreateModal(); handleCreateModal();
}} }}
> >
@ -150,7 +157,12 @@ const ModelSetting: React.FC<ModelSettingProps> = (props) => {
persistenceKey: 'algorithm_model_list', persistenceKey: 'algorithm_model_list',
persistenceType: 'localStorage', persistenceType: 'localStorage',
}} }}
dataSource={item.base_models} dataSource={item.base_models.map((baseModelItem) => {
const { base_models, ...restInfo } = item;
console.log(base_models, 'base_models');
baseModelItem.parentInfo = restInfo;
return baseModelItem;
})}
columns={columns} columns={columns}
/> />
</div> </div>
@ -203,7 +215,7 @@ const ModelSetting: React.FC<ModelSettingProps> = (props) => {
overflow: 'scroll', overflow: 'scroll',
}, },
}} }}
rowKey="id" rowKey="model_id"
dataSource={modelData} dataSource={modelData}
pagination={false} pagination={false}
rowSelection={false} rowSelection={false}
@ -216,6 +228,10 @@ const ModelSetting: React.FC<ModelSettingProps> = (props) => {
<CreateModelParams <CreateModelParams
createModalOpen={createModalOpen} createModalOpen={createModalOpen}
handleModal={handleCreateModal} handleModal={handleCreateModal}
info={currentRow}
deviceInfo={props.info}
commInfo={props.commInfo}
nodeInfo={props.nodeInfo}
reload={reloadList} reload={reloadList}
/> />
</div> </div>

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd * @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-07 14:02:00 * @Date: 2024-04-07 14:02:00
* @LastEditors: donghao donghao@supervision.ltd * @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-06-18 15:05:13 * @LastEditTime: 2024-06-20 17:14:13
* @FilePath: \general-ai-manage\src\pages\Log\index.tsx * @FilePath: \general-ai-manage\src\pages\Log\index.tsx
* @Description: * @Description:
* @ * @
@ -14,7 +14,8 @@ import { isSuccessApi } from '@/utils/forApi';
import { ReactComponent as ResetIcon } from '/public/home/reset_icon.svg'; import { ReactComponent as ResetIcon } from '/public/home/reset_icon.svg';
import { ReactComponent as SearchIcon } from '/public/home/search_icon.svg'; import { ReactComponent as SearchIcon } from '/public/home/search_icon.svg';
import { getServerLogList } from '@/services/testApi/serverLog'; import { apiSystemLog, apiUsers } from '@/services/business/system';
import { mathConvertJoinArrayToString } from '@/utils/forMath';
import type { ActionType, ProColumns } from '@ant-design/pro-components'; import type { ActionType, ProColumns } from '@ant-design/pro-components';
import { import {
ProCard, ProCard,
@ -47,14 +48,14 @@ const LogIndex: React.FC = () => {
const columns: ProColumns<Record<string, any>>[] = [ const columns: ProColumns<Record<string, any>>[] = [
{ {
title: <FormattedMessage id="server_log.table.list.name" defaultMessage="$$$" />, title: <FormattedMessage id="server_log.table.list.name" defaultMessage="$$$" />,
dataIndex: 'accountName', dataIndex: 'user',
hideInSearch: true, hideInSearch: true,
key: 'fixedName', key: 'fixedName',
fixed: 'left', fixed: 'left',
}, },
{ {
title: <FormattedMessage id="server_log.table.list.ip" defaultMessage="$$$" />, title: <FormattedMessage id="server_log.table.list.ip" defaultMessage="$$$" />,
dataIndex: 'ipAddress', dataIndex: 'ip',
hideInSearch: true, hideInSearch: true,
}, },
{ {
@ -66,17 +67,17 @@ const LogIndex: React.FC = () => {
{ {
title: <FormattedMessage id="server_log.table.list.action" defaultMessage="$$$" />, title: <FormattedMessage id="server_log.table.list.action" defaultMessage="$$$" />,
dataIndex: 'action', dataIndex: 'op_type',
hideInSearch: true, hideInSearch: true,
}, },
{ {
title: <FormattedMessage id="server_log.table.list.remark" defaultMessage="$$$" />, title: <FormattedMessage id="server_log.table.list.remark" defaultMessage="$$$" />,
dataIndex: 'logContent', dataIndex: 'content',
hideInSearch: true, hideInSearch: true,
render: (dom) => { render: (dom) => {
return ( return (
<Tooltip title={dom} trigger="hover"> <Tooltip title={dom} trigger="hover">
<div className="cursor-pointer single_line">{dom}</div>; <div className="cursor-pointer single_line">{dom}</div>
</Tooltip> </Tooltip>
); );
}, },
@ -136,7 +137,7 @@ const LogIndex: React.FC = () => {
<ProFormSelect <ProFormSelect
label={<FormattedMessage id="server_log.table.list.name" defaultMessage="账号" />} label={<FormattedMessage id="server_log.table.list.name" defaultMessage="账号" />}
mode="multiple" mode="multiple"
name="name" name="user"
debounceTime={1000} debounceTime={1000}
fieldProps={{ fieldProps={{
style: { style: {
@ -144,20 +145,16 @@ const LogIndex: React.FC = () => {
}, },
}} }}
request={async () => { request={async () => {
// const resp = await postCurrentIP(); const { data } = await apiUsers();
const resp = ['用户A', '用户B', '用户C']; return data?.data?.map((v: Record<string, any>) => {
return resp?.map((v: any) => { return { ...v, label: v, value: v };
return {
label: v,
value: v,
};
}); });
}} }}
/> />
<ProForm.Item style={{ marginLeft: '12px' }}> <ProForm.Item style={{ marginLeft: '12px' }}>
<ProFormDateRangePicker <ProFormDateRangePicker
style={{ marginLeft: '16px' }} // 设置左侧间距为16px style={{ marginLeft: '16px' }} // 设置左侧间距为16px
name="dateRange" name="date"
label="日期" label="日期"
fieldProps={{ fieldProps={{
style: { style: {
@ -218,8 +215,6 @@ const LogIndex: React.FC = () => {
const { current, ...rest } = params; const { current, ...rest } = params;
const reqParams = { const reqParams = {
pageNo: current, pageNo: current,
desc: false,
orderKey: '',
...rest, ...rest,
}; };
if (sort && Object.keys(sort).length) { if (sort && Object.keys(sort).length) {
@ -227,8 +222,13 @@ const LogIndex: React.FC = () => {
let sort_select = sort[reqParams.orderKey]; let sort_select = sort[reqParams.orderKey];
reqParams.desc = sort_select === 'descend'; reqParams.desc = sort_select === 'descend';
} }
let resp = await getServerLogList({ ...reqParams, ...querysData }); let resp = await apiSystemLog({
console.log(resp, 'getServerLogList_resp'); ...reqParams,
user: mathConvertJoinArrayToString(querysData?.user),
startDate: querysData?.date?.[0],
endDate: querysData?.date?.[1],
});
console.log(resp, 'apiSystemLog_resp');
if (!isSuccessApi(resp)) { if (!isSuccessApi(resp)) {
return { data: [], success: true }; return { data: [], success: true };
} }

@ -365,12 +365,12 @@ export async function apiEntityNodesDeviceModels(body: any, options?: { [key: st
} }
// 企业节点,节点信息 -> 设备列表 -> 基础模型配置 -> 基础模型参数配置 // 企业节点,节点信息 -> 设备列表 -> 基础模型配置 -> 基础模型参数配置
export async function apiEntityNodesDeviceModelCustomConfig( export async function apiEntityNodesDeviceBasemodelCustomConfig(
body: any, body: any,
options?: { [key: string]: any }, options?: { [key: string]: any },
) { ) {
return request<API.Response & { data?: API.ENTITY_INDEX_DATA; msg?: string }>( return request<API.Response & { data?: API.ENTITY_INDEX_DATA; msg?: string }>(
`/api/v1/enterprise/entity/nodes/device/model/custom/config`, `/api/v1/enterprise/entity/nodes/device/basemodel/custom/config`,
{ {
method: 'POST', method: 'POST',
headers: { headers: {

@ -0,0 +1,99 @@
// @ts-ignore
/* eslint-disable */
import { request } from '@umijs/max';
/**企业服务器 */
// 新建服务器
export async function apiServerAdd(body: any, options?: { [key: string]: any }) {
return request<API.Response & { data?: API.ENTITY_INDEX_DATA; msg?: string }>(
`/api/v1/enterprise/server/add`,
{
method: 'POST',
headers: {
// 'Content-Type': 'application/json',
// "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
},
data: body,
...(options || {}),
},
);
}
// 编辑服务器
export async function apiServerEdit(body: any, options?: { [key: string]: any }) {
return request<API.Response & { data?: API.ENTITY_INDEX_DATA; msg?: string }>(
`/api/v1/enterprise/server/edit`,
{
method: 'POST',
headers: {
// 'Content-Type': 'application/json',
// "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
},
data: body,
...(options || {}),
},
);
}
// 删除服务器
export async function apiServerDelete(body: any, options?: { [key: string]: any }) {
return request<API.Response & { data?: API.ENTITY_INDEX_DATA; msg?: string }>(
`/api/v1/enterprise/server/delete`,
{
method: 'POST',
headers: {
// 'Content-Type': 'application/json',
// "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
},
data: body,
...(options || {}),
},
);
}
// 服务器列表
export async function apiServerList(body: any, options?: { [key: string]: any }) {
return request<API.Response & { data?: API.ENTITY_INDEX_DATA; msg?: string }>(
`/api/v1/enterprise/server/list`,
{
method: 'POST',
headers: {
// 'Content-Type': 'application/json',
// "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
},
data: body,
...(options || {}),
},
);
}
// 服务器信息
export async function apiServerInfo(body: any, options?: { [key: string]: any }) {
return request<API.Response & { data?: API.ENTITY_INDEX_DATA; msg?: string }>(
`/api/v1/enterprise/server/info`,
{
method: 'POST',
headers: {
// 'Content-Type': 'application/json',
// "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
},
data: body,
...(options || {}),
},
);
}
// 服务器日志列表
export async function apiServerLog(body: any, options?: { [key: string]: any }) {
return request<API.Response & { data?: API.ENTITY_INDEX_DATA; msg?: string }>(
`/api/v1/enterprise/server/log`,
{
method: 'POST',
headers: {
// 'Content-Type': 'application/json',
// "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
},
data: body,
...(options || {}),
},
);
}

@ -0,0 +1,43 @@
/*
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-06-20 16:08:31
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-06-20 16:12:41
* @FilePath: \general-ai-platform-web\src\services\business\system.ts
* @Description: system api
*/
// @ts-ignore
/* eslint-disable */
import { request } from '@umijs/max';
/**系统管理 */
// 日志服务
export async function apiSystemLog(body: any, options?: { [key: string]: any }) {
return request<API.Response & { data?: API.ENTITY_INDEX_DATA; msg?: string }>(
`/api/v1/system/log`,
{
method: 'POST',
headers: {
// 'Content-Type': 'application/json',
// "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
},
data: body,
...(options || {}),
},
);
}
// 日志服务
export async function apiUsers(body: any, options?: { [key: string]: any }) {
return request<API.Response & { data?: API.ENTITY_INDEX_DATA; msg?: string }>(`/api/v1/users`, {
method: 'POST',
headers: {
// 'Content-Type': 'application/json',
// "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
},
data: body,
...(options || {}),
});
}

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd * @Author: donghao donghao@supervision.ltd
* @Date: 2024-06-18 13:36:03 * @Date: 2024-06-18 13:36:03
* @LastEditors: donghao donghao@supervision.ltd * @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-06-19 14:34:55 * @LastEditTime: 2024-06-20 16:22:01
* @FilePath: \general-ai-platform-web\src\utils\math.ts * @FilePath: \general-ai-platform-web\src\utils\math.ts
* @Description: * @Description:
*/ */
@ -32,6 +32,18 @@ export function mathConvertCommaSeparatedStringToArray(inputString: string): str
return []; return [];
} }
/**
* @
* @param inputArr string[]
* @returns
*/
export function mathConvertJoinArrayToString(inputArr: string[]): string {
if (Array.isArray(inputArr)) {
return inputArr.join(',');
}
return '';
}
/** /**
* Function to extract 'id' properties from an array of objects. * Function to extract 'id' properties from an array of objects.
* *

Loading…
Cancel
Save