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

develop2
donghao 1 year ago
parent 120b162a40
commit a00eeb2ffd

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-28 15:30:31
* @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
* @Description:
*/
@ -14,12 +14,12 @@ export const serverStateEnums: DICTENUM.DICT_TAB_ITEM[] = [
},
{
label: '在线',
key: '1',
key: '1001',
className: 'online_info',
},
{
label: '离线',
key: '2',
key: '1002',
className: 'outline_info',
},
];

@ -2,14 +2,15 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-05-09 15:21:03
* @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
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
// 服务器状态
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.form.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 { FormattedMessage, useIntl } from '@umijs/max';
import { Form } from 'antd';
import { Form, message } from 'antd';
import React from 'react';
import {
proFormSmallItemStyleProps,
proFormSmallModelWidth,
} from '../../../../../config/defaultForm';
export type CreateDeviceFormProps = {
export type CreateServerFormProps = {
createModalOpen: boolean;
handleModal: () => void;
commInfo: Record<string, any>;
reload: any;
};
const CreateServerForm: React.FC<CreateDeviceFormProps> = (props) => {
const CreateServerForm: React.FC<CreateServerFormProps> = (props) => {
const intl = useIntl();
const [form] = Form.useForm<API.ModelCategory>();
@ -21,7 +24,7 @@ const CreateServerForm: React.FC<CreateDeviceFormProps> = (props) => {
className="gn_modal_form gn_form"
width={proFormSmallModelWidth}
title={intl.formatMessage({
id: 'server_state.create.form.add',
id: 'server_state.create.form.action.add',
defaultMessage: '新建',
})}
open={props.createModalOpen}
@ -33,8 +36,23 @@ const CreateServerForm: React.FC<CreateDeviceFormProps> = (props) => {
}}
submitTimeout={2000}
onFinish={async (values) => {
console.log(values, 'add_finish_values');
// TODO 对接新增接口
console.log(values, 'apiServerAdd_values');
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();
return true;
}}
@ -67,6 +85,7 @@ const CreateServerForm: React.FC<CreateDeviceFormProps> = (props) => {
<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',
@ -79,7 +98,7 @@ const CreateServerForm: React.FC<CreateDeviceFormProps> = (props) => {
<ProFormText
width={proFormSmallItemStyleProps.column2Width}
name="userName"
name="username"
label={<FormattedMessage id="server_state.table.form.userName" defaultMessage="用户名" />}
placeholder={`${intl.formatMessage({
id: 'common.please_input',
@ -92,7 +111,7 @@ const CreateServerForm: React.FC<CreateDeviceFormProps> = (props) => {
<ProFormText.Password
width={proFormSmallItemStyleProps.column2Width}
label={<FormattedMessage id="server_state.table.form.pwd" defaultMessage="密码" />}
name="pwd"
name="passwd"
placeholder={`${intl.formatMessage({
id: 'common.please_input',
defaultMessage: '$$$',
@ -104,7 +123,8 @@ const CreateServerForm: React.FC<CreateDeviceFormProps> = (props) => {
<ProFormText
width={proFormSmallItemStyleProps.width}
name="defaultPort"
name="port"
initialValue={8080}
label={
<FormattedMessage id="server_state.table.form.defaultPort" defaultMessage="默认端口" />
}

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-08 16:57:30
* @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
* @Description:
* @
@ -19,11 +19,17 @@ import { proFormMaxModelWidth } from '../../../../../config/defaultForm';
import DetailServerStateLog from './detailServerStateLog';
type DetailServerStateProps = {
info: Record<string, any>;
commInfo: Record<string, any>;
detailOpen: boolean;
closeModal: () => void;
};
const DetailServerState: React.FC<DetailServerStateProps> = ({ info, detailOpen, closeModal }) => {
const DetailServerState: React.FC<DetailServerStateProps> = ({
info,
commInfo,
detailOpen,
closeModal,
}) => {
/**state */
const intl = useIntl();
const [tabKey, setTabKey] = useState<string>(bsServerDetailEnums[0].key);
@ -35,11 +41,11 @@ const DetailServerState: React.FC<DetailServerStateProps> = ({ info, detailOpen,
const ModelDetailColumns = [
{
title: <FormattedMessage id="server_state.table.form.name" defaultMessage="服务器名称" />,
dataIndex: 'deviceSort',
dataIndex: 'name',
},
{
title: <FormattedMessage id="server_state.table.form.ip" defaultMessage="IP" />,
dataIndex: 'IP',
dataIndex: 'ip',
},
{
title: (
@ -49,34 +55,35 @@ const DetailServerState: React.FC<DetailServerStateProps> = ({ info, detailOpen,
},
{
title: <FormattedMessage id="server_state.table.form.userName" defaultMessage="用户名" />,
dataIndex: 'userName',
},
{
title: <FormattedMessage id="server_state.table.form.pwd" defaultMessage="密码" />,
dataIndex: 'pwd',
render: () => {
return '*********';
},
dataIndex: 'username',
},
// {
// title: <FormattedMessage id="server_state.table.form.pwd" defaultMessage="密码" />,
// dataIndex: 'passwd',
// render: () => {
// return '*********';
// },
// },
];
// TODO 切换详情展示,未能渲染出来信息环形图
// 硬件信息环形图
const fetchOptionByData = (record) => {
const totalCount = 100 * Math.floor(Math.random() * 15);
const totalCount = 100;
const currData = [
{
value: record?.percent * totalCount,
name: `${intl.formatMessage({
id: 'server_state.table.detail.echarts.used',
defaultMessage: '已占用',
})}${record?.percent * 100}%`,
})}${Math.floor(record?.percent * totalCount)}%`,
},
{
value: totalCount - record?.percent * totalCount,
name: `${intl.formatMessage({
id: 'server_state.table.detail.echarts.free',
defaultMessage: '未占用',
})}${100 - record?.percent * 100}%`,
})}${100 - Math.floor(record?.percent * totalCount)}%`,
},
];
@ -96,7 +103,7 @@ const DetailServerState: React.FC<DetailServerStateProps> = ({ info, detailOpen,
},
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b} : {c} ({d}%)',
formatter: '{a} <br/>{b}',
},
legend: {
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(() => {
setForceRender(detailOpen);
}, [detailOpen]);
// 初始化加载
// useEffect(() => {
// fetchData();
// }, []);
return (
<Modal
width={proFormMaxModelWidth}
title={info?.deviceSort}
title={info?.name}
open={detailOpen}
onCancel={closeModal}
footer={null}
@ -282,7 +199,7 @@ const DetailServerState: React.FC<DetailServerStateProps> = ({ info, detailOpen,
</p>
<div className="mb-[8px] mt-[12px] gn_active_descriptions gn_descriptions bg_active_4">
<ProDescriptions
column={5}
column={4}
columns={ModelDetailColumns}
dataSource={info}
></ProDescriptions>
@ -315,52 +232,11 @@ const DetailServerState: React.FC<DetailServerStateProps> = ({ info, detailOpen,
})}
</ul>
</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>
</ProCard>
</div>
)}
{tabKey === '1' && <DetailServerStateLog />}
{tabKey === '1' && <DetailServerStateLog commInfo={commInfo} />}
</ProCard>
</Modal>
);

@ -2,21 +2,24 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-22 15:23:36
* @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
* @Description:
* @
* 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 { ProCard, ProTable } from '@ant-design/pro-components';
import { FormattedMessage } from '@umijs/max';
import { useRef, useState } from 'react';
import { proTablePaginationOptions } from '../../../../../config/defaultTable';
const DetailServerStateLog: React.FC = () => {
type DetailServerStateLogProps = {
commInfo: Record<string, any>;
};
const DetailServerStateLog: React.FC<DetailServerStateLogProps> = (props) => {
const actionRef = useRef<ActionType>();
// 动态设置每页数量
const [currentPageSize, setCurrentPageSize] = useState<number>(10);
@ -24,7 +27,7 @@ const DetailServerStateLog: React.FC = () => {
const columns: ProColumns<Record<string, any>>[] = [
{
title: <FormattedMessage id="server_state.table.stateLog.list.ip" defaultMessage="名称" />,
dataIndex: 'IP',
dataIndex: 'ip',
hideInSearch: true,
key: 'fixedName',
fixed: 'left',
@ -74,11 +77,15 @@ const DetailServerStateLog: React.FC = () => {
request={async (params = {}) => {
const { current, ...rest } = params;
const reqParams = {
entity_id: props?.commInfo?.id,
pageNo: current,
...rest,
};
let resp = await getServerStateLogList({ ...reqParams });
console.log(resp, 'getServerStateLogList_resp');
let resp = await apiServerLog({ ...reqParams });
console.log(resp, 'apiServerLog_resp');
if (!isSuccessApi(resp)) {
return { data: [], success: true };
}
return {
data: resp.data?.data,
success: resp.success,

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-08 16:57:30
* @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
* @Description:
*/
@ -25,7 +25,7 @@ const ServerStateCard: React.FC<ServerStateCardProps> = ({ info, renderActions,
// 动效类型
const fetchAnimatePicByType = () => {
switch (info?.state) {
switch (Number(info?.status)) {
case '1':
return <AnimatePic value={onlineAnimateJson} />;
default:
@ -41,16 +41,16 @@ const ServerStateCard: React.FC<ServerStateCardProps> = ({ info, renderActions,
}}
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 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
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>
<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
* @Date: 2024-05-10 10:47:45
* @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
* @Description:
* @
@ -235,11 +235,6 @@ const DeviceSate: React.FC = () => {
setCurrentPage(1);
console.log(key);
};
// function reloadList() {
// setTabKey('0');
// setCurrentPage(1);
// }
// 设备节点树
async function loadDeviceTree() {
const resp = await apiEntityNodes({ entity_id: commInfo.id });
@ -247,7 +242,6 @@ const DeviceSate: React.FC = () => {
setDeviceTreeList(resp?.data?.data);
}
}
// 初始化加载 & 筛选查询
useEffect(() => {
fetchData();
@ -312,13 +306,6 @@ const DeviceSate: React.FC = () => {
id: 'device_group_list.table.list.deviceNode',
defaultMessage: '节点',
})}`}
// treeData={deviceTreeList}
// fieldNames= {{
// label: 'name',
// value: 'id',
// children: 'children',
// }}
fieldProps={{
multiple: true,
treeData: deviceTreeList,

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-05-07 13:38:03
* @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
* @Description: businessStatebs
* @
@ -12,20 +12,27 @@
import { CommButton, TextButton } from '@/components/Button';
import IsDelete from '@/components/TableActionCard/isDelete';
import { serverStateEnums } from '@/enums/server';
import { getServerStateList } from '@/services/testApi/businessState';
import { useBusinessInfo } from '@/hooks/useBusinessInfo';
import { isSuccessApi } from '@/utils/forApi';
import { mathSumByNumberArr } from '@/utils/forMath';
import { ProCard, ProList } from '@ant-design/pro-components';
import { FormattedMessage } from '@umijs/max';
import { Tabs } from 'antd';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Tabs, message } from 'antd';
import { useEffect, useState } from 'react';
import { proTablePaginationOptions } from '../../../../config/defaultTable';
import CreateServerForm from './components/createServerForm';
import DetailServerState from './components/detailServerState';
import ServerStateCard from './components/serverStateCard';
import UpdateServerForm from './components/updateServerForm';
import './index.less';
import { apiServerDelete, apiServerInfo, apiServerList } from '@/services/business/server';
const BusinessState: React.FC = () => {
/**state */
const intl = useIntl();
const { getStoreBusinessInfo } = useBusinessInfo();
const [commInfo] = useState<Record<string, any>>({ ...getStoreBusinessInfo() }); // 通用信息
// 列表
const [serverList, setServerList] = 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 [total, setTotal] = useState<number>(1);
const [createModalOpen, setCreateModalOpen] = useState<boolean>(false);
const [updateModalOpen, setUpdateModalOpen] = useState<boolean>(false);
// 详情展示
const [detailOpen, setDetailOpen] = useState<boolean>(false);
@ -43,16 +52,70 @@ const BusinessState: React.FC = () => {
const handleCreateModal = () => {
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
function toListDomByData(record) {
let startList = [...record];
startList = startList.map((item) => {
item.progressData = toProgressListByItem(item);
return item;
});
let finalList = startList.map((item) => ({
content: (
<ServerStateCard
info={item}
fetchDetail={() => {
setCurrentRow(item);
loadDetail(item);
setDetailOpen(true);
}}
renderActions={[
@ -62,7 +125,9 @@ const BusinessState: React.FC = () => {
<span
onClick={(e) => {
e.stopPropagation();
setCurrentRow(item);
// setCurrentRow(item);
loadDetail(item);
setUpdateModalOpen(true);
console.log('编辑');
}}
>
@ -94,8 +159,17 @@ const BusinessState: React.FC = () => {
></TextButton>
}
deleteApi={() => {
// TODO 调用删除接口
// handleDestroy(record).then(() => {});
console.log('删除成功');
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>
@ -111,25 +185,29 @@ const BusinessState: React.FC = () => {
// 企业列表数据api
async function fetchData() {
const resp = await getServerStateList({
const resp = await apiServerList({
pageNo: currentPage,
pageSize: currentPageSize,
status: tabKey,
status: Number(tabKey),
entity_id: commInfo.id,
});
if (isSuccessApi(resp)) {
toListDomByData(resp.data.data);
const currCounts = { ...resp.data.status };
const currTotalCount = mathSumByNumberArr(Object.values(currCounts));
setTabs(() => {
const finalArr = [];
JSON.parse(JSON.stringify(serverStateEnums)).forEach((item) => {
switch (item.key) {
case '0':
item.label = `${serverStateEnums[0].label}${resp.data.count}`;
case '1001':
item.label = `${serverStateEnums[1].label}${currCounts[serverStateEnums[1].key]}`;
break;
case '1':
item.label = `${serverStateEnums[1].label}${resp.data.onlineCount}`;
case '1002':
item.label = `${serverStateEnums[2].label}${currCounts[serverStateEnums[2].key]}`;
break;
case '2':
item.label = `${serverStateEnums[2].label}${resp.data.outlineCount}`;
case '0':
default:
item.label = `${serverStateEnums[0].label}${currTotalCount}`;
break;
}
finalArr.push(item);
@ -138,9 +216,9 @@ const BusinessState: React.FC = () => {
});
setTotal(() => {
switch (tabKey) {
case '1':
case '1001':
return resp.data.onlineCount;
case '2':
case '1002':
return resp.data.outlineCount;
default:
return resp.data.count;
@ -157,6 +235,7 @@ const BusinessState: React.FC = () => {
function reloadList() {
setTabKey('0');
setCurrentPage(1);
fetchData();
}
// 初始化加载 & 筛选查询
@ -225,11 +304,20 @@ const BusinessState: React.FC = () => {
<CreateServerForm
createModalOpen={createModalOpen}
handleModal={handleCreateModal}
commInfo={commInfo}
reload={reloadList}
/>
<UpdateServerForm
updateModalOpen={updateModalOpen}
handleModal={handleUpdateModal}
values={currentRow}
commInfo={commInfo}
reload={reloadList}
/>
<DetailServerState
detailOpen={detailOpen}
info={currentRow}
commInfo={commInfo}
closeModal={() => {
setDetailOpen(false);
}}

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-30 10:02:29
* @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
* @Description:
* @
@ -34,6 +34,7 @@ const AlarmSetForm: React.FC<AlarmSetFormProps> = (props) => {
function fetchInitialValues(record) {
const { is_sms, is_email, sms_to, email_to, ...restParams } = record;
console.log(is_sms, 'fetchInitialValues');
form.setFieldsValue({
...restParams,
ways: [
@ -52,18 +53,10 @@ const AlarmSetForm: React.FC<AlarmSetFormProps> = (props) => {
}
async function loadData() {
// TODO 确认入参是否正确
const resp = await apiEntityNodesAlert({ node_id: props.values.node_id });
if (isSuccessApi(resp) && resp?.data) {
fetchInitialValues(resp?.data);
}
fetchInitialValues({
is_sms: 1,
is_email: 0,
sms_to: '用户A',
email_to: '',
freq: 'T',
});
}
useEffect(() => {
loadData();

@ -1,42 +1,34 @@
import { CommButton } from '@/components/Button';
import { getModelRuntimeLibFilesList } from '@/services/testApi/model';
import { FormUploadDraggerToken } from '@/components/UploadFile';
import { apiModelHubSync } from '@/services/business/model';
import {
ProForm,
ProFormInstance,
ProFormList,
ProFormSelect,
ProFormText,
ProFormUploadDragger,
StepsForm,
} 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 { Modal, UploadFile, message } from 'antd';
import yaml from 'js-yaml';
import React, { useEffect, useRef, useState } from 'react';
import { Modal, message } from 'antd';
import React, { useRef, useState } from 'react';
import {
proFormSmallItemStyleProps,
proFormSmallModelWidth,
proFormStepsFormProps,
} from '../../../../../config/defaultForm';
// 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 = {
createModalOpen: boolean;
handleModal: () => void;
values: Partial<API.ModelVersion>;
commInfo: Record<string, any>;
nodeInfo: Record<string, any>;
deviceInfo: Record<string, any>;
reload: any;
currentDefaultFieldsData?: Record<string, any>;
};
const waitTime = (time: number = 100) => {
return new Promise((resolve) => {
@ -45,61 +37,67 @@ const waitTime = (time: number = 100) => {
}, 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 [isHasModelFkId, setIsHasModelFkId] = useState<boolean>(false);
const [dataFormList] = useState<any>([]);
const dataFormListRef = useRef(dataFormList);
const [fileList, setFileList] = useState<UploadFile<any>[]>([]);
const [currFormData, setCurrFormData] = useState<Record<string, any>>({});
// const [form] = Form.useForm<API.ModelVersion>();
const [current, setCurrent] = useState(0);
const formRef = useRef<ProFormInstance>();
const [filePath] = useState('');
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 (
// TODO stepForm 中上传文件新增参数与UI图不一致
<StepsForm<{
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}
current={current}
onCurrentChange={setCurrent}
@ -119,7 +117,6 @@ const CreateModelParams: React.FC<CreateModelParamsProps> = (props) => {
onCancel={() => {
setCurrent(0);
formRef.current?.resetFields();
setFileList([]);
props.handleModal();
}}
open={props.createModalOpen}
@ -149,121 +146,41 @@ const CreateModelParams: React.FC<CreateModelParamsProps> = (props) => {
),
}}
onFinish={async (values: any) => {
setFileList([]);
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;
// });
}
console.log(values, 'values');
return true;
}}
>
<ProFormUploadDragger
width={proFormSmallItemStyleProps.width}
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>}
max={1}
label={<span className="font-bold"></span>}
value={fileList}
name="dragger"
fieldProps={{
className: 'gn_proFormUploadDragger_formItem',
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;
})
.catch(() => {
return false;
});
}
},
}}
/>
<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' }}>
~
<FormUploadDraggerToken
proFieldProps={{
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">
<span></span>
<a></a>
</div>
</div>
}
actionRef={actionFormListRef}
itemContainerRender={(doms) => {
return <ProForm.Group>{doms}</ProForm.Group>;
),
description: '',
icon: <i className="iconfont icon-shangchuanwenjian text_primary text-[32px]"></i>,
name: 'busi_conf_file_arr',
max: 1,
}}
alwaysShowItemLabel
>
{() => {
return (
<>
<ProFormText width={268} key="name" name="name" label="键名" />
<ProFormText width={268} key="default" name="default" label="默认值" />
</>
);
afterUploadFile={({ resp }) => {
setCurrFormData((data) => {
return { ...data, busi_conf_file: resp?.data?.result };
});
}}
</ProFormList>
afterRemoveFile={() => {
setCurrFormData((data) => {
return { ...data, busi_conf_file: '' };
});
}}
openPreviewFile={true}
/>
</StepsForm.StepForm>
{/* 运行库选择 runtimeLib */}
<StepsForm.StepForm<{
@ -290,8 +207,8 @@ const CreateModelParams: React.FC<CreateModelParamsProps> = (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地址" />
}
@ -318,7 +235,7 @@ const CreateModelParams: React.FC<CreateModelParamsProps> = (props) => {
<ProFormText
width={proFormSmallItemStyleProps.column2Width - 30}
name="port"
initialValue={'80'}
initialValue={'5000'}
label={
<FormattedMessage id="model_runtimeLib.list.table.form.port" defaultMessage="端口" />
}
@ -354,8 +271,8 @@ const CreateModelParams: React.FC<CreateModelParamsProps> = (props) => {
color: '#154ddd',
}}
onClick={() => {
const { ip, port } = formRef.current?.getFieldsValue();
if (ip && port) {
const { host, port } = formRef.current?.getFieldsValue();
if (host && port) {
// 访问接口拿数据
setOpenFiles(true);
} else {
@ -369,7 +286,7 @@ const CreateModelParams: React.FC<CreateModelParamsProps> = (props) => {
{openFiles ? (
<ProFormSelect
width={proFormSmallItemStyleProps.width}
name="fileName"
name="model_hub_image"
placeholder={`${intl.formatMessage({
id: 'common.please_select',
defaultMessage: '$$$',
@ -381,9 +298,13 @@ const CreateModelParams: React.FC<CreateModelParamsProps> = (props) => {
showSearch
debounceTime={500}
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 { ...v, label: v.name, value: v.id };
return { ...v, label: v, value: v };
});
}}
rules={[
@ -418,122 +339,41 @@ const CreateModelParams: React.FC<CreateModelParamsProps> = (props) => {
),
}}
onFinish={async (values: any) => {
setFileList([]);
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;
// });
}
console.log(values, 'values');
return true;
}}
>
{/* // TODO 上传文案需要和UI稿对比 */}
<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>}
value={fileList}
name="dragger"
fieldProps={{
className: 'gn_proFormUploadDragger_formItem',
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;
})
.catch(() => {
return false;
});
}
},
}}
/>
<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' }}>
~
<FormUploadDraggerToken
proFieldProps={{
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">
<span></span>
<a></a>
</div>
</div>
}
actionRef={actionFormListRef}
itemContainerRender={(doms) => {
return <ProForm.Group>{doms}</ProForm.Group>;
),
description: '',
icon: <i className="iconfont icon-shangchuanwenjian text_primary text-[32px]"></i>,
name: 'model_conf_file_arr',
max: 1,
}}
alwaysShowItemLabel
>
{() => {
return (
<>
<ProFormText width={268} key="name" name="name" label="键名" />
<ProFormText width={268} key="default" name="default" label="默认值" />
</>
);
afterUploadFile={({ resp }) => {
setCurrFormData((data) => {
return { ...data, model_conf_file: resp?.data?.result };
});
}}
</ProFormList>
afterRemoveFile={() => {
setCurrFormData((data) => {
return { ...data, model_conf_file: '' };
});
}}
openPreviewFile={true}
/>
</StepsForm.StepForm>
</StepsForm>
);

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

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-30 10:02:29
* @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
* @Description:
* @
@ -22,6 +22,8 @@ import CreateModelParams from './createModelParams';
type ModelSettingProps = {
info: Record<string, any>;
commInfo: Record<string, any>;
nodeInfo: Record<string, any>;
};
const ModelSetting: React.FC<ModelSettingProps> = (props) => {
@ -33,7 +35,7 @@ const ModelSetting: React.FC<ModelSettingProps> = (props) => {
const [createModalOpen, setCreateModalOpen] = useState<boolean>(false);
// const [categoryFkIdIds, setCategoryFkIdIds] = useState([]);
// 动态设置每页数量
// const [currentRow, setCurrentRow] = useState<Record<string, any>>({});
const [currentRow, setCurrentRow] = useState<Record<string, any>>({});
/**配置参数 */
const handleCreateModal = () => {
@ -88,7 +90,7 @@ const ModelSetting: React.FC<ModelSettingProps> = (props) => {
valueType: 'option',
fixed: 'right',
key: 'option',
render: () => [
render: (_, record) => [
<TableActionCard
key="TableActionCardRef"
renderActions={[
@ -100,6 +102,11 @@ const ModelSetting: React.FC<ModelSettingProps> = (props) => {
type="link"
size="small"
onClick={() => {
setCurrentRow({
...record,
base_model_id: record.model_id,
busi_model_id: record?.parentInfo?.busi_model_id,
});
handleCreateModal();
}}
>
@ -150,7 +157,12 @@ const ModelSetting: React.FC<ModelSettingProps> = (props) => {
persistenceKey: 'algorithm_model_list',
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}
/>
</div>
@ -203,7 +215,7 @@ const ModelSetting: React.FC<ModelSettingProps> = (props) => {
overflow: 'scroll',
},
}}
rowKey="id"
rowKey="model_id"
dataSource={modelData}
pagination={false}
rowSelection={false}
@ -216,6 +228,10 @@ const ModelSetting: React.FC<ModelSettingProps> = (props) => {
<CreateModelParams
createModalOpen={createModalOpen}
handleModal={handleCreateModal}
info={currentRow}
deviceInfo={props.info}
commInfo={props.commInfo}
nodeInfo={props.nodeInfo}
reload={reloadList}
/>
</div>

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

Loading…
Cancel
Save