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

develop2
donghao 10 months ago
parent b55530aa51
commit 120b162a40

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

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

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

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

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

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

@ -145,7 +145,9 @@ const BaseTree: React.FC<BaseTreeProps> = (props) => {
return ( return (
<TreeNode <TreeNode
{...node} {...node}
title={formatTreeValByNodeKey('title', node)} title={`${formatTreeValByNodeKey('title', node)}(${
formatTreeValByNodeKey('children', node)?.length
})`}
key={formatTreeValByNodeKey('key', node)} key={formatTreeValByNodeKey('key', node)}
className={`tree_node_item tree_node_${!node?.parent ? 0 : 1}`} className={`tree_node_item tree_node_${!node?.parent ? 0 : 1}`}
> >
@ -234,25 +236,6 @@ const BaseTree: React.FC<BaseTreeProps> = (props) => {
</Tree> </Tree>
<div className="tree_node_0">{renderAddAction()}</div> <div className="tree_node_0">{renderAddAction()}</div>
</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> </div>
); );
}; };

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

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

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

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

@ -2,7 +2,7 @@
* @Author: zhoux zhouxia@supervision.ltd * @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-01 13:56:33 * @Date: 2023-11-01 13:56:33
* @LastEditors: donghao donghao@supervision.ltd * @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 * @FilePath: \general-ai-platform-web\src\locales\zh-CN\device.ts
* @Description: * @Description:
*/ */
@ -50,6 +50,8 @@ export const device_group_list: { [key: string]: string } = {
'device_group_list.table.list.name': '设备名称', 'device_group_list.table.list.name': '设备名称',
'device_group_list.table.list.rule.required.name': '请填写设备名称', 'device_group_list.table.list.rule.required.name': '请填写设备名称',
'device_group_list.table.list.deviceSite': '设备位置', 'device_group_list.table.list.deviceSite': '设备位置',
'device_group_list.table.list.deviceNode': '节点',
'device_group_list.table.list.deviceType': '设备分类', 'device_group_list.table.list.deviceType': '设备分类',
'device_group_list.table.list.rule.required.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 } = { 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.deviceType': '设备分类',
'device_state.table.form.name': '设备名称', 'device_state.table.form.name': '设备名称',
'device_state.table.form.remark': '备注', 'device_state.table.form.remark': '备注',
// 日志 // 日志
'device_state.table.stateLog.list.ip': '设备IP', '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.stateLog.list.updateTime': '更新时间',
'device_state.table.detail.echarts.used': '已占用', 'device_state.table.detail.echarts.used': '已占用',

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

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

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

@ -2,16 +2,14 @@
* @Author: donghao donghao@supervision.ltd * @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-08 16:57:30 * @Date: 2024-04-08 16:57:30
* @LastEditors: donghao donghao@supervision.ltd * @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-22 16:51:39 * @LastEditTime: 2024-06-18 11:43:19
* @FilePath: \general-ai-manage\src\pages\Project\BusinessProject\components\detailServerState.tsx * @FilePath: \general-ai-manage\src\pages\Project\BusinessProject\components\detailServerState.tsx
* @Description: * @Description:
* @ * @
* *
*/ */
import { bsServerDetailEnums } from '@/enums/server'; import { bsServerDetailEnums } from '@/enums/server';
import { getModelGroupBaseModelList } from '@/services/testApi/model'; import { ProCard, ProDescriptions } from '@ant-design/pro-components';
import { isSuccessApi } from '@/utils/forApi';
import { ProCard, ProDescriptions, ProList, ProTable } from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max'; import { FormattedMessage, useIntl } from '@umijs/max';
import { Modal, Tabs } from 'antd'; import { Modal, Tabs } from 'antd';
import * as echarts from 'echarts'; import * as echarts from 'echarts';
@ -30,7 +28,7 @@ const DetailServerState: React.FC<DetailServerStateProps> = ({ info, detailOpen,
const intl = useIntl(); const intl = useIntl();
const [tabKey, setTabKey] = useState<string>(bsServerDetailEnums[0].key); const [tabKey, setTabKey] = useState<string>(bsServerDetailEnums[0].key);
const [tabs] = useState<DICTENUM.DICT_TAB_ITEM[]>([...bsServerDetailEnums]); 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); const [forceRender, setForceRender] = useState<boolean>(false);
// 基础模型信息 // 基础模型信息
@ -156,98 +154,98 @@ const DetailServerState: React.FC<DetailServerStateProps> = ({ info, detailOpen,
}; };
// 模型列表信息 // 模型列表信息
const columns: ProColumns<Record<string, any>>[] = [ // const columns: ProColumns<Record<string, any>>[] = [
{ // {
title: <FormattedMessage id="base_model.table.list.name" defaultMessage="基础模型名称" />, // title: <FormattedMessage id="base_model.table.list.name" defaultMessage="基础模型名称" />,
dataIndex: 'name', // dataIndex: 'name',
hideInSearch: true, // hideInSearch: true,
key: 'fixedName', // key: 'fixedName',
fixed: 'left', // fixed: 'left',
width: '45%', // width: '45%',
}, // },
{ // {
title: <FormattedMessage id="base_model.table.list.version" defaultMessage="版本" />, // title: <FormattedMessage id="base_model.table.list.version" defaultMessage="版本" />,
dataIndex: 'version', // dataIndex: 'version',
hideInSearch: true, // hideInSearch: true,
width: '20%', // width: '20%',
}, // },
{ // {
title: ( // title: (
<FormattedMessage id="base_model.table.list.runtimeLibFile" defaultMessage="运行库镜像" /> // <FormattedMessage id="base_model.table.list.runtimeLibFile" defaultMessage="运行库镜像" />
), // ),
dataIndex: 'runtimeLibFile', // dataIndex: 'runtimeLibFile',
hideInSearch: true, // hideInSearch: true,
render: (dom, record) => { // render: (dom, record) => {
return ( // return (
<div> // <div>
{record.runtimeLibFile ? ( // {record.runtimeLibFile ? (
dom // dom
) : ( // ) : (
<div className={`gn_list_type_tag flex items-center justify-center active2`}> // <div className={`gn_list_type_tag flex items-center justify-center active2`}>
<span className="dot"></span> // <span className="dot"></span>
<span> // <span>
<FormattedMessage // <FormattedMessage
id="base_model.table.list.undeployed.runtimeLibFile" // id="base_model.table.list.undeployed.runtimeLibFile"
defaultMessage="未部署" // defaultMessage="未部署"
/> // />
</span> // </span>
</div> // </div>
)} // )}
</div> // </div>
); // );
}, // },
}, // },
]; // ];
// 将数据组装成reactDom // 将数据组装成reactDom
function toListDomByData(record) { // function toListDomByData(record) {
let startList = [...record]; // let startList = [...record];
let finalList = startList.map((item) => ({ // let finalList = startList.map((item) => ({
content: ( // content: (
<div> // <div>
<div className="gn_list_card_title pb-[12px]"> // <div className="gn_list_card_title pb-[12px]">
<span></span> // <span></span>
<span>{item.name}</span> // <span>{item.name}</span>
</div> // </div>
<ProTable // <ProTable
className="gn_pro_table mb-[16px]" // className="gn_pro_table mb-[16px]"
cardProps={{ // cardProps={{
bodyStyle: { padding: 0, margin: 0 }, // bodyStyle: { padding: 0, margin: 0 },
}} // }}
// 标题栏 // // 标题栏
search={false} // search={false}
options={{ fullScreen: false, setting: false, density: false, reload: false }} // options={{ fullScreen: false, setting: false, density: false, reload: false }}
rowKey="id" // rowKey="id"
onDataSourceChange={(data) => { // onDataSourceChange={(data) => {
console.log(data, 'onDataSourceChange_data'); // console.log(data, 'onDataSourceChange_data');
}} // }}
pagination={false} // pagination={false}
dataSource={item.list} // dataSource={item.list}
columns={columns} // columns={columns}
/> // />
</div> // </div>
), // ),
})); // }));
setModelData(finalList); // setModelData(finalList);
console.log(finalList, 'toListDomByData_finalList'); // console.log(finalList, 'toListDomByData_finalList');
} // }
// 基础模型列表数据api // 基础模型列表数据api
async function fetchData() { // async function fetchData() {
const resp = await getModelGroupBaseModelList(); // const resp = await getModelGroupBaseModelList();
if (isSuccessApi(resp)) { // if (isSuccessApi(resp)) {
toListDomByData(resp.data.data); // toListDomByData(resp.data.data);
} // }
} // }
useEffect(() => { useEffect(() => {
setForceRender(detailOpen); setForceRender(detailOpen);
}, [detailOpen]); }, [detailOpen]);
// 初始化加载 // 初始化加载
useEffect(() => { // useEffect(() => {
fetchData(); // fetchData();
}, []); // }, []);
return ( return (
<Modal <Modal
@ -317,7 +315,8 @@ const DetailServerState: React.FC<DetailServerStateProps> = ({ info, detailOpen,
})} })}
</ul> </ul>
</li> </li>
<li className="pb-[8px] bs_server_task_wrap"> {/* 服务器信息暂时不需要当前任务模块 */}
{/* <li className="pb-[8px] bs_server_task_wrap">
<p className="head4"> <p className="head4">
<FormattedMessage <FormattedMessage
id="server_state.table.detail.title.task" id="server_state.table.detail.title.task"
@ -356,7 +355,7 @@ const DetailServerState: React.FC<DetailServerStateProps> = ({ info, detailOpen,
}} }}
/> />
</div> </div>
</li> </li> */}
</ul> </ul>
</ProCard> </ProCard>
</div> </div>

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd * @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-08 16:57:30 * @Date: 2024-04-08 16:57:30
* @LastEditors: donghao donghao@supervision.ltd * @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-05-22 16:20:13 * @LastEditTime: 2024-06-17 13:33:33
* @FilePath: \general-ai-manage\src\pages\Business\BusinessState\components\deviceStateCard.tsx * @FilePath: \general-ai-manage\src\pages\Business\BusinessState\components\deviceStateCard.tsx
* @Description: * @Description:
*/ */
@ -22,17 +22,17 @@ type DeviceStateCardProps = {
}; };
const DeviceStateCard: React.FC<DeviceStateCardProps> = ({ info, renderActions, fetchDetail }) => { const DeviceStateCard: React.FC<DeviceStateCardProps> = ({ info, renderActions, fetchDetail }) => {
const formatStateByVal = (record: string): DICTENUM.DICT_TAB_ITEM => { const formatStateByVal = (record: number): DICTENUM.DICT_TAB_ITEM => {
return deviceStateEnums.find((item: DICTENUM.DICT_TAB_ITEM) => item.key === record); return deviceStateEnums.find((item: DICTENUM.DICT_TAB_ITEM) => Number(item.key) === record);
}; };
// 动效类型 // 动效类型
const fetchAnimatePicByType = () => { const fetchAnimatePicByType = () => {
switch (info?.state) { switch (info?.status + '') {
case '1': case '1001':
case '3': case '1003':
return <AnimatePic value={onlineAnimateJson} />; return <AnimatePic value={onlineAnimateJson} />;
case '4': case '1004':
return <AnimatePic value={errorAnimateJson} />; return <AnimatePic value={errorAnimateJson} />;
default: default:
@ -48,18 +48,18 @@ const DeviceStateCard: React.FC<DeviceStateCardProps> = ({ info, renderActions,
}} }}
className={`bs_card_box`} className={`bs_card_box`}
> >
<div className={`bs_card_body ${formatStateByVal(info?.state)?.className}`}> <div className={`bs_card_body ${formatStateByVal(Number(info?.status))?.className}`}>
<div className="flex justify-between w-full p-[12px] bs_card_header"> <div className="flex justify-between w-full p-[12px] bs_card_header">
<div className="flex items-center title_box"> <div className="flex items-center title_box">
<div className="bs_card_name single_line head4">{info?.name}</div> <div className="bs_card_name single_line head4">{info?.name}</div>
<div <div
className={`gn_card_tag ml-[8px] text-white ${ className={`gn_card_tag ml-[8px] text-white ${
info?.state === '1' ? 'bg_active_1' : '' Number(info?.status) === 1001 ? 'bg_active_1' : ''
} ${info?.state === '2' ? 'bg_gray_color_1' : ''} ${ } ${Number(info?.status) === 1002 ? 'bg_gray_color_1' : ''} ${
info?.state === '3' ? 'bg_active_3' : '' Number(info?.status) === 1003 ? 'bg_active_3' : ''
} ${info?.state === '4' ? 'bg_active_2' : ''}`} } ${Number(info?.status) === 1004 ? 'bg_active_2' : ''}`}
> >
{formatStateByVal(info?.state)?.label} {formatStateByVal(info?.status)?.label}
</div> </div>
</div> </div>
<span> <span>

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

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

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

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

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

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

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd * @Author: donghao donghao@supervision.ltd
* @Date: 2024-04-07 14:02:00 * @Date: 2024-04-07 14:02:00
* @LastEditors: donghao donghao@supervision.ltd * @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-06-11 17:41:25 * @LastEditTime: 2024-06-18 15:05:13
* @FilePath: \general-ai-manage\src\pages\Log\index.tsx * @FilePath: \general-ai-manage\src\pages\Log\index.tsx
* @Description: * @Description:
* @ * @
@ -185,7 +185,7 @@ const LogIndex: React.FC = () => {
</div> </div>
} }
> >
{/* // TODO 需要控制表格溢出滚动高度 */} <div className="gn_scroll_list_wrap" style={{ maxHeight: 'calc(100vh - 240px)' }}>
<ProTable <ProTable
className="gn_pro_table" className="gn_pro_table"
cardProps={{ cardProps={{
@ -242,6 +242,7 @@ const LogIndex: React.FC = () => {
}} }}
columns={columns} columns={columns}
/> />
</div>
</ProCard> </ProCard>
</div> </div>
); );

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

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

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd * @Author: donghao donghao@supervision.ltd
* @Date: 2024-05-24 17:57:19 * @Date: 2024-05-24 17:57:19
* @LastEditors: donghao donghao@supervision.ltd * @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 * @FilePath: \general-ai-platform-web\src\services\business\device.ts
* @Description: * @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( export async function getDeviceGroupTree(
body: Record<string, any>, // body: Record<string, any>, //
options?: { [key: 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 * @Author: donghao donghao@supervision.ltd
* @Date: 2024-06-05 13:32:31 * @Date: 2024-06-05 13:32:31
* @LastEditors: donghao donghao@supervision.ltd * @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 * @FilePath: \general-ai-platform-web\src\utils\is.ts
* @Description: * @Description:
*/ */
@ -29,3 +29,23 @@ export function isValidJson(jsonString) {
export function isArrayAndNotEmpty(obj) { export function isArrayAndNotEmpty(obj) {
return Array.isArray(obj) && obj.length > 0; 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