feat: 设备状态,节点模型部署模块完成联调

develop2
donghao 10 months ago
parent b55530aa51
commit 120b162a40

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-03-27 14:56:27
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-06-12 14:04:24
* @LastEditTime: 2024-06-17 14:42:27
* @FilePath: \general-ai-manage\config\routes.ts
* @Description:
*/
@ -201,25 +201,25 @@ export default [
component: './404',
},
// test demo
{
path: '/admin',
name: 'admin',
icon: 'crown',
routes: [
{
path: '/admin',
redirect: '/admin/index',
},
{
path: '/admin/index',
name: 'admin-index',
component: './Admin',
},
{
path: '/admin/previewFile',
name: 'admin-preview-file',
component: './Admin/previewFile',
},
],
},
// {
// path: '/admin',
// name: 'admin',
// icon: 'crown',
// routes: [
// {
// path: '/admin',
// redirect: '/admin/index',
// },
// {
// path: '/admin/index',
// name: 'admin-index',
// component: './Admin',
// },
// {
// path: '/admin/previewFile',
// name: 'admin-preview-file',
// component: './Admin/previewFile',
// },
// ],
// },
];

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-01-25 16:53:15
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-04-26 16:35:54
* @LastEditTime: 2024-06-18 09:28:19
* @FilePath: \general-ai-platform-web\mock\deviceGroup.ts
* @Description: mock
*/
@ -18,7 +18,7 @@ import {
import { successMockApiProps } from './typing';
import { fetchCurrPageByList, fetchMockSuccessFullByOther } from './utils/apiMock';
export default {
// 设备组列表分页
// 节点列表分页
'GET /api/device_group/getDeviceGroupList': async (req: Request, res: Response) => {
const { pageNo, pageSize } = req.query;
const resData: successMockApiProps = {
@ -30,7 +30,7 @@ export default {
res.json(resData);
},
// 设备组网点树列表
// 设备点树列表
'GET /api/device_group/setting_data': async (req: Request, res: Response) => {
const resData: successMockApiProps = {
...fetchMockSuccessFullByOther(mockGetDeviceGroupSettingData),
@ -39,14 +39,14 @@ export default {
},
/** 未启用 */
// 设备组网点选项列表
// 设备点选项列表
'GET /api/device_group/getDeviceGroupFkSelect': async (req: Request, res: Response) => {
const resData: successMockApiProps = {
...fetchMockSuccessFullByOther(mockGetDeviceGroupFkSelectData),
};
res.json(resData);
},
// 设备组网点树列表
// 设备点树列表
'GET /api/device_group/getDeviceGroupTree': async (req: Request, res: Response) => {
const resData: successMockApiProps = {
...fetchMockSuccessFullByOther(mockGetDeviceGroupTreeData),
@ -54,7 +54,7 @@ export default {
res.json(resData);
},
// 设备组详情
// 节点详情
'GET /api/device_group/getDeviceGroupById': async (req: Request, res: Response) => {
const { id } = req.query;
let currRes = {};

@ -135,7 +135,7 @@ const fetchDeviceList = () => {
updateTime: generateRandomDateTimeByYear(2023),
isEnable: Math.floor(Math.random() * 8) % 2 === 0,
name: '设备' + (i + 1),
groupName: '设备组0' + ((Math.floor(Math.random() * 8) % 3) + 1),
groupName: '节点0' + ((Math.floor(Math.random() * 8) % 3) + 1),
deviceType: '设备分类' + ((Math.floor(Math.random() * 8) % 4) + 1),
index: i,
provider: '苏胜天',

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-25 15:45:31
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-31 14:28:44
* @LastEditTime: 2024-06-18 09:27:29
* @FilePath: \general-ai-platform-web\mock\pools\deviceGroupData.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
@ -15,7 +15,7 @@
* @Description:
*/
// 设备节点树
// 设备节点树
export const mockGetDeviceGroupSettingData = {
data: [
{
@ -286,7 +286,7 @@ export const mockGetDeviceGroupTreeData = {
},
};
// 设备组列表分页
// 节点列表分页
export const mockGetDeviceGroupListData = {
data: {
data: [
@ -368,7 +368,7 @@ export const mockGetDeviceGroupListData = {
};
/** 未启用 */
// 设备组节点选项列表
// 节点节点选项列表
export const mockGetDeviceGroupFkSelectData = {
data: {
list: [
@ -396,7 +396,7 @@ export const mockGetDeviceGroupFkSelectData = {
},
};
// 设备组详情
// 节点详情
export const mockGetDeviceGroupData1 = {
data: {
deviceGroup: {

@ -2,7 +2,6 @@
.app_page_wrap {
height: calc(100vh);
padding: 0;
/* TODO 替换整体页面背景图 */
.ant-pro-layout .ant-pro-layout-content {
position: relative;
display: flex;

@ -117,7 +117,6 @@ const MenuBar: React.FC<MenuBarProps> = ({ menuData, changeMenu }) => {
</div>
</div>
{/* // TODO 菜单需要补充路由聚焦状态 */}
<div className="w-full menu_center">
<ul className="w-full single_menu_box">
{menuData &&

@ -145,7 +145,9 @@ const BaseTree: React.FC<BaseTreeProps> = (props) => {
return (
<TreeNode
{...node}
title={formatTreeValByNodeKey('title', node)}
title={`${formatTreeValByNodeKey('title', node)}(${
formatTreeValByNodeKey('children', node)?.length
})`}
key={formatTreeValByNodeKey('key', node)}
className={`tree_node_item tree_node_${!node?.parent ? 0 : 1}`}
>
@ -234,25 +236,6 @@ const BaseTree: React.FC<BaseTreeProps> = (props) => {
</Tree>
<div className="tree_node_0">{renderAddAction()}</div>
</div>
{/* <div onClick={handleAddNode}>添加一级节点</div> */}
{/* TODO 使用ProForm */}
{/* <Modal
title={editNodeKey ? '编辑节点' : '新增节点'}
open={visible}
onOk={handleModalOk}
onCancel={handleModalCancel}
>
<Form form={form}>
<Form.Item
name="nodeTitle"
label="节点名称"
rules={[{ required: true, message: '请输入节点名称' }]}
>
<Input />
</Form.Item>
</Form>
</Modal> */}
</div>
);
};

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-06-04 15:14:27
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-06-12 14:40:40
* @LastEditTime: 2024-06-17 14:23:18
* @FilePath: \general-ai-platform-web\src\components\UploadFile\src\FormUploadDraggerToken.tsx
* @Description:
* // TODO 需要支持多文件上传
@ -109,7 +109,7 @@ const FormUploadDraggerToken: React.FC<FormUploadDraggerTokenProps> = (props) =>
// requestDelFile?.(code === 200);
// return code === 200;
};
// TODO 组装初始值
// 组装初始值
return (
<>
<ProFormUploadDragger

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-28 15:30:31
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-10 15:03:03
* @LastEditTime: 2024-06-14 13:54:47
* @FilePath: \general-ai-platform-web\src\enums\device.ts
* @Description:
*/
@ -25,26 +25,26 @@ export const deviceGroupEnums: Record<string, any>[] = [
export const deviceStateEnums: DICTENUM.DICT_TAB_ITEM[] = [
{
label: '全部状态',
key: '0',
key: '1000',
},
{
label: '在线',
key: '1',
key: '1001',
className: 'online_info',
},
{
label: '离线',
key: '2',
key: '1002',
className: 'outline_info',
},
{
label: '运行中',
key: '3',
key: '1003',
className: 'process_info',
},
{
label: '故障',
key: '4',
key: '1004',
className: 'error_info',
},
];

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-07 15:25:23
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-20 15:26:48
* @LastEditTime: 2024-06-17 14:23:43
* @FilePath: \general-ai-manage\src\layouts\HomeLayout.tsx
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
@ -171,7 +171,6 @@ const HomeLayout: React.FC = () => {
</div>
</Header>
{/* 二级菜单 */}
{/* //TODO 按UI图调整二级菜单栏效果 */}
{currRoute?.subMenu && !currRoute?.isHideMenu && (
<div className="mx-[32px] mb-[12px] flex sub_menu_box">
{currRoute.subMenu.map((menuItem, index) => {

@ -27,7 +27,7 @@ export const alarm_setting: { [key: string]: string } = {
'alarm.setting.table.list.update': '编辑告警项',
'alarm.setting.table.rule.required.code': '类别代码为必填项',
'alarm.setting.table.model.alarmStatusSetting': '告警等级',
'alarm.list.table.list.deviceGroup': '设备组',
'alarm.list.table.list.deviceGroup': '节点',
'alarm.list.table.list.alarmTime': '告警时间',
'alarm.setting.table.list.rule.required.name': '请填写告警名称',
};

@ -2,7 +2,7 @@
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-01 13:56:33
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-29 16:06:49
* @LastEditTime: 2024-06-19 11:32:14
* @FilePath: \general-ai-platform-web\src\locales\zh-CN\device.ts
* @Description:
*/
@ -50,6 +50,8 @@ export const device_group_list: { [key: string]: string } = {
'device_group_list.table.list.name': '设备名称',
'device_group_list.table.list.rule.required.name': '请填写设备名称',
'device_group_list.table.list.deviceSite': '设备位置',
'device_group_list.table.list.deviceNode': '节点',
'device_group_list.table.list.deviceType': '设备分类',
'device_group_list.table.list.rule.required.deviceType': '请选择设备分类',
@ -81,13 +83,13 @@ export const device_group_list: { [key: string]: string } = {
// 设备状态
export const device_state: { [key: string]: string } = {
'device_state.table.form.groupName': '设备组',
'device_state.table.form.groupName': '节点',
'device_state.table.form.deviceType': '设备分类',
'device_state.table.form.name': '设备名称',
'device_state.table.form.remark': '备注',
// 日志
'device_state.table.stateLog.list.ip': '设备IP',
'device_state.table.stateLog.list.runTime': '默认端口',
'device_state.table.stateLog.list.runTime': '运行时长',
'device_state.table.stateLog.list.updateTime': '更新时间',
'device_state.table.detail.echarts.used': '已占用',

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-06-11 13:33:07
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-06-12 16:30:51
* @LastEditTime: 2024-06-13 09:51:34
* @FilePath: \general-ai-platform-web\src\pages\Business\BusinessModel\components\detailCard.tsx
* @Description:
*/
@ -10,7 +10,6 @@
import { isArrayAndNotEmpty } from '@/utils/is';
import { ProCard } from '@ant-design/pro-components';
import { Modal } from 'antd';
import { useEffect, useState } from 'react';
import { proFormSmallModelWidth } from '../../../../../config/defaultForm';
type DetailCardProps = {
info: Record<string, any>;
@ -21,11 +20,6 @@ type DetailCardProps = {
const DetailCard: React.FC<DetailCardProps> = (props) => {
/**state */
// const intl = useIntl();
const [setForceRender] = useState<boolean>(false);
useEffect(() => {
setForceRender(props.detailModalOpen);
}, [props.detailModalOpen]);
return (
<Modal
@ -34,11 +28,6 @@ const DetailCard: React.FC<DetailCardProps> = (props) => {
open={props.detailModalOpen}
onCancel={props.handleModal}
footer={null}
afterVisibleChange={(isVisible) => {
if (!isVisible) {
setForceRender(false); // Modal 关闭时重置状态
}
}}
>
<ProCard className="gn_card_wrap" bodyStyle={{ padding: 0 }}>
<ul className="p1">

@ -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:52:38
* @LastEditTime: 2024-06-19 11:30:46
* @FilePath: \general-ai-manage\src\pages\Project\BusinessProject\components\detailDeviceState.tsx
* @Description:
* @
@ -11,7 +11,12 @@
import { bsDeviceDetailEnums } from '@/enums/device';
import { getModelGroupBaseModelList } from '@/services/testApi/model';
import { isSuccessApi } from '@/utils/forApi';
import { ProCard, ProDescriptions, ProList, ProTable } from '@ant-design/pro-components';
import {
ProCard,
ProDescriptions,
// ProList,
ProTable,
} from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Modal, Tabs } from 'antd';
import * as echarts from 'echarts';
@ -21,27 +26,33 @@ import { proFormMaxModelWidth } from '../../../../../config/defaultForm';
import DetailDeviceStateLog from './detailDeviceStateLog';
type DetailDeviceStateProps = {
info: Record<string, any>;
commInfo: Record<string, any>;
detailOpen: boolean;
closeModal: () => void;
};
const DetailDeviceState: React.FC<DetailDeviceStateProps> = ({ info, detailOpen, closeModal }) => {
const DetailDeviceState: React.FC<DetailDeviceStateProps> = ({
info,
commInfo,
detailOpen,
closeModal,
}) => {
/**state */
const intl = useIntl();
const [tabKey, setTabKey] = useState<string>(bsDeviceDetailEnums[0].key);
const [tabs] = useState<DICTENUM.DICT_TAB_ITEM[]>([...bsDeviceDetailEnums]);
const [modelData, setModelData] = useState<Record<string, any>[]>([]); // 列表数据
// const [modelData, setModelData] = useState<Record<string, any>[]>([]); // 列表数据
const [forceRender, setForceRender] = useState<boolean>(false);
// 基础模型信息
const ModelDetailColumns = [
{
title: <FormattedMessage id="device_state.table.form.groupName" defaultMessage="设备组" />,
dataIndex: 'groupName',
title: <FormattedMessage id="device_state.table.form.groupName" defaultMessage="节点" />,
dataIndex: 'group',
},
{
title: <FormattedMessage id="device_state.table.form.deviceType" defaultMessage="设备分类" />,
dataIndex: 'deviceType',
dataIndex: 'classification',
},
{
title: <FormattedMessage id="device_state.table.form.name" defaultMessage="设备名称" />,
@ -49,27 +60,27 @@ const DetailDeviceState: React.FC<DetailDeviceStateProps> = ({ info, detailOpen,
},
{
title: <FormattedMessage id="device_state.table.form.remark" defaultMessage="备注" />,
dataIndex: 'remark',
dataIndex: 'comment',
},
];
// TODO 切换详情展示,未能渲染出来信息环形图
// 硬件信息环形图
const fetchOptionByData = (record) => {
const totalCount = 100 * Math.floor(Math.random() * 15);
const totalCount = 100;
const currData = [
{
value: record?.percent * totalCount,
value: Math.floor(record?.percent * totalCount),
name: `${intl.formatMessage({
id: 'device_state.table.detail.echarts.used',
defaultMessage: '已占用',
})}${record?.percent * 100}%`,
})}${Math.floor(record?.percent * totalCount)}%`,
},
{
value: totalCount - record?.percent * totalCount,
value: totalCount - Math.floor(record?.percent * totalCount),
name: `${intl.formatMessage({
id: 'device_state.table.detail.echarts.free',
defaultMessage: '未占用',
})}${100 - record?.percent * 100}%`,
})}${100 - Math.floor(record?.percent * totalCount)}%`,
},
];
@ -89,7 +100,7 @@ const DetailDeviceState: React.FC<DetailDeviceStateProps> = ({ info, detailOpen,
},
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b} : {c} ({d}%)',
formatter: '{a} <br/>{b}',
},
legend: {
orient: 'horizontal',
@ -219,7 +230,7 @@ const DetailDeviceState: React.FC<DetailDeviceStateProps> = ({ info, detailOpen,
</div>
),
}));
setModelData(finalList);
// setModelData(finalList);
console.log(finalList, 'toListDomByData_finalList');
}
@ -231,8 +242,14 @@ const DetailDeviceState: React.FC<DetailDeviceStateProps> = ({ info, detailOpen,
}
}
function resetData() {
setTabKey(() => bsDeviceDetailEnums[0].key);
}
useEffect(() => {
setForceRender(detailOpen);
if (!detailOpen) {
resetData();
}
}, [detailOpen]);
// 初始化加载
@ -275,7 +292,7 @@ const DetailDeviceState: React.FC<DetailDeviceStateProps> = ({ info, detailOpen,
</p>
<div className="my-[8px] gn_active_descriptions gn_descriptions bg_active_4">
<ProDescriptions
column={4}
column={3}
columns={ModelDetailColumns}
dataSource={info}
></ProDescriptions>
@ -308,7 +325,8 @@ const DetailDeviceState: React.FC<DetailDeviceStateProps> = ({ info, detailOpen,
})}
</ul>
</li>
<li className="pb-[8px] bs_server_task_wrap">
{/* 暂无数据,隐藏当前任务 */}
{/* <li className="pb-[8px] bs_server_task_wrap">
<p className="head4">
<FormattedMessage
id="device_state.table.detail.title.task"
@ -347,12 +365,12 @@ const DetailDeviceState: React.FC<DetailDeviceStateProps> = ({ info, detailOpen,
}}
/>
</div>
</li>
</li> */}
</ul>
</ProCard>
</div>
)}
{tabKey === '1' && <DetailDeviceStateLog />}
{tabKey === '1' && <DetailDeviceStateLog commInfo={commInfo} />}
</ProCard>
</Modal>
);

@ -2,21 +2,25 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-22 15:23:36
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-10 17:07:15
* @LastEditTime: 2024-06-19 11:33:59
* @FilePath: \general-ai-platform-web\src\pages\Business\BusinessState\components\detailDeviceStateLog.tsx
* @Description:
* @
* 1
*/
import { getDeviceStateLogList } from '@/services/testApi/businessState';
import { apiDeviceStatusLog } from '@/services/business/device';
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 DetailDeviceStateLog: React.FC = () => {
type DetailDeviceStateLogProps = {
commInfo: Record<string, any>;
};
// TODO 根据具体数据展示
const DetailDeviceStateLog: React.FC<DetailDeviceStateLogProps> = (props) => {
const actionRef = useRef<ActionType>();
// 动态设置每页数量
const [currentPageSize, setCurrentPageSize] = useState<number>(10);
@ -34,7 +38,7 @@ const DetailDeviceStateLog: React.FC = () => {
title: (
<FormattedMessage id="device_state.table.stateLog.list.runTime" defaultMessage="运行时长" />
),
dataIndex: 'runTime',
dataIndex: 'duration',
hideInSearch: true,
width: '20%',
},
@ -45,7 +49,7 @@ const DetailDeviceStateLog: React.FC = () => {
defaultMessage="更新时间"
/>
),
dataIndex: 'updateTime',
dataIndex: 'update_time',
hideInSearch: true,
valueType: 'dateTime',
},
@ -75,11 +79,15 @@ const DetailDeviceStateLog: React.FC = () => {
request={async (params = {}) => {
const { current, ...rest } = params;
const reqParams = {
entity_id: props?.commInfo?.id,
pageNo: current,
...rest,
};
let resp = await getDeviceStateLogList({ ...reqParams });
let resp = await apiDeviceStatusLog({ ...reqParams });
console.log(resp, 'getDeviceStateLogList_resp');
if (!isSuccessApi(resp)) {
return { data: [], success: true };
}
return {
data: resp.data?.data,
success: resp.success,

@ -2,16 +2,14 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-08 16:57:30
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-22 16:51:39
* @LastEditTime: 2024-06-18 11:43:19
* @FilePath: \general-ai-manage\src\pages\Project\BusinessProject\components\detailServerState.tsx
* @Description:
* @
*
*/
import { bsServerDetailEnums } from '@/enums/server';
import { getModelGroupBaseModelList } from '@/services/testApi/model';
import { isSuccessApi } from '@/utils/forApi';
import { ProCard, ProDescriptions, ProList, ProTable } from '@ant-design/pro-components';
import { ProCard, ProDescriptions } from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Modal, Tabs } from 'antd';
import * as echarts from 'echarts';
@ -30,7 +28,7 @@ const DetailServerState: React.FC<DetailServerStateProps> = ({ info, detailOpen,
const intl = useIntl();
const [tabKey, setTabKey] = useState<string>(bsServerDetailEnums[0].key);
const [tabs] = useState<DICTENUM.DICT_TAB_ITEM[]>([...bsServerDetailEnums]);
const [modelData, setModelData] = useState<Record<string, any>[]>([]); // 列表数据
// const [modelData, setModelData] = useState<Record<string, any>[]>([]); // 列表数据
const [forceRender, setForceRender] = useState<boolean>(false);
// 基础模型信息
@ -156,98 +154,98 @@ 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>
);
},
},
];
// 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');
}
// 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);
}
}
// async function fetchData() {
// const resp = await getModelGroupBaseModelList();
// if (isSuccessApi(resp)) {
// toListDomByData(resp.data.data);
// }
// }
useEffect(() => {
setForceRender(detailOpen);
}, [detailOpen]);
// 初始化加载
useEffect(() => {
fetchData();
}, []);
// useEffect(() => {
// fetchData();
// }, []);
return (
<Modal
@ -317,7 +315,8 @@ const DetailServerState: React.FC<DetailServerStateProps> = ({ info, detailOpen,
})}
</ul>
</li>
<li className="pb-[8px] bs_server_task_wrap">
{/* 服务器信息暂时不需要当前任务模块 */}
{/* <li className="pb-[8px] bs_server_task_wrap">
<p className="head4">
<FormattedMessage
id="server_state.table.detail.title.task"
@ -356,7 +355,7 @@ const DetailServerState: React.FC<DetailServerStateProps> = ({ info, detailOpen,
}}
/>
</div>
</li>
</li> */}
</ul>
</ProCard>
</div>

@ -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:13
* @LastEditTime: 2024-06-17 13:33:33
* @FilePath: \general-ai-manage\src\pages\Business\BusinessState\components\deviceStateCard.tsx
* @Description:
*/
@ -22,17 +22,17 @@ type DeviceStateCardProps = {
};
const DeviceStateCard: React.FC<DeviceStateCardProps> = ({ info, renderActions, fetchDetail }) => {
const formatStateByVal = (record: string): DICTENUM.DICT_TAB_ITEM => {
return deviceStateEnums.find((item: DICTENUM.DICT_TAB_ITEM) => item.key === record);
const formatStateByVal = (record: number): DICTENUM.DICT_TAB_ITEM => {
return deviceStateEnums.find((item: DICTENUM.DICT_TAB_ITEM) => Number(item.key) === record);
};
// 动效类型
const fetchAnimatePicByType = () => {
switch (info?.state) {
case '1':
case '3':
switch (info?.status + '') {
case '1001':
case '1003':
return <AnimatePic value={onlineAnimateJson} />;
case '4':
case '1004':
return <AnimatePic value={errorAnimateJson} />;
default:
@ -48,18 +48,18 @@ const DeviceStateCard: React.FC<DeviceStateCardProps> = ({ 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?.name}</div>
<div
className={`gn_card_tag ml-[8px] text-white ${
info?.state === '1' ? 'bg_active_1' : ''
} ${info?.state === '2' ? 'bg_gray_color_1' : ''} ${
info?.state === '3' ? 'bg_active_3' : ''
} ${info?.state === '4' ? 'bg_active_2' : ''}`}
Number(info?.status) === 1001 ? 'bg_active_1' : ''
} ${Number(info?.status) === 1002 ? 'bg_gray_color_1' : ''} ${
Number(info?.status) === 1003 ? 'bg_active_3' : ''
} ${Number(info?.status) === 1004 ? 'bg_active_2' : ''}`}
>
{formatStateByVal(info?.state)?.label}
{formatStateByVal(info?.status)?.label}
</div>
</div>
<span>

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-05-10 10:47:45
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-22 11:14:05
* @LastEditTime: 2024-06-19 11:29:16
* @FilePath: \general-ai-platform-web\src\pages\Business\BusinessState\deviceSate.tsx
* @Description:
* @
@ -13,10 +13,22 @@
import { CommButton, TextButton } from '@/components/Button';
import IsConfirmAction from '@/components/TableActionCard/isConfirmAction';
import { deviceStateEnums } from '@/enums/device';
import { getDeviceStateList } from '@/services/testApi/businessState';
import { getDictDeviceType } from '@/services/testApi/dict';
import { useBusinessInfo } from '@/hooks/useBusinessInfo';
import {
apiDeviceClassification,
apiDeviceStatusInfo,
apiDeviceStatusList,
} from '@/services/business/device';
import { apiEntityNodes } from '@/services/business/entity';
import { isSuccessApi } from '@/utils/forApi';
import { ProCard, ProForm, ProFormSelect, ProList } from '@ant-design/pro-components';
import { mathSumByNumberArr } from '@/utils/forMath';
import {
ProCard,
ProForm,
ProFormSelect,
ProFormTreeSelect,
ProList,
} from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Tabs } from 'antd';
import { useEffect, useState } from 'react';
@ -30,6 +42,9 @@ import { ReactComponent as SearchIcon } from '/public/home/search_icon.svg';
const DeviceSate: 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>>();
@ -45,16 +60,70 @@ const DeviceSate: React.FC = () => {
const [querysData, setQuerysData] = useState<Record<string, any>>({}); // 列表查询参数
const [tabKey, setTabKey] = useState<string>(deviceStateEnums[0].key);
const [tabs, setTabs] = useState<DICTENUM.DICT_TAB_ITEM[]>([]);
const [deviceTreeList, setDeviceTreeList] = useState<Record<string, any>[]>([]);
// 组装进度展示信息
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 apiDeviceStatusInfo({ 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: (
<DeviceStateCard
info={item}
fetchDetail={() => {
setCurrentRow(item);
loadDetail(item);
setDetailOpen(true);
}}
renderActions={[
@ -107,33 +176,38 @@ const DeviceSate: React.FC = () => {
// 企业列表数据api
async function fetchData() {
const resp = await getDeviceStateList({
const resp = await apiDeviceStatusList({
pageNo: currentPage,
pageSize: currentPageSize,
status: tabKey,
status: Number(tabKey),
entity_id: commInfo.id,
...querysData,
});
if (isSuccessApi(resp)) {
toListDomByData(resp.data.data);
const currCounts = { ...resp.data.status_count };
const currTotalCount = mathSumByNumberArr(Object.values(currCounts));
setTabs(() => {
const finalArr = [];
JSON.parse(JSON.stringify(deviceStateEnums)).forEach((item) => {
switch (item.key) {
case '1':
item.label = `${deviceStateEnums[1].label}${resp.data.onlineCount}`;
case '1001':
item.label = `${deviceStateEnums[1].label}${currCounts[deviceStateEnums[1].key]}`;
break;
case '2':
item.label = `${deviceStateEnums[2].label}${resp.data.outlineCount}`;
case '1002':
item.label = `${deviceStateEnums[2].label}${currCounts[deviceStateEnums[2].key]}`;
break;
case '3':
item.label = `${deviceStateEnums[3].label}${resp.data.processCount}`;
case '1003':
item.label = `${deviceStateEnums[3].label}${
currCounts[deviceStateEnums[3].key]
}}`;
break;
case '4':
item.label = `${deviceStateEnums[4].label}${resp.data.errorCount}`;
case '1004':
item.label = `${deviceStateEnums[4].label}${currCounts[deviceStateEnums[4].key]}`;
break;
case '0':
case '1000':
default:
item.label = `${deviceStateEnums[0].label}${resp.data.count}`;
item.label = `${deviceStateEnums[0].label}${currTotalCount}`;
break;
}
finalArr.push(item);
@ -142,13 +216,13 @@ const DeviceSate: React.FC = () => {
});
setTotal(() => {
switch (tabKey) {
case '1':
case '1001':
return resp.data.onlineCount;
case '2':
case '1002':
return resp.data.outlineCount;
case '3':
case '1003':
return resp.data.processCount;
case '4':
case '1004':
return resp.data.errorCount;
default:
return resp.data.count;
@ -156,7 +230,6 @@ const DeviceSate: React.FC = () => {
});
}
}
// TODO 切换时页码没有显示第一页
const changeTabMode = (key: string) => {
setTabKey(key);
setCurrentPage(1);
@ -167,11 +240,23 @@ const DeviceSate: React.FC = () => {
// setCurrentPage(1);
// }
// 设备节点树
async function loadDeviceTree() {
const resp = await apiEntityNodes({ entity_id: commInfo.id });
if (isSuccessApi(resp)) {
setDeviceTreeList(resp?.data?.data);
}
}
// 初始化加载 & 筛选查询
useEffect(() => {
fetchData();
}, [tabKey, currentPageSize, currentPage, querysData]);
useEffect(() => {
loadDeviceTree();
}, []);
return (
<div className="flex-1 bs_server_state_page bs_state_page gn_head_card">
<div className="gn_form gn_table_query_filter">
@ -211,10 +296,44 @@ const DeviceSate: React.FC = () => {
return true;
}}
>
{/* //TODO 缺失筛选条件设备组 树形选择*/}
<ProFormTreeSelect
width={300}
name="node_ids"
label={
<FormattedMessage
id="device_group_list.table.list.deviceNode"
defaultMessage="节点"
/>
}
placeholder={`${intl.formatMessage({
id: 'common.please_select',
defaultMessage: '$$$',
})}${intl.formatMessage({
id: 'device_group_list.table.list.deviceNode',
defaultMessage: '节点',
})}`}
// treeData={deviceTreeList}
// fieldNames= {{
// label: 'name',
// value: 'id',
// children: 'children',
// }}
fieldProps={{
multiple: true,
treeData: deviceTreeList,
style: { marginRight: 12 },
treeDefaultExpandAll: true,
fieldNames: {
label: 'name',
value: 'id',
children: 'children',
},
}}
/>
<ProFormSelect
width={300}
name="deviceType"
name="classification_suid"
label={
<FormattedMessage
id="device_group_list.table.list.deviceType"
@ -231,7 +350,7 @@ const DeviceSate: React.FC = () => {
showSearch
debounceTime={500}
request={async () => {
const { data } = await getDictDeviceType();
const { data } = await apiDeviceClassification();
return data?.data?.map((v: Record<string, any>) => {
return { ...v, label: v.name, value: v.id };
});
@ -289,6 +408,7 @@ const DeviceSate: React.FC = () => {
<DetailDeviceState
detailOpen={detailOpen}
info={currentRow}
commInfo={commInfo}
closeModal={() => {
setDetailOpen(false);
}}

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-22 15:23:36
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-06-04 16:33:16
* @LastEditTime: 2024-06-19 11:42:02
* @FilePath: \general-ai-platform-web\src\pages\Business\DeviceGroup\components\deviceList.tsx
* @Description: deviceGroupdg
* @
@ -95,6 +95,7 @@ const DeviceList: React.FC<DeviceListProps> = (props) => {
useEffect(() => {
if (actionRef && props?.nodeInfo) {
reloadList();
setIsSettingOpen(false);
}
}, [actionRef, props.nodeInfo]);

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-30 10:02:29
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-06-12 10:08:58
* @LastEditTime: 2024-06-19 15:23:58
* @FilePath: \general-ai-platform-web\src\pages\Business\DeviceGroup\components\modelDeploy.tsx
* @Description:
* @
@ -11,8 +11,9 @@
*/
import { TextButton } from '@/components/Button';
import TableActionCard from '@/components/TableActionCard';
import { apiEntityNodesBusimodel } from '@/services/business/entity';
import { apiEntityNodesBusimodel, apiEntityNodesBusimodelInfo } from '@/services/business/entity';
import { isSuccessApi } from '@/utils/forApi';
import { ExclamationCircleFilled } from '@ant-design/icons';
import type { ActionType, ProColumns } from '@ant-design/pro-components';
import { ProTable } from '@ant-design/pro-components';
@ -28,7 +29,7 @@ type ModelDeployProps = {
nodeInfo: Record<string, any>;
};
const ModelDeploy: React.FC<ModelDeployProps> = (props) => {
const ModelDeploy: React.FC<ModelDeployProps> = ({ nodeInfo }) => {
// const intl = useIntl();
const actionRef = useRef<ActionType>();
@ -40,9 +41,21 @@ const ModelDeploy: React.FC<ModelDeployProps> = (props) => {
// 部署参数配置展示
const [detailOpen, setDetailOpen] = useState<boolean>(false);
/**配置参数 */
// function reloadList() {
// actionRef.current?.reload();
// }
function reloadList() {
actionRef.current?.reload();
}
// 详情 apiEntityNodesBusimodelInfo
async function loadDetail(record) {
const resp = await apiEntityNodesBusimodelInfo({
node_id: nodeInfo?.node_id,
busi_model_id: record?.busi_model_id,
});
if (isSuccessApi(resp) && resp?.data) {
setCurrentRow({ ...resp?.data, busi_model_id: record?.busi_model_id });
}
}
// 业务模型列表信息
const columns: ProColumns<Record<string, any>>[] = [
{
@ -54,18 +67,18 @@ const ModelDeploy: React.FC<ModelDeployProps> = (props) => {
},
{
title: <FormattedMessage id="business_model.table.list.isEnable" defaultMessage="部署状态" />,
dataIndex: 'isEnable',
dataIndex: 'deployed',
hideInSearch: true,
render: (dom, record) => {
return (
<div
className={`gn_list_type_tag flex items-center justify-center ${
record.isEnable ? 'active1' : 'active2'
record.deployed === 1 ? 'active1' : 'active2'
}`}
>
<span className="dot"></span>
<span>
{record.isEnable ? (
{record.deployed === 1 ? (
<FormattedMessage
id="business_model.table.list.deployed.isEnable"
defaultMessage="已部署"
@ -106,7 +119,7 @@ const ModelDeploy: React.FC<ModelDeployProps> = (props) => {
renderDom: (
<span
onClick={() => {
setCurrentRow(record);
loadDetail(record);
setDetailOpen(true);
}}
>
@ -170,7 +183,7 @@ const ModelDeploy: React.FC<ModelDeployProps> = (props) => {
const { current, ...rest } = params;
const reqParams = {
pageNo: current,
node_id: props.nodeInfo.id,
node_id: nodeInfo.id,
...rest,
};
if (!reqParams.node_id) {
@ -192,9 +205,11 @@ const ModelDeploy: React.FC<ModelDeployProps> = (props) => {
<ModelDeployConfig
detailOpen={detailOpen}
info={currentRow}
closeModal={() => {
nodeInfo={nodeInfo}
handleModal={() => {
setDetailOpen(false);
}}
reload={reloadList}
/>
</div>
);

@ -2,29 +2,45 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-08 16:57:30
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-21 15:51:41
* @LastEditTime: 2024-06-19 15:23:06
* @FilePath: \general-ai-manage\src\pages\Project\BusinessProject\components\detailServerState.tsx
* @Description:
* @
*
*/
import { getAllDeviceList } from '@/services/testApi/device';
import {
apiEntityNodesBusimodelDeploy,
apiEntityNodesDeviceListSimple,
} from '@/services/business/entity';
import { isSuccessApi } from '@/utils/forApi';
import { mathConvertCommaSeparatedStringToArray, mathExtractIds } from '@/utils/forMath';
import { isArrayAndNotEmpty } from '@/utils/is';
import { ProCard, ProColumns, ProDescriptions, ProTable } from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max';
import { Modal } from 'antd';
import { Modal, message } from 'antd';
import { useEffect, useRef, useState } from 'react';
import { proFormSmallModelWidth } from '../../../../../config/defaultForm';
type ModelDeployConfigProps = {
info: Record<string, any>;
nodeInfo: Record<string, any>;
detailOpen: boolean;
closeModal: () => void;
handleModal: () => void;
reload: () => void;
};
const ModelDeployConfig: React.FC<ModelDeployConfigProps> = ({ info, detailOpen, closeModal }) => {
const ModelDeployConfig: React.FC<ModelDeployConfigProps> = ({
info,
nodeInfo,
detailOpen,
reload,
handleModal,
}) => {
/**state */
const intl = useIntl();
const [selectedRows, setSelectedRows] = useState<Record<string, any>[]>([]);
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
const actionRef = useRef();
// 基础配置信息
const detailColumns = [
@ -35,11 +51,11 @@ const ModelDeployConfig: React.FC<ModelDeployConfigProps> = ({ info, detailOpen,
defaultMessage="业务名称"
/>
),
dataIndex: 'bussnessName',
dataIndex: 'busi_model_name',
},
{
title: <FormattedMessage id="business_model.deploy.config.remark" defaultMessage="简介" />,
dataIndex: 'remark',
dataIndex: 'busi_model_comment',
},
{
title: (
@ -52,15 +68,15 @@ const ModelDeployConfig: React.FC<ModelDeployConfigProps> = ({ info, detailOpen,
render: (_, record) => {
return (
<ul className="flex flex-wrap">
{record?.linkModels?.map((item, index) => {
{mathConvertCommaSeparatedStringToArray(record?.base_models)?.map((item, index) => {
return (
<li
className={`text_primary primary_border rounded-[2px] px-[8px] mb-[8px] ${
index !== 0 ? 'ml-[8px]' : ''
}`}
key={item.id}
key={index + item}
>
{item.name}
{item}
</li>
);
})}
@ -89,22 +105,35 @@ const ModelDeployConfig: React.FC<ModelDeployConfigProps> = ({ info, detailOpen,
defaultMessage="设备类型"
/>
),
dataIndex: 'deviceType',
dataIndex: 'classification_name',
hideInSearch: true,
},
];
// 基础模型列表数据api
function loadData() {}
function loadData() {
console.log(info?.devices, 'loadData_devices');
if (isArrayAndNotEmpty(info?.devices)) {
const selectArr = [];
info?.devices.forEach((item) => {
selectArr.push(item.device_id);
});
setSelectedRowKeys(selectArr);
}
}
useEffect(() => {
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
info?.busi_model_id && loadData();
}, [info]);
// 初始化加载
useEffect(() => {
console.log('modelDeployConfig_detailOpen', detailOpen);
if (detailOpen) {
loadData();
} else {
if (!detailOpen) {
actionRef?.current?.clearSelected();
setSelectedRows([]);
setSelectedRowKeys([]);
}
}, [detailOpen]);
@ -117,12 +146,27 @@ const ModelDeployConfig: React.FC<ModelDeployConfigProps> = ({ info, detailOpen,
})}`}
open={detailOpen}
onCancel={() => {
closeModal();
handleModal();
}}
onOk={() => {
console.log('onOk_selectedRows', selectedRows);
// TODO 选择完成后再关闭弹框
closeModal();
onOk={async () => {
console.log(info, 'onOk_selectedRows', selectedRows);
let resp = await apiEntityNodesBusimodelDeploy({
node_id: nodeInfo?.node_id,
busi_model_id: info?.busi_model_id,
device_ids: mathExtractIds(selectedRows)?.join(','),
});
if (isSuccessApi(resp)) {
message.success(
intl.formatMessage({ id: 'common.action.success', defaultMessage: '$$$' }),
);
reload();
handleModal();
} else {
message.error(
resp?.meta?.message ||
intl.formatMessage({ id: 'common.action.failure', defaultMessage: '$$$' }),
);
}
}}
okText={<FormattedMessage id="pages.modelForm.okText" defaultMessage="确认" />}
cancelText={<FormattedMessage id="pages.modelForm.cancelText" defaultMessage="取消" />}
@ -153,13 +197,14 @@ const ModelDeployConfig: React.FC<ModelDeployConfigProps> = ({ info, detailOpen,
rowKey="id"
pagination={false}
rowSelection={{
selectedRowKeys,
onChange: (_, selectedRowsData) => {
setSelectedRows(selectedRowsData);
},
}}
tableAlertRender={false}
request={async () => {
let resp = await getAllDeviceList();
let resp = await apiEntityNodesDeviceListSimple({ node_id: nodeInfo?.node_id });
console.log(resp, 'getAllDeviceList_resp');
return {
data: resp.data?.data,

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-30 10:02:29
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-06-12 10:04:30
* @LastEditTime: 2024-06-19 16:07:50
* @FilePath: \general-ai-platform-web\src\pages\Business\DeviceGroup\components\modelSetting.tsx
* @Description:
* @
@ -44,7 +44,7 @@ const ModelSetting: React.FC<ModelSettingProps> = (props) => {
const columns: ProColumns<Record<string, any>>[] = [
{
title: <FormattedMessage id="base_model.table.list.name" defaultMessage="基础模型名称" />,
dataIndex: 'name',
dataIndex: 'model_name',
hideInSearch: true,
key: 'fixedName',
fixed: 'left',
@ -52,7 +52,7 @@ const ModelSetting: React.FC<ModelSettingProps> = (props) => {
},
{
title: <FormattedMessage id="base_model.table.list.version" defaultMessage="版本" />,
dataIndex: 'version',
dataIndex: 'model_version',
hideInSearch: true,
width: '20%',
},
@ -60,12 +60,12 @@ const ModelSetting: React.FC<ModelSettingProps> = (props) => {
title: (
<FormattedMessage id="base_model.table.list.runtimeLibFile" defaultMessage="运行库镜像" />
),
dataIndex: 'runtimeLibFile',
dataIndex: 'model_hub_image',
hideInSearch: true,
render: (dom, record) => {
return (
<div>
{record.runtimeLibFile ? (
{record.model_hub_image ? (
dom
) : (
<div className={`gn_list_type_tag flex items-center justify-center active2`}>
@ -125,7 +125,7 @@ const ModelSetting: React.FC<ModelSettingProps> = (props) => {
<div>
<div className="gn_list_card_title pb-[12px]">
<span></span>
<span>{item.name}</span>
<span>{item?.busi_model_name}</span>
</div>
<ProTable
className="gn_pro_table mb-[16px]"
@ -141,7 +141,7 @@ const ModelSetting: React.FC<ModelSettingProps> = (props) => {
// 标题栏
search={false}
options={{ fullScreen: false, setting: false, density: false, reload: false }}
rowKey="id"
rowKey="model_id"
onDataSourceChange={(data) => {
console.log(data, 'onDataSourceChange_data');
}}
@ -150,7 +150,7 @@ const ModelSetting: React.FC<ModelSettingProps> = (props) => {
persistenceKey: 'algorithm_model_list',
persistenceType: 'localStorage',
}}
dataSource={item.list}
dataSource={item.base_models}
columns={columns}
/>
</div>
@ -168,7 +168,7 @@ const ModelSetting: React.FC<ModelSettingProps> = (props) => {
device_id: props.info.device_id,
});
if (isSuccessApi(resp)) {
// toListDomByData(resp.data.data);
toListDomByData(resp.data.data);
}
}

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-22 15:23:36
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-06-11 13:30:14
* @LastEditTime: 2024-06-19 15:44:38
* @FilePath: \general-ai-platform-web\src\pages\Business\DeviceGroup\index.tsx
* @Description: deviceGroupdg
* @
@ -156,6 +156,7 @@ const DeviceGroup: React.FC = () => {
}}
selectTree={(selectedKeys, info) => {
if (selectedKeys && Array.isArray(selectedKeys) && selectedKeys.length) {
setTabKey('1'); // 重置到设备列表
loadDeviceDetail({ id: selectedKeys[0] });
}
console.log('selectTree_selected', selectedKeys, info);

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-07 14:02:00
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-06-11 17:41:25
* @LastEditTime: 2024-06-18 15:05:13
* @FilePath: \general-ai-manage\src\pages\Log\index.tsx
* @Description:
* @
@ -185,63 +185,64 @@ const LogIndex: React.FC = () => {
</div>
}
>
{/* // TODO 需要控制表格溢出滚动高度 */}
<ProTable
className="gn_pro_table"
cardProps={{
bodyStyle: {
padding: '0',
},
}}
search={false}
scroll={{ x: proTableCommonOptions.commscrollX }}
options={{ fullScreen: false, setting: false, density: false, reload: false }}
actionRef={actionRef}
rowKey="id"
onDataSourceChange={(data) => {
console.log(data, 'onDataSourceChange_data');
// let CategoryFkIdIds: any = data.map((v) => {
// return v.categoryFkId;
// });
// setCategoryFkIdIds(CategoryFkIdIds);
}}
pagination={{
...proTablePaginationOptions,
pageSize: currentPageSize,
onChange: (pageNo, pageSize) => setCurrentPageSize(pageSize),
}}
columnsState={{
persistenceKey: 'algorithm_model_list',
persistenceType: 'localStorage',
}}
request={async (params = {}, sort) => {
const { current, ...rest } = params;
const reqParams = {
pageNo: current,
desc: false,
orderKey: '',
...rest,
};
if (sort && Object.keys(sort).length) {
reqParams.orderKey = Object.keys(sort)[0];
let sort_select = sort[reqParams.orderKey];
reqParams.desc = sort_select === 'descend';
}
let resp = await getServerLogList({ ...reqParams, ...querysData });
console.log(resp, 'getServerLogList_resp');
if (!isSuccessApi(resp)) {
return { data: [], success: true };
}
return {
data: resp.data.data,
success: resp.success,
total: resp.data.count,
current: current,
<div className="gn_scroll_list_wrap" style={{ maxHeight: 'calc(100vh - 240px)' }}>
<ProTable
className="gn_pro_table"
cardProps={{
bodyStyle: {
padding: '0',
},
}}
search={false}
scroll={{ x: proTableCommonOptions.commscrollX }}
options={{ fullScreen: false, setting: false, density: false, reload: false }}
actionRef={actionRef}
rowKey="id"
onDataSourceChange={(data) => {
console.log(data, 'onDataSourceChange_data');
// let CategoryFkIdIds: any = data.map((v) => {
// return v.categoryFkId;
// });
// setCategoryFkIdIds(CategoryFkIdIds);
}}
pagination={{
...proTablePaginationOptions,
pageSize: currentPageSize,
};
}}
columns={columns}
/>
onChange: (pageNo, pageSize) => setCurrentPageSize(pageSize),
}}
columnsState={{
persistenceKey: 'algorithm_model_list',
persistenceType: 'localStorage',
}}
request={async (params = {}, sort) => {
const { current, ...rest } = params;
const reqParams = {
pageNo: current,
desc: false,
orderKey: '',
...rest,
};
if (sort && Object.keys(sort).length) {
reqParams.orderKey = Object.keys(sort)[0];
let sort_select = sort[reqParams.orderKey];
reqParams.desc = sort_select === 'descend';
}
let resp = await getServerLogList({ ...reqParams, ...querysData });
console.log(resp, 'getServerLogList_resp');
if (!isSuccessApi(resp)) {
return { data: [], success: true };
}
return {
data: resp.data.data,
success: resp.success,
total: resp.data.count,
current: current,
pageSize: currentPageSize,
};
}}
columns={columns}
/>
</div>
</ProCard>
</div>
);

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-07 14:02:00
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-31 14:36:33
* @LastEditTime: 2024-06-14 14:08:11
* @FilePath: \general-ai-manage\src\pages\ModelIndex\ModelIndex.tsx
* @Description:
* @
@ -252,7 +252,6 @@ const ModelIndex: React.FC = () => {
onFinish={async (values) => {
console.log(values, 'filter_finish_values');
setQuerysData(() => values);
return true;
}}
>

@ -70,7 +70,7 @@ export const errorConfig: RequestConfig = {
});
break;
case ErrorShowType.REDIRECT:
// TODO: redirect
// redirect
break;
default:
message.error(errorMessage);

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-05-24 17:57:19
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-27 14:54:19
* @LastEditTime: 2024-06-18 13:50:25
* @FilePath: \general-ai-platform-web\src\services\business\device.ts
* @Description:
*/
@ -58,3 +58,51 @@ export async function apiDeviceClassificationDelete(body: any, options?: { [key:
},
);
}
// 设备状态列表
export async function apiDeviceStatusList(body: any, options?: { [key: string]: any }) {
return request<API.Response & { data?: API.ENTITY_INDEX_DATA; msg?: string }>(
`/api/v1/enterprise/device/status/list`,
{
method: 'POST',
headers: {
// 'Content-Type': 'application/json',
// "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
},
data: body,
...(options || {}),
},
);
}
// 设备状态 - 设备详情
export async function apiDeviceStatusInfo(body: any, options?: { [key: string]: any }) {
return request<API.Response & { data?: API.ENTITY_INDEX_DATA; msg?: string }>(
`/api/v1/enterprise/device/status/info`,
{
method: 'POST',
headers: {
// 'Content-Type': 'application/json',
// "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
},
data: body,
...(options || {}),
},
);
}
// 设备状态日志
export async function apiDeviceStatusLog(body: any, options?: { [key: string]: any }) {
return request<API.Response & { data?: API.ENTITY_INDEX_DATA; msg?: string }>(
`/api/v1/enterprise/device/status/log`,
{
method: 'POST',
headers: {
// 'Content-Type': 'application/json',
// "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
},
data: body,
...(options || {}),
},
);
}

@ -30,7 +30,7 @@ export async function getDeviceGroupList(
);
}
/** 获取设备组树 GET /device_group/getDeviceGroupTree */
/** 获取节点树 GET /device_group/getDeviceGroupTree */
export async function getDeviceGroupTree(
body: Record<string, any>, //
options?: { [key: string]: any },

@ -0,0 +1,58 @@
/*
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-06-18 13:36:03
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-06-19 14:34:55
* @FilePath: \general-ai-platform-web\src\utils\math.ts
* @Description:
*/
import { isNotEmptyString } from './is';
/**
*
* @param arr number
* @returns
*/
export function mathSumByNumberArr(arr: number[]) {
return arr.reduce(function (prev, curr) {
return prev + curr;
});
}
/**
*
* @param inputString - The comma-separated string.
* @returns An array of strings.
*/
export function mathConvertCommaSeparatedStringToArray(inputString: string): string[] {
if (isNotEmptyString(inputString)) {
return inputString.split(',');
}
return [];
}
/**
* Function to extract 'id' properties from an array of objects.
*
* @param objectsArray - The array of objects, each containing an 'id' property.
* @returns An array of 'id' values, or an empty array if input is invalid.
*/
export function mathExtractIds(objectsArray: any): (number | string)[] {
// Check if the input is an array
if (!Array.isArray(objectsArray)) {
console.error('Input is not an array');
return [];
}
// Check if every item in the array is an object and has an 'id' property
for (const obj of objectsArray) {
if (typeof obj !== 'object' || obj === null || !('id' in obj)) {
console.error("Invalid object in array or missing 'id' property");
return [];
}
}
// Map the array to extract 'id' properties
return objectsArray.map((obj) => obj.id);
}

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-06-05 13:32:31
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-06-07 16:10:52
* @LastEditTime: 2024-06-19 15:27:28
* @FilePath: \general-ai-platform-web\src\utils\is.ts
* @Description:
*/
@ -29,3 +29,23 @@ export function isValidJson(jsonString) {
export function isArrayAndNotEmpty(obj) {
return Array.isArray(obj) && obj.length > 0;
}
/**
* Function to check if a given string is not empty.
* An empty string is defined as a string that is either null, undefined, or consists only of whitespace.
*
* @param inputString - The string to check.
* @returns A boolean indicating whether the string is not empty.
*/
export function isNotEmptyString(inputString: string | null | undefined): boolean {
// Check if the string is null or undefined
if (inputString === null || inputString === undefined) {
return false;
}
// Trim the input string to remove any leading or trailing whitespace
const trimmedString = inputString.trim();
// Check if the trimmed string is not empty
return trimmedString !== '';
}

Loading…
Cancel
Save