feat: 设备和服务器静态交互完成
parent
d8590ee313
commit
bd9a81e0a6
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* @Author: donghao donghao@supervision.ltd
|
||||
* @Date: 2024-05-08 14:21:42
|
||||
* @LastEditors: donghao donghao@supervision.ltd
|
||||
* @LastEditTime: 2024-05-10 15:17:08
|
||||
* @FilePath: \general-ai-platform-web\mock\businessState.ts
|
||||
* @Description: 服务器、设备状态
|
||||
*/
|
||||
import {
|
||||
deviceListData,
|
||||
deviceStateLogListData,
|
||||
serverListData,
|
||||
serverStateLogListData,
|
||||
} from './pools/businessStateData';
|
||||
import { successMockApiProps } from './typing';
|
||||
import { fetchCurrPageByList } from './utils/apiMock';
|
||||
export default {
|
||||
// 服务器列表
|
||||
'GET /api/business/serverState/list': async (req: Request, res: Response) => {
|
||||
// get 使用 query 读取参数
|
||||
const { page, pageSize, status } = req.query;
|
||||
let finalData = serverListData;
|
||||
let { onlineCount, outlineCount } = serverListData.data;
|
||||
if (status && ['1', '2'].includes(status)) {
|
||||
onlineCount = 0;
|
||||
outlineCount = 0;
|
||||
let newArr = [];
|
||||
serverListData.data.results.forEach((item) => {
|
||||
if (status === item.state) {
|
||||
newArr.push(item);
|
||||
}
|
||||
if (item.state === '1') {
|
||||
onlineCount++;
|
||||
} else {
|
||||
outlineCount++;
|
||||
}
|
||||
});
|
||||
finalData = {
|
||||
...serverListData,
|
||||
data: {
|
||||
...serverListData.data,
|
||||
onlineCount,
|
||||
outlineCount,
|
||||
results: newArr,
|
||||
},
|
||||
};
|
||||
}
|
||||
const resData: successMockApiProps = {
|
||||
...fetchCurrPageByList({
|
||||
...finalData,
|
||||
data: { ...finalData.data, page, pageSize: pageSize || 10 },
|
||||
}),
|
||||
};
|
||||
res.json(resData);
|
||||
},
|
||||
|
||||
// 服务器日志分页列表
|
||||
'GET /api/business/serverState/logList': async (req: Request, res: Response) => {
|
||||
// get 使用 query 读取参数
|
||||
const { page, pageSize } = req.query;
|
||||
const resData: successMockApiProps = {
|
||||
...fetchCurrPageByList({
|
||||
...serverStateLogListData,
|
||||
data: { ...serverStateLogListData.data, page, pageSize: pageSize || 10 },
|
||||
}),
|
||||
};
|
||||
res.json(resData);
|
||||
},
|
||||
|
||||
// 设备列表
|
||||
'GET /api/business/deviceState/list': async (req: Request, res: Response) => {
|
||||
// get 使用 query 读取参数
|
||||
const { page, pageSize, status } = req.query;
|
||||
let finalData = deviceListData;
|
||||
let { onlineCount, outlineCount, processCount, errorCount } = deviceListData.data;
|
||||
if (status && ['1', '2', '3', '4'].includes(status)) {
|
||||
onlineCount = 0;
|
||||
outlineCount = 0;
|
||||
processCount = 0;
|
||||
errorCount = 0;
|
||||
let newArr = [];
|
||||
deviceListData.data.results.forEach((item) => {
|
||||
if (status === item.state) {
|
||||
newArr.push(item);
|
||||
}
|
||||
switch (item.state) {
|
||||
case '1':
|
||||
onlineCount++;
|
||||
break;
|
||||
case '2':
|
||||
outlineCount++;
|
||||
break;
|
||||
case '3':
|
||||
processCount++;
|
||||
break;
|
||||
default:
|
||||
errorCount++;
|
||||
break;
|
||||
}
|
||||
});
|
||||
finalData = {
|
||||
...deviceListData,
|
||||
data: {
|
||||
...deviceListData.data,
|
||||
onlineCount,
|
||||
outlineCount,
|
||||
processCount,
|
||||
errorCount,
|
||||
results: newArr,
|
||||
},
|
||||
};
|
||||
}
|
||||
const resData: successMockApiProps = {
|
||||
...fetchCurrPageByList({
|
||||
...finalData,
|
||||
data: { ...finalData.data, page, pageSize: pageSize || 10 },
|
||||
}),
|
||||
};
|
||||
res.json(resData);
|
||||
},
|
||||
|
||||
// 服务器日志分页列表
|
||||
'GET /api/business/deviceState/logList': async (req: Request, res: Response) => {
|
||||
// get 使用 query 读取参数
|
||||
const { page, pageSize } = req.query;
|
||||
const resData: successMockApiProps = {
|
||||
...fetchCurrPageByList({
|
||||
...deviceStateLogListData,
|
||||
data: { ...deviceStateLogListData.data, page, pageSize: pageSize || 10 },
|
||||
}),
|
||||
};
|
||||
res.json(resData);
|
||||
},
|
||||
|
||||
// 未启用
|
||||
// 企业详情
|
||||
// 'GET /api/business/serverState/detail': async (req: Request, res: Response) => {
|
||||
// // get 使用 query 读取参数
|
||||
// const { id } = req.query;
|
||||
// let finalData = {};
|
||||
// serverListData.data.results.forEach((item) => {
|
||||
// if (Number(item.id) === Number(id)) {
|
||||
// finalData = item;
|
||||
// // break;
|
||||
// }
|
||||
// });
|
||||
// const resData: successMockApiProps = fetchMockSuccessFullByOther({
|
||||
// data: finalData,
|
||||
// });
|
||||
// res.json(resData);
|
||||
// },
|
||||
};
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,5 @@
|
||||
// import animateServer from './src/animateServer';
|
||||
import animatePic from './src/animatePic';
|
||||
|
||||
// export const AnimateServer = animateServer;
|
||||
export const AnimatePic = animatePic;
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* @Author: donghao donghao@supervision.ltd
|
||||
* @Date: 2024-05-08 17:33:43
|
||||
* @LastEditors: donghao donghao@supervision.ltd
|
||||
* @LastEditTime: 2024-05-08 17:45:06
|
||||
* @FilePath: \general-ai-platform-web\src\components\Animate\src\animatePic.tsx
|
||||
* @Description: 图片动效
|
||||
*/
|
||||
import lottie from 'lottie-web'; //引入动效库
|
||||
import React from 'react';
|
||||
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { LottieProps } from '../typing';
|
||||
|
||||
const AnimatePic: React.FC<LottieProps> = (props) => {
|
||||
const animationPic = useRef(null);
|
||||
|
||||
function initAnimate() {
|
||||
console.log(lottie, 'lottie', props);
|
||||
lottie.loadAnimation({
|
||||
container: animationPic.current, //选择渲染dom
|
||||
renderer: 'svg', //渲染格式
|
||||
loop: true, //循环播放
|
||||
autoplay: true, //是否i自动播放,
|
||||
animationData: props.value, //渲染动效json
|
||||
});
|
||||
}
|
||||
useEffect(() => {
|
||||
initAnimate();
|
||||
}, []);
|
||||
|
||||
return <div ref={animationPic} />;
|
||||
};
|
||||
|
||||
export default AnimatePic;
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* @Author: donghao donghao@supervision.ltd
|
||||
* @Date: 2024-05-08 17:33:43
|
||||
* @LastEditors: donghao donghao@supervision.ltd
|
||||
* @LastEditTime: 2024-05-08 17:47:09
|
||||
* @FilePath: \general-ai-platform-web\src\components\Animate\src\animateServer.tsx
|
||||
* @Description: 服务器动效
|
||||
*/
|
||||
import lottie from 'lottie-web'; //引入动效库
|
||||
import React from 'react';
|
||||
// import json01 from '../../../../public/animate/device/01.json'; //引入下载的动效json
|
||||
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { LottieProps } from '../typing';
|
||||
|
||||
const AnimateServer: React.FC<LottieProps> = (props) => {
|
||||
const animation1 = useRef(null);
|
||||
|
||||
function initAnimate() {
|
||||
console.log(lottie, 'lottie', props);
|
||||
lottie.loadAnimation({
|
||||
container: animation1.current, //选择渲染dom
|
||||
renderer: 'svg', //渲染格式
|
||||
loop: true, //循环播放
|
||||
autoplay: true, //是否i自动播放,
|
||||
// animationData: json01, //渲染动效json
|
||||
});
|
||||
}
|
||||
useEffect(() => {
|
||||
initAnimate();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div style={{ width: 100 }}>
|
||||
<div ref={animation1} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AnimateServer;
|
@ -0,0 +1,3 @@
|
||||
export interface LottieProps {
|
||||
value: any;
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
import commButton from './src/commButton';
|
||||
import textButton from './src/textButton';
|
||||
|
||||
export const CommButton = commButton;
|
||||
export const TextButton = textButton;
|
||||
|
@ -0,0 +1,3 @@
|
||||
.text_btn_box {
|
||||
// font-size: 12px;
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* @Author: donghao donghao@supervision.ltd
|
||||
* @Date: 2024-05-08 09:42:31
|
||||
* @LastEditors: donghao donghao@supervision.ltd
|
||||
* @LastEditTime: 2024-05-09 14:18:48
|
||||
* @FilePath: \general-ai-platform-web\src\components\Button\src\textButton.tsx
|
||||
* @Description: 文字按钮
|
||||
*/
|
||||
import React from 'react';
|
||||
import { TextButtonProps } from '../typing';
|
||||
import './button.less';
|
||||
const TextButton: React.FC<TextButtonProps> = (props) => {
|
||||
const { buttonLabel } = props;
|
||||
return (
|
||||
<span
|
||||
className={`text_btn_box ${props?.buttonType === 'danger' ? 'text_active_2' : ''} ${
|
||||
props?.buttonType === 'primary' ? 'text_primary' : ''
|
||||
}`}
|
||||
>
|
||||
{buttonLabel}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
export default TextButton;
|
@ -1,4 +1,17 @@
|
||||
/*
|
||||
* @Author: donghao donghao@supervision.ltd
|
||||
* @Date: 2024-04-19 17:10:21
|
||||
* @LastEditors: donghao donghao@supervision.ltd
|
||||
* @LastEditTime: 2024-05-09 14:07:59
|
||||
* @FilePath: \general-ai-platform-web\src\components\Button\typing.ts
|
||||
* @Description: 按钮类型
|
||||
*/
|
||||
export interface CommButtonProps extends ButtonProps {
|
||||
prevIcon?: React.ReactNode;
|
||||
buttonLabel: string | React.ReactNode;
|
||||
}
|
||||
|
||||
export interface TextButtonProps extends ButtonProps {
|
||||
buttonLabel: string | React.ReactNode;
|
||||
buttonType: 'danger' | 'primary' | 'default' | undefined;
|
||||
}
|
||||
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* @Author: donghao donghao@supervision.ltd
|
||||
* @Date: 2024-04-28 15:30:31
|
||||
* @LastEditors: donghao donghao@supervision.ltd
|
||||
* @LastEditTime: 2024-05-10 15:03:03
|
||||
* @FilePath: \general-ai-platform-web\src\enums\device.ts
|
||||
* @Description: 节点、设备 枚举值
|
||||
*/
|
||||
// 节点设置模块
|
||||
export const deviceGroupEnums: Record<string, any>[] = [
|
||||
{
|
||||
label: '设备列表',
|
||||
key: '1',
|
||||
},
|
||||
{
|
||||
label: '业务模型部署',
|
||||
key: '2',
|
||||
},
|
||||
{
|
||||
label: '告警设置',
|
||||
key: '3',
|
||||
},
|
||||
];
|
||||
// 设备状态
|
||||
export const deviceStateEnums: DICTENUM.DICT_TAB_ITEM[] = [
|
||||
{
|
||||
label: '全部状态',
|
||||
key: '0',
|
||||
},
|
||||
{
|
||||
label: '在线',
|
||||
key: '1',
|
||||
className: 'online_info',
|
||||
},
|
||||
{
|
||||
label: '离线',
|
||||
key: '2',
|
||||
className: 'outline_info',
|
||||
},
|
||||
{
|
||||
label: '运行中',
|
||||
key: '3',
|
||||
className: 'process_info',
|
||||
},
|
||||
{
|
||||
label: '故障',
|
||||
key: '4',
|
||||
className: 'error_info',
|
||||
},
|
||||
];
|
||||
|
||||
// 服务器状态详情
|
||||
export const bsDeviceDetailEnums: DICTENUM.DICT_TAB_ITEM[] = [
|
||||
{
|
||||
label: '设备信息',
|
||||
key: '0',
|
||||
},
|
||||
{
|
||||
label: '设备日志',
|
||||
key: '1',
|
||||
},
|
||||
];
|
@ -1,23 +0,0 @@
|
||||
/*
|
||||
* @Author: donghao donghao@supervision.ltd
|
||||
* @Date: 2024-04-28 15:30:31
|
||||
* @LastEditors: donghao donghao@supervision.ltd
|
||||
* @LastEditTime: 2024-04-28 15:32:43
|
||||
* @FilePath: \general-ai-platform-web\src\enums\device.ts
|
||||
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
||||
*/
|
||||
// 告警规则
|
||||
export const deviceGroupEnums: Record<string, any>[] = [
|
||||
{
|
||||
label: '设备列表',
|
||||
key: '1',
|
||||
},
|
||||
{
|
||||
label: '业务模型部署',
|
||||
key: '2',
|
||||
},
|
||||
{
|
||||
label: '告警设置',
|
||||
key: '3',
|
||||
},
|
||||
];
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* @Author: donghao donghao@supervision.ltd
|
||||
* @Date: 2024-04-28 15:30:31
|
||||
* @LastEditors: donghao donghao@supervision.ltd
|
||||
* @LastEditTime: 2024-05-09 14:35:52
|
||||
* @FilePath: \general-ai-platform-web\src\enums\server.ts
|
||||
* @Description: 服务器 枚举值
|
||||
*/
|
||||
// 服务器状态
|
||||
export const serverStateEnums: DICTENUM.DICT_TAB_ITEM[] = [
|
||||
{
|
||||
label: '全部状态',
|
||||
key: '0',
|
||||
},
|
||||
{
|
||||
label: '在线',
|
||||
key: '1',
|
||||
className: 'online_info',
|
||||
},
|
||||
{
|
||||
label: '离线',
|
||||
key: '2',
|
||||
className: 'outline_info',
|
||||
},
|
||||
];
|
||||
// 服务器状态详情
|
||||
export const bsServerDetailEnums: DICTENUM.DICT_TAB_ITEM[] = [
|
||||
{
|
||||
label: '服务器信息',
|
||||
key: '0',
|
||||
},
|
||||
{
|
||||
label: '服务器日志',
|
||||
key: '1',
|
||||
},
|
||||
];
|
@ -0,0 +1,102 @@
|
||||
@font-face {
|
||||
font-family: "iconfont";
|
||||
/* Project id 4530966 */
|
||||
src: url('//at.alicdn.com/t/c/font_4530966_1jxithnpibx.woff2?t=1715311346156') format('woff2'), url('//at.alicdn.com/t/c/font_4530966_1jxithnpibx.woff?t=1715311346156') format('woff'), url('//at.alicdn.com/t/c/font_4530966_1jxithnpibx.ttf?t=1715311346156') format('truetype');
|
||||
}
|
||||
.iconfont {
|
||||
font-family: "iconfont" !important;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
.icon-fuzhi:before {
|
||||
content: "\e719";
|
||||
}
|
||||
.icon-zip:before {
|
||||
content: "\e71a";
|
||||
}
|
||||
.icon-shangchuanwenjian:before {
|
||||
content: "\e718";
|
||||
}
|
||||
.icon-you:before {
|
||||
content: "\e717";
|
||||
}
|
||||
.icon-delete:before {
|
||||
content: "\e716";
|
||||
}
|
||||
.icon-tianjiafenlei:before {
|
||||
content: "\e714";
|
||||
}
|
||||
.icon-shanchufenlei:before {
|
||||
content: "\e715";
|
||||
}
|
||||
.icon-tianjiajiedian:before {
|
||||
content: "\e713";
|
||||
}
|
||||
.icon-banbenxinxi:before {
|
||||
content: "\e711";
|
||||
}
|
||||
.icon-shiyonghangye:before {
|
||||
content: "\e712";
|
||||
}
|
||||
.icon-jiedianshezhi:before {
|
||||
content: "\e70f";
|
||||
}
|
||||
.icon-fuwuqizhuangtai:before {
|
||||
content: "\e710";
|
||||
}
|
||||
.icon-yewumoxing:before {
|
||||
content: "\e70b";
|
||||
}
|
||||
.icon-shouye:before {
|
||||
content: "\e70c";
|
||||
}
|
||||
.icon-shebeizhuangtai:before {
|
||||
content: "\e70d";
|
||||
}
|
||||
.icon-qiyexinxi:before {
|
||||
content: "\e70e";
|
||||
}
|
||||
.icon-moxingliebiao-unselected:before {
|
||||
content: "\e709";
|
||||
}
|
||||
.icon-moxingyunhangku-selected:before {
|
||||
content: "\e70a";
|
||||
}
|
||||
.icon-wen:before {
|
||||
content: "\e704";
|
||||
}
|
||||
.icon-xia:before {
|
||||
content: "\e705";
|
||||
}
|
||||
.icon-moxingliebiao-selected:before {
|
||||
content: "\e706";
|
||||
}
|
||||
.icon-moxingyunhangku-unselected:before {
|
||||
content: "\e707";
|
||||
}
|
||||
.icon-close:before {
|
||||
content: "\e708";
|
||||
}
|
||||
.icon-moxingshuliang:before {
|
||||
content: "\e6fd";
|
||||
}
|
||||
.icon-shebeishuliang:before {
|
||||
content: "\e6fe";
|
||||
}
|
||||
.icon-xinjian:before {
|
||||
content: "\e6ff";
|
||||
}
|
||||
.icon-gengduo:before {
|
||||
content: "\e700";
|
||||
}
|
||||
.icon-chuangjianshijian:before {
|
||||
content: "\e701";
|
||||
}
|
||||
.icon-search:before {
|
||||
content: "\e702";
|
||||
}
|
||||
.icon-refresh:before {
|
||||
content: "\e703";
|
||||
}
|
@ -0,0 +1,134 @@
|
||||
@font-face {
|
||||
font-family: 'iconfont'; /* Project id 4530966 */
|
||||
src: url('//at.alicdn.com/t/c/font_4530966_1jxithnpibx.woff2?t=1715311346156') format('woff2'),
|
||||
url('//at.alicdn.com/t/c/font_4530966_1jxithnpibx.woff?t=1715311346156') format('woff'),
|
||||
url('//at.alicdn.com/t/c/font_4530966_1jxithnpibx.ttf?t=1715311346156') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
font-size: 16px;
|
||||
font-family: 'iconfont' !important;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-fuzhi:before {
|
||||
content: '\e719';
|
||||
}
|
||||
|
||||
.icon-zip:before {
|
||||
content: '\e71a';
|
||||
}
|
||||
|
||||
.icon-shangchuanwenjian:before {
|
||||
content: '\e718';
|
||||
}
|
||||
|
||||
.icon-you:before {
|
||||
content: '\e717';
|
||||
}
|
||||
|
||||
.icon-delete:before {
|
||||
content: '\e716';
|
||||
}
|
||||
|
||||
.icon-tianjiafenlei:before {
|
||||
content: '\e714';
|
||||
}
|
||||
|
||||
.icon-shanchufenlei:before {
|
||||
content: '\e715';
|
||||
}
|
||||
|
||||
.icon-tianjiajiedian:before {
|
||||
content: '\e713';
|
||||
}
|
||||
|
||||
.icon-banbenxinxi:before {
|
||||
content: '\e711';
|
||||
}
|
||||
|
||||
.icon-shiyonghangye:before {
|
||||
content: '\e712';
|
||||
}
|
||||
|
||||
.icon-jiedianshezhi:before {
|
||||
content: '\e70f';
|
||||
}
|
||||
|
||||
.icon-fuwuqizhuangtai:before {
|
||||
content: '\e710';
|
||||
}
|
||||
|
||||
.icon-yewumoxing:before {
|
||||
content: '\e70b';
|
||||
}
|
||||
|
||||
.icon-shouye:before {
|
||||
content: '\e70c';
|
||||
}
|
||||
|
||||
.icon-shebeizhuangtai:before {
|
||||
content: '\e70d';
|
||||
}
|
||||
|
||||
.icon-qiyexinxi:before {
|
||||
content: '\e70e';
|
||||
}
|
||||
|
||||
.icon-moxingliebiao-unselected:before {
|
||||
content: '\e709';
|
||||
}
|
||||
|
||||
.icon-moxingyunhangku-selected:before {
|
||||
content: '\e70a';
|
||||
}
|
||||
|
||||
.icon-wen:before {
|
||||
content: '\e704';
|
||||
}
|
||||
|
||||
.icon-xia:before {
|
||||
content: '\e705';
|
||||
}
|
||||
|
||||
.icon-moxingliebiao-selected:before {
|
||||
content: '\e706';
|
||||
}
|
||||
|
||||
.icon-moxingyunhangku-unselected:before {
|
||||
content: '\e707';
|
||||
}
|
||||
|
||||
.icon-close:before {
|
||||
content: '\e708';
|
||||
}
|
||||
|
||||
.icon-moxingshuliang:before {
|
||||
content: '\e6fd';
|
||||
}
|
||||
|
||||
.icon-shebeishuliang:before {
|
||||
content: '\e6fe';
|
||||
}
|
||||
|
||||
.icon-xinjian:before {
|
||||
content: '\e6ff';
|
||||
}
|
||||
|
||||
.icon-gengduo:before {
|
||||
content: '\e700';
|
||||
}
|
||||
|
||||
.icon-chuangjianshijian:before {
|
||||
content: '\e701';
|
||||
}
|
||||
|
||||
.icon-search:before {
|
||||
content: '\e702';
|
||||
}
|
||||
|
||||
.icon-refresh:before {
|
||||
content: '\e703';
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* @Author: donghao donghao@supervision.ltd
|
||||
* @Date: 2024-05-09 15:21:03
|
||||
* @LastEditors: donghao donghao@supervision.ltd
|
||||
* @LastEditTime: 2024-05-10 14:51:36
|
||||
* @FilePath: \general-ai-platform-web\src\locales\zh-CN\server.ts
|
||||
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
||||
*/
|
||||
|
||||
// 服务器状态
|
||||
export const server_state: { [key: string]: string } = {
|
||||
'server_state.create.form.add': '新建服务器',
|
||||
'server_state.table.list.add': '新建服务器',
|
||||
'server_state.table.form.name': '服务器名称',
|
||||
'server_state.table.form.rule.required.name': '请填写服务器名称',
|
||||
'server_state.table.form.ip': 'IP',
|
||||
'server_state.table.form.userName': '用户名',
|
||||
'server_state.table.form.pwd': '密码',
|
||||
'server_state.table.form.defaultPort': '默认端口',
|
||||
'server_state.table.stateLog.list.ip': 'IP',
|
||||
'server_state.table.stateLog.list.defaultPort': '默认端口',
|
||||
'server_state.table.stateLog.list.createTime': '创建时间',
|
||||
|
||||
'server_state.table.detail.echarts.used': '已占用',
|
||||
'server_state.table.detail.echarts.free': '未占用',
|
||||
'server_state.table.detail.echarts.kindName': '名称',
|
||||
'server_state.table.detail.title.params': '服务器参数',
|
||||
'server_state.table.detail.title.info': '硬件信息',
|
||||
'server_state.table.detail.title.task': '当前任务',
|
||||
};
|
@ -0,0 +1,123 @@
|
||||
import { ModalForm, ProForm, ProFormText } from '@ant-design/pro-components';
|
||||
import { FormattedMessage, useIntl } from '@umijs/max';
|
||||
import { Form } from 'antd';
|
||||
import React from 'react';
|
||||
import {
|
||||
proFormSmallItemStyleProps,
|
||||
proFormSmallModelWidth,
|
||||
} from '../../../../../config/defaultForm';
|
||||
|
||||
export type CreateDeviceFormProps = {
|
||||
createModalOpen: boolean;
|
||||
handleModal: () => void;
|
||||
reload: any;
|
||||
};
|
||||
const CreateServerForm: React.FC<CreateDeviceFormProps> = (props) => {
|
||||
const intl = useIntl();
|
||||
const [form] = Form.useForm<API.ModelCategory>();
|
||||
|
||||
return (
|
||||
<ModalForm<API.ModelCategory>
|
||||
className="gn_modal_form gn_form"
|
||||
width={proFormSmallModelWidth}
|
||||
title={intl.formatMessage({
|
||||
id: 'server_state.create.form.add',
|
||||
defaultMessage: '新建',
|
||||
})}
|
||||
open={props.createModalOpen}
|
||||
form={form}
|
||||
autoFocusFirstInput
|
||||
modalProps={{
|
||||
destroyOnClose: true,
|
||||
onCancel: () => props.handleModal(),
|
||||
}}
|
||||
submitTimeout={2000}
|
||||
onFinish={async (values) => {
|
||||
console.log(values, 'add_finish_values');
|
||||
// TODO 对接新增接口
|
||||
props.handleModal();
|
||||
return true;
|
||||
}}
|
||||
>
|
||||
<ProForm.Group>
|
||||
<ProFormText
|
||||
width={proFormSmallItemStyleProps.column2Width}
|
||||
name="name"
|
||||
label={<FormattedMessage id="server_state.table.form.name" defaultMessage="名称" />}
|
||||
placeholder={`${intl.formatMessage({
|
||||
id: 'common.please_input',
|
||||
defaultMessage: '$$$',
|
||||
})}${intl.formatMessage({
|
||||
id: 'server_state.table.form.name',
|
||||
defaultMessage: '$$$',
|
||||
})}`}
|
||||
required={true}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: (
|
||||
<FormattedMessage
|
||||
id="server_state.table.form.rule.required.name"
|
||||
defaultMessage="名称必填"
|
||||
/>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<ProFormText
|
||||
width={proFormSmallItemStyleProps.column2Width}
|
||||
name="ip"
|
||||
label={<FormattedMessage id="server_state.table.form.ip" defaultMessage="IP" />}
|
||||
placeholder={`${intl.formatMessage({
|
||||
id: 'common.please_input',
|
||||
defaultMessage: '$$$',
|
||||
})}${intl.formatMessage({
|
||||
id: 'server_state.table.form.ip',
|
||||
defaultMessage: '$$$',
|
||||
})}`}
|
||||
/>
|
||||
|
||||
<ProFormText
|
||||
width={proFormSmallItemStyleProps.column2Width}
|
||||
name="userName"
|
||||
label={<FormattedMessage id="server_state.table.form.userName" defaultMessage="用户名" />}
|
||||
placeholder={`${intl.formatMessage({
|
||||
id: 'common.please_input',
|
||||
defaultMessage: '$$$',
|
||||
})}${intl.formatMessage({
|
||||
id: 'server_state.table.form.userName',
|
||||
defaultMessage: '$$$',
|
||||
})}`}
|
||||
/>
|
||||
<ProFormText.Password
|
||||
width={proFormSmallItemStyleProps.column2Width}
|
||||
label={<FormattedMessage id="server_state.table.form.pwd" defaultMessage="密码" />}
|
||||
name="pwd"
|
||||
placeholder={`${intl.formatMessage({
|
||||
id: 'common.please_input',
|
||||
defaultMessage: '$$$',
|
||||
})}${intl.formatMessage({
|
||||
id: 'server_state.table.form.pwd',
|
||||
defaultMessage: '$$$',
|
||||
})}`}
|
||||
/>
|
||||
|
||||
<ProFormText
|
||||
width={proFormSmallItemStyleProps.width}
|
||||
name="defaultPort"
|
||||
label={
|
||||
<FormattedMessage id="server_state.table.form.defaultPort" defaultMessage="默认端口" />
|
||||
}
|
||||
placeholder={`${intl.formatMessage({
|
||||
id: 'common.please_input',
|
||||
defaultMessage: '$$$',
|
||||
})}${intl.formatMessage({
|
||||
id: 'server_state.table.form.defaultPort',
|
||||
defaultMessage: '$$$',
|
||||
})}`}
|
||||
/>
|
||||
</ProForm.Group>
|
||||
</ModalForm>
|
||||
);
|
||||
};
|
||||
export default CreateServerForm;
|
@ -0,0 +1,358 @@
|
||||
/*
|
||||
* @Author: donghao donghao@supervision.ltd
|
||||
* @Date: 2024-04-08 16:57:30
|
||||
* @LastEditors: donghao donghao@supervision.ltd
|
||||
* @LastEditTime: 2024-05-10 15:12:44
|
||||
* @FilePath: \general-ai-manage\src\pages\Project\BusinessProject\components\detailDeviceState.tsx
|
||||
* @Description: 设备详情
|
||||
* @交互说明
|
||||
*
|
||||
*/
|
||||
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 { FormattedMessage, useIntl } from '@umijs/max';
|
||||
import { Modal, Tabs } from 'antd';
|
||||
import * as echarts from 'echarts';
|
||||
import ReactEcharts from 'echarts-for-react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { proFormMaxModelWidth } from '../../../../../config/defaultForm';
|
||||
import DetailDeviceStateLog from './detailDeviceStateLog';
|
||||
type DetailDeviceStateProps = {
|
||||
info: Record<string, any>;
|
||||
detailOpen: boolean;
|
||||
closeModal: () => void;
|
||||
};
|
||||
|
||||
const DetailDeviceState: React.FC<DetailDeviceStateProps> = ({ info, 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 [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.deviceType" defaultMessage="设备分类" />,
|
||||
dataIndex: 'deviceType',
|
||||
},
|
||||
{
|
||||
title: <FormattedMessage id="device_state.table.form.name" defaultMessage="设备名称" />,
|
||||
dataIndex: 'name',
|
||||
},
|
||||
{
|
||||
title: <FormattedMessage id="device_state.table.form.remark" defaultMessage="备注" />,
|
||||
dataIndex: 'remark',
|
||||
},
|
||||
];
|
||||
|
||||
// 硬件信息环形图
|
||||
const fetchOptionByData = (record) => {
|
||||
const totalCount = 100 * Math.floor(Math.random() * 15);
|
||||
const currData = [
|
||||
{
|
||||
value: record?.percent * totalCount,
|
||||
name: `${intl.formatMessage({
|
||||
id: 'device_state.table.detail.echarts.used',
|
||||
defaultMessage: '已占用',
|
||||
})}`,
|
||||
},
|
||||
{
|
||||
value: totalCount - record?.percent * totalCount,
|
||||
name: `${intl.formatMessage({
|
||||
id: 'device_state.table.detail.echarts.free',
|
||||
defaultMessage: '未占用',
|
||||
})}`,
|
||||
},
|
||||
];
|
||||
|
||||
let currNames = [];
|
||||
currData.forEach((item) => {
|
||||
currNames.push(item.name);
|
||||
});
|
||||
console.log(record, 'fetchOptionByData_record');
|
||||
return {
|
||||
title: {
|
||||
text: record.label,
|
||||
x: 'center',
|
||||
y: '16.2%',
|
||||
textStyle: {
|
||||
fontSize: 16, // 标题文字大小
|
||||
},
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{a} <br/>{b} : {c} ({d}%)',
|
||||
},
|
||||
legend: {
|
||||
orient: 'horizontal',
|
||||
top: '37%',
|
||||
data: currNames,
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '名称',
|
||||
type: 'pie',
|
||||
center: ['50%', '20%'], // 调整 center 属性使饼图偏上
|
||||
radius: ['28%', '45%'], // 控制环形图大小
|
||||
color: [
|
||||
new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{
|
||||
offset: 0,
|
||||
color: record.usedColors[0],
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: record.usedColors[1],
|
||||
},
|
||||
]),
|
||||
new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{
|
||||
offset: 0,
|
||||
color: record.freeColors[0],
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: record.freeColors[1],
|
||||
},
|
||||
]),
|
||||
],
|
||||
avoidLabelOverlap: false,
|
||||
label: {
|
||||
show: false,
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
show: false,
|
||||
fontSize: '20',
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
},
|
||||
labelLine: {
|
||||
show: false,
|
||||
},
|
||||
data: currData,
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
||||
|
||||
// 模型列表信息
|
||||
const columns: ProColumns<Record<string, any>>[] = [
|
||||
{
|
||||
title: <FormattedMessage id="base_model.table.list.name" defaultMessage="基础模型名称" />,
|
||||
dataIndex: 'name',
|
||||
hideInSearch: true,
|
||||
key: 'fixedName',
|
||||
fixed: 'left',
|
||||
width: '45%',
|
||||
},
|
||||
{
|
||||
title: <FormattedMessage id="base_model.table.list.version" defaultMessage="版本" />,
|
||||
dataIndex: 'version',
|
||||
hideInSearch: true,
|
||||
width: '20%',
|
||||
},
|
||||
{
|
||||
title: (
|
||||
<FormattedMessage id="base_model.table.list.runtimeLibFile" defaultMessage="运行库镜像" />
|
||||
),
|
||||
dataIndex: 'runtimeLibFile',
|
||||
hideInSearch: true,
|
||||
render: (dom, record) => {
|
||||
return (
|
||||
<div>
|
||||
{record.runtimeLibFile ? (
|
||||
dom
|
||||
) : (
|
||||
<div className={`gn_list_type_tag flex items-center justify-center active2`}>
|
||||
<span className="dot"></span>
|
||||
<span>
|
||||
<FormattedMessage
|
||||
id="base_model.table.list.undeployed.runtimeLibFile"
|
||||
defaultMessage="未部署"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
// 将数据组装成reactDom
|
||||
function toListDomByData(record) {
|
||||
let startList = [...record];
|
||||
let finalList = startList.map((item) => ({
|
||||
content: (
|
||||
<div>
|
||||
<div className="gn_list_card_title pb-[12px]">
|
||||
<span></span>
|
||||
<span>{item.name}</span>
|
||||
</div>
|
||||
<ProTable
|
||||
className="gn_pro_table mb-[16px]"
|
||||
cardProps={{
|
||||
bodyStyle: { padding: 0, margin: 0 },
|
||||
}}
|
||||
// 标题栏
|
||||
search={false}
|
||||
options={{ fullScreen: false, setting: false, density: false, reload: false }}
|
||||
rowKey="id"
|
||||
onDataSourceChange={(data) => {
|
||||
console.log(data, 'onDataSourceChange_data');
|
||||
}}
|
||||
pagination={false}
|
||||
dataSource={item.list}
|
||||
columns={columns}
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
}));
|
||||
setModelData(finalList);
|
||||
console.log(finalList, 'toListDomByData_finalList');
|
||||
}
|
||||
|
||||
// 基础模型列表数据api
|
||||
async function fetchData() {
|
||||
const resp = await getModelGroupBaseModelList();
|
||||
if (isSuccessApi(resp)) {
|
||||
toListDomByData(resp.data.results);
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setForceRender(detailOpen);
|
||||
}, [detailOpen]);
|
||||
|
||||
// 初始化加载
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
width={proFormMaxModelWidth}
|
||||
title={info?.deviceSort}
|
||||
open={detailOpen}
|
||||
onCancel={closeModal}
|
||||
footer={null}
|
||||
afterVisibleChange={(isVisible) => {
|
||||
if (!isVisible) {
|
||||
setForceRender(false); // Modal 关闭时重置状态
|
||||
}
|
||||
}}
|
||||
>
|
||||
<ProCard className="gn_card" bodyStyle={{ padding: 0 }}>
|
||||
<Tabs
|
||||
className="gn_tabs"
|
||||
activeKey={tabKey}
|
||||
items={tabs}
|
||||
onChange={(key) => {
|
||||
setTabKey(key);
|
||||
}}
|
||||
></Tabs>
|
||||
{tabKey === '0' && (
|
||||
<div>
|
||||
<ProCard className="gn_card bs_server_info_wrap" bodyStyle={{ padding: 0 }}>
|
||||
<ul>
|
||||
<li className="pb-[8px]">
|
||||
<p className="head4">
|
||||
<FormattedMessage
|
||||
id="device_state.table.detail.title.params"
|
||||
defaultMessage="设备参数"
|
||||
/>
|
||||
</p>
|
||||
<div className="my-[8px] gn_active_descriptions bg_active_4">
|
||||
<ProDescriptions
|
||||
column={4}
|
||||
columns={ModelDetailColumns}
|
||||
dataSource={info}
|
||||
></ProDescriptions>
|
||||
</div>
|
||||
</li>
|
||||
<li className="pb-[16px]">
|
||||
<p className="head4">
|
||||
<FormattedMessage
|
||||
id="device_state.table.detail.title.info"
|
||||
defaultMessage="硬件信息"
|
||||
/>
|
||||
</p>
|
||||
<ul className="mt-[8px] flex items-center ">
|
||||
{detailOpen &&
|
||||
info?.progressData?.map((item, index) => {
|
||||
return (
|
||||
<li
|
||||
key={index}
|
||||
className={`w-[25%] bg_active_4 rounded ${
|
||||
index !== 0 ? 'ml-[10px]' : ''
|
||||
}`}
|
||||
>
|
||||
<div style={{ height: '140px' }}>
|
||||
{forceRender && (
|
||||
<ReactEcharts echarts={echarts} option={fetchOptionByData(item)} />
|
||||
)}
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</li>
|
||||
<li className="pb-[8px] bs_server_task_wrap">
|
||||
<p className="head4">
|
||||
<FormattedMessage
|
||||
id="device_state.table.detail.title.task"
|
||||
defaultMessage="当前任务"
|
||||
/>
|
||||
</p>
|
||||
<div className="pt-[8px]">
|
||||
<ProList<{ title: string }>
|
||||
itemLayout="vertical"
|
||||
itemCardProps={{
|
||||
ghost: true,
|
||||
bodyStyle: { padding: 0, margin: 0 },
|
||||
style: {
|
||||
width: '100%',
|
||||
border: 0,
|
||||
},
|
||||
}}
|
||||
cardProps={{
|
||||
style: { padding: 0, margin: 0 }, // 设置卡片的内外边距为 0
|
||||
bodyStyle: {
|
||||
padding: 0,
|
||||
margin: 0,
|
||||
height: 'calc(300px)',
|
||||
overflow: 'scroll',
|
||||
},
|
||||
}}
|
||||
rowKey="id"
|
||||
dataSource={modelData}
|
||||
pagination={false}
|
||||
rowSelection={false}
|
||||
metas={{
|
||||
content: {
|
||||
style: { margin: 0, padding: 0 },
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</ProCard>
|
||||
</div>
|
||||
)}
|
||||
{tabKey === '1' && <DetailDeviceStateLog />}
|
||||
</ProCard>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default DetailDeviceState;
|
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* @Author: donghao donghao@supervision.ltd
|
||||
* @Date: 2024-04-22 15:23:36
|
||||
* @LastEditors: donghao donghao@supervision.ltd
|
||||
* @LastEditTime: 2024-05-10 17:07:15
|
||||
* @FilePath: \general-ai-platform-web\src\pages\Business\BusinessState\components\detailDeviceStateLog.tsx
|
||||
* @Description: 设备日志
|
||||
* @交互说明
|
||||
* 1、设备日志列表的分页展示
|
||||
*/
|
||||
|
||||
import { getDeviceStateLogList } from '@/services/testApi/businessState';
|
||||
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 = () => {
|
||||
const actionRef = useRef<ActionType>();
|
||||
// 动态设置每页数量
|
||||
const [currentPageSize, setCurrentPageSize] = useState<number>(10);
|
||||
// 业务模型列表信息
|
||||
const columns: ProColumns<Record<string, any>>[] = [
|
||||
{
|
||||
title: <FormattedMessage id="device_state.table.stateLog.list.ip" defaultMessage="名称" />,
|
||||
dataIndex: 'IP',
|
||||
hideInSearch: true,
|
||||
key: 'fixedName',
|
||||
fixed: 'left',
|
||||
width: '40%',
|
||||
},
|
||||
{
|
||||
title: (
|
||||
<FormattedMessage id="device_state.table.stateLog.list.runTime" defaultMessage="运行时长" />
|
||||
),
|
||||
dataIndex: 'runTime',
|
||||
hideInSearch: true,
|
||||
width: '20%',
|
||||
},
|
||||
{
|
||||
title: (
|
||||
<FormattedMessage
|
||||
id="device_state.table.stateLog.list.updateTime"
|
||||
defaultMessage="更新时间"
|
||||
/>
|
||||
),
|
||||
dataIndex: 'updateTime',
|
||||
hideInSearch: true,
|
||||
valueType: 'dateTime',
|
||||
},
|
||||
];
|
||||
return (
|
||||
<div className="detailDeviceStateLog_wrap">
|
||||
<ProCard className="gn_card" bodyStyle={{ padding: 0 }}>
|
||||
<ProTable
|
||||
className="gn_pro_table"
|
||||
cardProps={{
|
||||
bodyStyle: { padding: 0 },
|
||||
}}
|
||||
// 标题栏
|
||||
search={false}
|
||||
options={{ fullScreen: false, setting: false, density: false, reload: false }}
|
||||
actionRef={actionRef}
|
||||
rowKey="id"
|
||||
pagination={{
|
||||
...proTablePaginationOptions,
|
||||
pageSize: currentPageSize,
|
||||
onChange: (page, pageSize) => setCurrentPageSize(pageSize),
|
||||
}}
|
||||
columnsState={{
|
||||
persistenceKey: 'bs_server_log_list',
|
||||
persistenceType: 'localStorage',
|
||||
}}
|
||||
request={async (params = {}) => {
|
||||
const { current, ...rest } = params;
|
||||
const reqParams = {
|
||||
page: current,
|
||||
...rest,
|
||||
};
|
||||
let resp = await getDeviceStateLogList({ ...reqParams });
|
||||
console.log(resp, 'getDeviceStateLogList_resp');
|
||||
return {
|
||||
data: resp.data?.results,
|
||||
success: resp.success,
|
||||
total: resp.data.count,
|
||||
current: current,
|
||||
pageSize: currentPageSize,
|
||||
};
|
||||
}}
|
||||
columns={columns}
|
||||
/>
|
||||
</ProCard>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DetailDeviceStateLog;
|
@ -0,0 +1,367 @@
|
||||
/*
|
||||
* @Author: donghao donghao@supervision.ltd
|
||||
* @Date: 2024-04-08 16:57:30
|
||||
* @LastEditors: donghao donghao@supervision.ltd
|
||||
* @LastEditTime: 2024-05-10 15:05:25
|
||||
* @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 { FormattedMessage, useIntl } from '@umijs/max';
|
||||
import { Modal, Tabs } from 'antd';
|
||||
import * as echarts from 'echarts';
|
||||
import ReactEcharts from 'echarts-for-react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { proFormMaxModelWidth } from '../../../../../config/defaultForm';
|
||||
import DetailServerStateLog from './detailServerStateLog';
|
||||
type DetailServerStateProps = {
|
||||
info: Record<string, any>;
|
||||
detailOpen: boolean;
|
||||
closeModal: () => void;
|
||||
};
|
||||
|
||||
const DetailServerState: React.FC<DetailServerStateProps> = ({ info, detailOpen, closeModal }) => {
|
||||
/**state */
|
||||
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 [forceRender, setForceRender] = useState<boolean>(false);
|
||||
|
||||
// 基础模型信息
|
||||
const ModelDetailColumns = [
|
||||
{
|
||||
title: <FormattedMessage id="server_state.table.form.name" defaultMessage="服务器名称" />,
|
||||
dataIndex: 'deviceSort',
|
||||
},
|
||||
{
|
||||
title: <FormattedMessage id="server_state.table.form.ip" defaultMessage="IP" />,
|
||||
dataIndex: 'IP',
|
||||
},
|
||||
{
|
||||
title: (
|
||||
<FormattedMessage id="server_state.table.form.defaultPort" defaultMessage="默认端口" />
|
||||
),
|
||||
dataIndex: 'port',
|
||||
},
|
||||
{
|
||||
title: <FormattedMessage id="server_state.table.form.userName" defaultMessage="用户名" />,
|
||||
dataIndex: 'userName',
|
||||
},
|
||||
{
|
||||
title: <FormattedMessage id="server_state.table.form.pwd" defaultMessage="密码" />,
|
||||
dataIndex: 'pwd',
|
||||
render: () => {
|
||||
return '*********';
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
// 硬件信息环形图
|
||||
const fetchOptionByData = (record) => {
|
||||
const totalCount = 100 * Math.floor(Math.random() * 15);
|
||||
const currData = [
|
||||
{
|
||||
value: record?.percent * totalCount,
|
||||
name: `${intl.formatMessage({
|
||||
id: 'server_state.table.detail.echarts.used',
|
||||
defaultMessage: '已占用',
|
||||
})}`,
|
||||
},
|
||||
{
|
||||
value: totalCount - record?.percent * totalCount,
|
||||
name: `${intl.formatMessage({
|
||||
id: 'server_state.table.detail.echarts.free',
|
||||
defaultMessage: '未占用',
|
||||
})}`,
|
||||
},
|
||||
];
|
||||
|
||||
let currNames = [];
|
||||
currData.forEach((item) => {
|
||||
currNames.push(item.name);
|
||||
});
|
||||
console.log(record, 'fetchOptionByData_record');
|
||||
return {
|
||||
title: {
|
||||
text: record.label,
|
||||
x: 'center',
|
||||
y: '16.2%',
|
||||
textStyle: {
|
||||
fontSize: 16, // 标题文字大小
|
||||
},
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{a} <br/>{b} : {c} ({d}%)',
|
||||
},
|
||||
legend: {
|
||||
orient: 'horizontal',
|
||||
top: '37%',
|
||||
data: currNames,
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '名称',
|
||||
type: 'pie',
|
||||
center: ['50%', '20%'], // 调整 center 属性使饼图偏上
|
||||
radius: ['28%', '45%'], // 控制环形图大小
|
||||
color: [
|
||||
new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{
|
||||
offset: 0,
|
||||
color: record.usedColors[0],
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: record.usedColors[1],
|
||||
},
|
||||
]),
|
||||
new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{
|
||||
offset: 0,
|
||||
color: record.freeColors[0],
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: record.freeColors[1],
|
||||
},
|
||||
]),
|
||||
],
|
||||
avoidLabelOverlap: false,
|
||||
label: {
|
||||
show: false,
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
show: false,
|
||||
fontSize: '20',
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
},
|
||||
labelLine: {
|
||||
show: false,
|
||||
},
|
||||
data: currData,
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
||||
|
||||
// 模型列表信息
|
||||
const columns: ProColumns<Record<string, any>>[] = [
|
||||
{
|
||||
title: <FormattedMessage id="base_model.table.list.name" defaultMessage="基础模型名称" />,
|
||||
dataIndex: 'name',
|
||||
hideInSearch: true,
|
||||
key: 'fixedName',
|
||||
fixed: 'left',
|
||||
width: '45%',
|
||||
},
|
||||
{
|
||||
title: <FormattedMessage id="base_model.table.list.version" defaultMessage="版本" />,
|
||||
dataIndex: 'version',
|
||||
hideInSearch: true,
|
||||
width: '20%',
|
||||
},
|
||||
{
|
||||
title: (
|
||||
<FormattedMessage id="base_model.table.list.runtimeLibFile" defaultMessage="运行库镜像" />
|
||||
),
|
||||
dataIndex: 'runtimeLibFile',
|
||||
hideInSearch: true,
|
||||
render: (dom, record) => {
|
||||
return (
|
||||
<div>
|
||||
{record.runtimeLibFile ? (
|
||||
dom
|
||||
) : (
|
||||
<div className={`gn_list_type_tag flex items-center justify-center active2`}>
|
||||
<span className="dot"></span>
|
||||
<span>
|
||||
<FormattedMessage
|
||||
id="base_model.table.list.undeployed.runtimeLibFile"
|
||||
defaultMessage="未部署"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
// 将数据组装成reactDom
|
||||
function toListDomByData(record) {
|
||||
let startList = [...record];
|
||||
let finalList = startList.map((item) => ({
|
||||
content: (
|
||||
<div>
|
||||
<div className="gn_list_card_title pb-[12px]">
|
||||
<span></span>
|
||||
<span>{item.name}</span>
|
||||
</div>
|
||||
<ProTable
|
||||
className="gn_pro_table mb-[16px]"
|
||||
cardProps={{
|
||||
bodyStyle: { padding: 0, margin: 0 },
|
||||
}}
|
||||
// 标题栏
|
||||
search={false}
|
||||
options={{ fullScreen: false, setting: false, density: false, reload: false }}
|
||||
rowKey="id"
|
||||
onDataSourceChange={(data) => {
|
||||
console.log(data, 'onDataSourceChange_data');
|
||||
}}
|
||||
pagination={false}
|
||||
dataSource={item.list}
|
||||
columns={columns}
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
}));
|
||||
setModelData(finalList);
|
||||
console.log(finalList, 'toListDomByData_finalList');
|
||||
}
|
||||
|
||||
// 基础模型列表数据api
|
||||
async function fetchData() {
|
||||
const resp = await getModelGroupBaseModelList();
|
||||
if (isSuccessApi(resp)) {
|
||||
toListDomByData(resp.data.results);
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setForceRender(detailOpen);
|
||||
}, [detailOpen]);
|
||||
|
||||
// 初始化加载
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
width={proFormMaxModelWidth}
|
||||
title={info?.deviceSort}
|
||||
open={detailOpen}
|
||||
onCancel={closeModal}
|
||||
footer={null}
|
||||
afterVisibleChange={(isVisible) => {
|
||||
if (!isVisible) {
|
||||
setForceRender(false); // Modal 关闭时重置状态
|
||||
}
|
||||
}}
|
||||
>
|
||||
<ProCard className="gn_card" bodyStyle={{ padding: 0 }}>
|
||||
<Tabs
|
||||
className="gn_tabs"
|
||||
activeKey={tabKey}
|
||||
items={tabs}
|
||||
onChange={(key) => {
|
||||
setTabKey(key);
|
||||
}}
|
||||
></Tabs>
|
||||
{tabKey === '0' && (
|
||||
<div>
|
||||
<ProCard className="gn_card bs_server_info_wrap" bodyStyle={{ padding: 0 }}>
|
||||
<ul>
|
||||
<li className="pb-[8px]">
|
||||
<p className="head4">
|
||||
<FormattedMessage
|
||||
id="server_state.table.detail.title.params"
|
||||
defaultMessage="服务器参数"
|
||||
/>
|
||||
</p>
|
||||
<div className="my-[8px] gn_active_descriptions bg_active_4">
|
||||
<ProDescriptions
|
||||
column={5}
|
||||
columns={ModelDetailColumns}
|
||||
dataSource={info}
|
||||
></ProDescriptions>
|
||||
</div>
|
||||
</li>
|
||||
<li className="pb-[16px]">
|
||||
<p className="head4">
|
||||
<FormattedMessage
|
||||
id="server_state.table.detail.title.info"
|
||||
defaultMessage="硬件信息"
|
||||
/>
|
||||
</p>
|
||||
<ul className="mt-[8px] flex items-center ">
|
||||
{detailOpen &&
|
||||
info?.progressData?.map((item, index) => {
|
||||
return (
|
||||
<li
|
||||
key={index}
|
||||
className={`w-[25%] bg_active_4 rounded ${
|
||||
index !== 0 ? 'ml-[10px]' : ''
|
||||
}`}
|
||||
>
|
||||
<div style={{ height: '140px' }}>
|
||||
{forceRender && (
|
||||
<ReactEcharts echarts={echarts} option={fetchOptionByData(item)} />
|
||||
)}
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</li>
|
||||
<li className="pb-[8px] bs_server_task_wrap">
|
||||
<p className="head4">
|
||||
<FormattedMessage
|
||||
id="server_state.table.detail.title.task"
|
||||
defaultMessage="当前任务"
|
||||
/>
|
||||
</p>
|
||||
<div className="pt-[8px]">
|
||||
<ProList<{ title: string }>
|
||||
itemLayout="vertical"
|
||||
itemCardProps={{
|
||||
ghost: true,
|
||||
bodyStyle: { padding: 0, margin: 0 },
|
||||
style: {
|
||||
width: '100%',
|
||||
border: 0,
|
||||
},
|
||||
}}
|
||||
cardProps={{
|
||||
style: { padding: 0, margin: 0 }, // 设置卡片的内外边距为 0
|
||||
bodyStyle: {
|
||||
padding: 0,
|
||||
margin: 0,
|
||||
height: 'calc(300px)',
|
||||
overflow: 'scroll',
|
||||
},
|
||||
}}
|
||||
rowKey="id"
|
||||
dataSource={modelData}
|
||||
pagination={false}
|
||||
rowSelection={false}
|
||||
metas={{
|
||||
content: {
|
||||
style: { margin: 0, padding: 0 },
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</ProCard>
|
||||
</div>
|
||||
)}
|
||||
{tabKey === '1' && <DetailServerStateLog />}
|
||||
</ProCard>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default DetailServerState;
|
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* @Author: donghao donghao@supervision.ltd
|
||||
* @Date: 2024-04-22 15:23:36
|
||||
* @LastEditors: donghao donghao@supervision.ltd
|
||||
* @LastEditTime: 2024-05-10 14:44:54
|
||||
* @FilePath: \general-ai-platform-web\src\pages\Business\BusinessState\components\detailServerStateLog.tsx
|
||||
* @Description: 服务器日志
|
||||
* @交互说明
|
||||
* 1、服务器日志列表的分页展示
|
||||
*/
|
||||
|
||||
import { getServerStateLogList } from '@/services/testApi/businessState';
|
||||
import type { ActionType, ProColumns } from '@ant-design/pro-components';
|
||||
import { ProCard, ProTable } from '@ant-design/pro-components';
|
||||
import { FormattedMessage } from '@umijs/max';
|
||||
import { useRef, useState } from 'react';
|
||||
import { proTablePaginationOptions } from '../../../../../config/defaultTable';
|
||||
|
||||
const DetailServerStateLog: React.FC = () => {
|
||||
const actionRef = useRef<ActionType>();
|
||||
// 动态设置每页数量
|
||||
const [currentPageSize, setCurrentPageSize] = useState<number>(10);
|
||||
// 业务模型列表信息
|
||||
const columns: ProColumns<Record<string, any>>[] = [
|
||||
{
|
||||
title: <FormattedMessage id="server_state.table.stateLog.list.ip" defaultMessage="名称" />,
|
||||
dataIndex: 'IP',
|
||||
hideInSearch: true,
|
||||
key: 'fixedName',
|
||||
fixed: 'left',
|
||||
},
|
||||
{
|
||||
title: (
|
||||
<FormattedMessage id="server_state.table.stateLog.list.defaultPort" defaultMessage="端口" />
|
||||
),
|
||||
dataIndex: 'port',
|
||||
hideInSearch: true,
|
||||
},
|
||||
|
||||
{
|
||||
title: (
|
||||
<FormattedMessage
|
||||
id="server_state.table.stateLog.list.createTime"
|
||||
defaultMessage="创建时间"
|
||||
/>
|
||||
),
|
||||
dataIndex: 'createTime',
|
||||
hideInSearch: true,
|
||||
valueType: 'dateTime',
|
||||
},
|
||||
];
|
||||
return (
|
||||
<div className="detailServerStateLog_wrap">
|
||||
<ProCard className="gn_card" bodyStyle={{ padding: 0 }}>
|
||||
<ProTable
|
||||
className="gn_pro_table"
|
||||
cardProps={{
|
||||
bodyStyle: { padding: 0 },
|
||||
}}
|
||||
// 标题栏
|
||||
search={false}
|
||||
options={{ fullScreen: false, setting: false, density: false, reload: false }}
|
||||
actionRef={actionRef}
|
||||
rowKey="key"
|
||||
pagination={{
|
||||
...proTablePaginationOptions,
|
||||
pageSize: currentPageSize,
|
||||
onChange: (page, pageSize) => setCurrentPageSize(pageSize),
|
||||
}}
|
||||
columnsState={{
|
||||
persistenceKey: 'bs_server_log_list',
|
||||
persistenceType: 'localStorage',
|
||||
}}
|
||||
request={async (params = {}) => {
|
||||
const { current, ...rest } = params;
|
||||
const reqParams = {
|
||||
page: current,
|
||||
...rest,
|
||||
};
|
||||
let resp = await getServerStateLogList({ ...reqParams });
|
||||
console.log(resp, 'getServerStateLogList_resp');
|
||||
return {
|
||||
data: resp.data?.results.map((v: Record<string, any>) => {
|
||||
return { ...v, key: v.id };
|
||||
}),
|
||||
success: resp.success,
|
||||
total: resp.data.count,
|
||||
current: current,
|
||||
pageSize: currentPageSize,
|
||||
};
|
||||
}}
|
||||
columns={columns}
|
||||
/>
|
||||
</ProCard>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DetailServerStateLog;
|
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* @Author: donghao donghao@supervision.ltd
|
||||
* @Date: 2024-04-08 16:57:30
|
||||
* @LastEditors: donghao donghao@supervision.ltd
|
||||
* @LastEditTime: 2024-05-10 14:26:02
|
||||
* @FilePath: \general-ai-manage\src\pages\Business\BusinessState\components\deviceStateCard.tsx
|
||||
* @Description: 设备状态项卡片
|
||||
*/
|
||||
import { AnimatePic } from '@/components/Animate';
|
||||
import TableActionCard, { actionsProps } from '@/components/TableActionCard';
|
||||
import { deviceStateEnums } from '@/enums/device';
|
||||
import { Progress } from 'antd';
|
||||
import json01 from '../../../../../public/animate/device/01.json'; //引入下载的动效json
|
||||
|
||||
type DeviceStateCardProps = {
|
||||
info: Record<string, any>;
|
||||
renderActions: actionsProps[];
|
||||
fetchDetail: () => void;
|
||||
};
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
onClick={() => {
|
||||
console.log('服务器详情展示');
|
||||
fetchDetail();
|
||||
}}
|
||||
className={`bs_card_box ${formatStateByVal(info?.state)?.className}`}
|
||||
>
|
||||
<div className="flex justify-between w-full p-[12px] bs_card_header">
|
||||
<div className="flex items-center title_box">
|
||||
<div className="bs_card_name single_line head4">{info?.deviceSort}</div>
|
||||
<div
|
||||
className={`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' : ''}`}
|
||||
>
|
||||
{formatStateByVal(info?.state)?.label}
|
||||
</div>
|
||||
</div>
|
||||
<span>
|
||||
<TableActionCard renderActions={renderActions} maxActionCount={3}></TableActionCard>
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex bs_card_content px-[12px] py-[6px] items-center">
|
||||
<div className="device-content-left w-[100px] mr-[10px]">
|
||||
<AnimatePic value={json01} />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<ul className="w-full">
|
||||
{info?.progressData?.map((v, k) => {
|
||||
return (
|
||||
<li key={k}>
|
||||
<div className="flex rectProgress_box my-[6px]">
|
||||
<div className="pr-[4px] text3 pt-[5px]">{v.label}</div>
|
||||
<div className="flex items-center flex-1">
|
||||
<Progress
|
||||
style={{ padding: 0, margin: 0, borderRadius: 0 }}
|
||||
size={['100%', 10]}
|
||||
height={46}
|
||||
percent={v.percent * 100}
|
||||
strokeColor={v.strokeColor}
|
||||
showInfo={false}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeviceStateCard;
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* @Author: donghao donghao@supervision.ltd
|
||||
* @Date: 2024-04-08 16:57:30
|
||||
* @LastEditors: donghao donghao@supervision.ltd
|
||||
* @LastEditTime: 2024-05-10 14:25:55
|
||||
* @FilePath: \general-ai-manage\src\pages\Business\BusinessState\components\serverStateCard.tsx
|
||||
* @Description: 服务器状态项卡片
|
||||
*/
|
||||
import { AnimatePic } from '@/components/Animate';
|
||||
import TableActionCard, { actionsProps } from '@/components/TableActionCard';
|
||||
import { serverStateEnums } from '@/enums/server';
|
||||
import { Progress } from 'antd';
|
||||
import json01 from '../../../../../public/animate/device/01.json'; //引入下载的动效json
|
||||
|
||||
type ServerStateCardProps = {
|
||||
info: Record<string, any>;
|
||||
renderActions: actionsProps[];
|
||||
fetchDetail: () => void;
|
||||
};
|
||||
|
||||
const ServerStateCard: React.FC<ServerStateCardProps> = ({ info, renderActions, fetchDetail }) => {
|
||||
const formatStateByVal = (record: string): DICTENUM.DICT_TAB_ITEM => {
|
||||
return serverStateEnums.find((item: DICTENUM.DICT_TAB_ITEM) => item.key === record);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
onClick={() => {
|
||||
console.log('服务器详情展示');
|
||||
fetchDetail();
|
||||
}}
|
||||
className={`bs_card_box ${formatStateByVal(info?.state)?.className}`}
|
||||
>
|
||||
<div className="flex justify-between w-full p-[12px] bs_card_header">
|
||||
<div className="flex items-center title_box">
|
||||
<div className="bs_card_name single_line head4">{info?.deviceSort}</div>
|
||||
<div
|
||||
className={`gn_card_tag ml-[8px] text-white ${
|
||||
info?.state === '1' ? 'bg_active_1' : 'bg_gray_color_1'
|
||||
}`}
|
||||
>
|
||||
{formatStateByVal(info?.state).label}
|
||||
</div>
|
||||
</div>
|
||||
<span>
|
||||
<TableActionCard renderActions={renderActions} maxActionCount={3}></TableActionCard>
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex bs_card_content px-[12px] py-[6px] items-center">
|
||||
<div className="server-content-left w-[100px] mr-[10px]">
|
||||
<AnimatePic value={json01} />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<ul className="w-full">
|
||||
{info?.progressData?.map((v, k) => {
|
||||
return (
|
||||
<li key={k}>
|
||||
<div className="flex rectProgress_box my-[6px]">
|
||||
<div className="pr-[4px] text3 pt-[5px]">{v.label}</div>
|
||||
<div className="flex items-center flex-1">
|
||||
<Progress
|
||||
style={{ padding: 0, margin: 0, borderRadius: 0 }}
|
||||
size={['100%', 10]}
|
||||
height={46}
|
||||
percent={v.percent * 100}
|
||||
strokeColor={v.strokeColor}
|
||||
showInfo={false}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ServerStateCard;
|
@ -0,0 +1,26 @@
|
||||
/* 服务器 设备 共用 */
|
||||
.bs_state_page .bs_card_box {
|
||||
width: 100%;
|
||||
background: #f4f8fe;
|
||||
}
|
||||
.bs_state_page .bs_card_box .bs_card_header {
|
||||
background: linear-gradient(90deg, #d5e6fe 0%, rgba(213, 230, 254, 0) 100%);
|
||||
}
|
||||
.bs_state_page .bs_card_box .bs_card_header .bs_card_name {
|
||||
max-width: 100px;
|
||||
}
|
||||
.bs_state_page .bs_card_box.outline_info {
|
||||
background: #f5f5f5;
|
||||
-webkit-filter: grayscale(100%);
|
||||
-moz-filter: grayscale(100%);
|
||||
-ms-filter: grayscale(100%);
|
||||
-o-filter: grayscale(100%);
|
||||
-webkit-filter: gray;
|
||||
-webkit-filter: progid:dximagetransform.microsoft.basicimage(grayscale=1);
|
||||
filter: grayscale(100%);
|
||||
filter: gray;
|
||||
filter: progid:dximagetransform.microsoft.basicimage(grayscale=1);
|
||||
}
|
||||
.bs_state_page .bs_card_box.outline_info .bs_card_header {
|
||||
background: linear-gradient(90deg, #dcdcdc 0%, rgba(245, 245, 245, 0) 100%);
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/* 服务器 设备 共用 */
|
||||
@import url('@/base.less');
|
||||
.bs_state_page {
|
||||
.bs_card_box {
|
||||
width: 100%;
|
||||
background: #f4f8fe;
|
||||
|
||||
.bs_card_header {
|
||||
background: linear-gradient(90deg, #d5e6fe 0%, rgba(213, 230, 254, 0) 100%);
|
||||
.bs_card_name {
|
||||
max-width: 100px;
|
||||
}
|
||||
}
|
||||
// 离线
|
||||
&.outline_info {
|
||||
.gray_info_all();
|
||||
background: #f5f5f5;
|
||||
// .bs_card_header {
|
||||
// background: linear-gradient(90deg, #dcdcdc 0%, rgba(245, 245, 245, 0) 100%);
|
||||
// }
|
||||
}
|
||||
// 在线
|
||||
// &.online_info {
|
||||
// }
|
||||
}
|
||||
}
|
||||
// 基础模型设置
|
||||
.bs_server_task_wrap {
|
||||
.ant-list-items {
|
||||
.ant-list-item {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: none;
|
||||
.ant-pro-list-row-content {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,178 @@
|
||||
/*
|
||||
* @Author: donghao donghao@supervision.ltd
|
||||
* @Date: 2024-04-08 16:57:30
|
||||
* @LastEditors: donghao donghao@supervision.ltd
|
||||
* @LastEditTime: 2024-05-10 17:28:39
|
||||
* @FilePath: \general-ai-manage\src\pages\Project\BusinessProject\components\detailServerState.tsx
|
||||
* @Description: 服务器详情
|
||||
* @交互说明
|
||||
*
|
||||
*/
|
||||
import { getAllDeviceList } from '@/services/testApi/device';
|
||||
import { ProCard, ProColumns, ProDescriptions, ProTable } from '@ant-design/pro-components';
|
||||
import { FormattedMessage, useIntl } from '@umijs/max';
|
||||
import { Modal } from 'antd';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { proFormMaxModelWidth } from '../../../../../config/defaultForm';
|
||||
|
||||
type ModelDeployConfigProps = {
|
||||
info: Record<string, any>;
|
||||
detailOpen: boolean;
|
||||
closeModal: () => void;
|
||||
};
|
||||
|
||||
const ModelDeployConfig: React.FC<ModelDeployConfigProps> = ({ info, detailOpen, closeModal }) => {
|
||||
/**state */
|
||||
const intl = useIntl();
|
||||
const [selectedRows, setSelectedRows] = useState<Record<string, any>[]>([]);
|
||||
const actionRef = useRef();
|
||||
// 基础配置信息
|
||||
const detailColumns = [
|
||||
{
|
||||
title: (
|
||||
<FormattedMessage
|
||||
id="business_model.deploy.config.bussnessName"
|
||||
defaultMessage="业务名称"
|
||||
/>
|
||||
),
|
||||
dataIndex: 'bussnessName',
|
||||
},
|
||||
{
|
||||
title: <FormattedMessage id="business_model.deploy.config.remark" defaultMessage="简介" />,
|
||||
dataIndex: 'remark',
|
||||
},
|
||||
{
|
||||
title: (
|
||||
<FormattedMessage
|
||||
id="business_model.deploy.config.linkModels"
|
||||
defaultMessage="关联基础模型"
|
||||
/>
|
||||
),
|
||||
dataIndex: 'linkModels',
|
||||
render: (_, record) => {
|
||||
return (
|
||||
<ul className="flex flex-wrap">
|
||||
{record?.linkModels?.map((item, index) => {
|
||||
return (
|
||||
<li
|
||||
className={`text_primary primary_border rounded-[2px] px-[8px] mb-[8px] ${
|
||||
index !== 0 ? 'ml-[8px]' : ''
|
||||
}`}
|
||||
key={item.id}
|
||||
>
|
||||
{item.name}
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
// 模型列表信息
|
||||
const columns: ProColumns<Record<string, any>>[] = [
|
||||
{
|
||||
title: (
|
||||
<FormattedMessage id="business_model.deploy.config.table.name" defaultMessage="设备名称" />
|
||||
),
|
||||
dataIndex: 'name',
|
||||
hideInSearch: true,
|
||||
key: 'fixedName',
|
||||
fixed: 'left',
|
||||
width: '55%',
|
||||
},
|
||||
{
|
||||
title: (
|
||||
<FormattedMessage
|
||||
id="business_model.deploy.config.table.deviceType"
|
||||
defaultMessage="设备类型"
|
||||
/>
|
||||
),
|
||||
dataIndex: 'deviceType',
|
||||
hideInSearch: true,
|
||||
},
|
||||
];
|
||||
|
||||
// 基础模型列表数据api
|
||||
function loadData() {}
|
||||
|
||||
// 初始化加载
|
||||
useEffect(() => {
|
||||
console.log('modelDeployConfig_detailOpen', detailOpen);
|
||||
if (detailOpen) {
|
||||
loadData();
|
||||
} else {
|
||||
actionRef?.current?.clearSelected();
|
||||
setSelectedRows([]);
|
||||
}
|
||||
}, [detailOpen]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
width={proFormMaxModelWidth}
|
||||
title={`${intl.formatMessage({
|
||||
id: 'business_model.table.list.action.config',
|
||||
defaultMessage: '配置参数',
|
||||
})}`}
|
||||
open={detailOpen}
|
||||
onCancel={() => {
|
||||
closeModal();
|
||||
}}
|
||||
onOk={() => {
|
||||
console.log('onOk_selectedRows', selectedRows);
|
||||
// TODO 选择完成后再关闭弹框
|
||||
closeModal();
|
||||
}}
|
||||
okText={<FormattedMessage id="pages.modelForm.okText" defaultMessage="确认" />}
|
||||
cancelText={<FormattedMessage id="pages.modelForm.cancelText" defaultMessage="取消" />}
|
||||
>
|
||||
<ProCard className="gn_card" bodyStyle={{ padding: 0 }}>
|
||||
<div className="my-[8px] gn_active_descriptions bg_active_4">
|
||||
<ProDescriptions column={1} columns={detailColumns} dataSource={info}></ProDescriptions>
|
||||
</div>
|
||||
<div className="head4 py-[8px]">
|
||||
<FormattedMessage
|
||||
id="business_model.deploy.config.table.title.name"
|
||||
defaultMessage="请选择"
|
||||
/>
|
||||
</div>
|
||||
<ProTable
|
||||
style={{
|
||||
height: '300px',
|
||||
overflowY: 'scroll',
|
||||
}}
|
||||
className="gn_pro_table"
|
||||
cardProps={{
|
||||
bodyStyle: { padding: 0 },
|
||||
}}
|
||||
actionRef={actionRef}
|
||||
// 标题栏
|
||||
search={false}
|
||||
options={{ fullScreen: false, setting: false, density: false, reload: false }}
|
||||
rowKey="id"
|
||||
pagination={false}
|
||||
rowSelection={{
|
||||
onChange: (_, selectedRowsData) => {
|
||||
setSelectedRows(selectedRowsData);
|
||||
},
|
||||
}}
|
||||
tableAlertOptionRender={() => {
|
||||
return <>{selectedRows?.length > 0 && <></>}</>;
|
||||
}}
|
||||
request={async () => {
|
||||
let resp = await getAllDeviceList();
|
||||
console.log(resp, 'getAllDeviceList_resp');
|
||||
return {
|
||||
data: resp.data?.results,
|
||||
success: resp.success,
|
||||
};
|
||||
}}
|
||||
columns={columns}
|
||||
/>
|
||||
</ProCard>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default ModelDeployConfig;
|
@ -1,23 +0,0 @@
|
||||
.modelIndex_page .model_index_type_tag {
|
||||
width: 82px;
|
||||
height: 24px;
|
||||
background: rgba(21, 77, 221, 0.1);
|
||||
border: 1px solid rgba(21, 77, 221, 0.4);
|
||||
border-radius: 12px;
|
||||
color: #154DDD;
|
||||
}
|
||||
.modelIndex_page .model_index_type_tag .dot {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
background: #154ddd;
|
||||
border-radius: 50%;
|
||||
margin-right: 4px;
|
||||
}
|
||||
.modelIndex_page .model_index_type_tag.active2 {
|
||||
color: #FF8413;
|
||||
background: #FFF3E8;
|
||||
border: 1px solid #FFBF84;
|
||||
}
|
||||
.modelIndex_page .model_index_type_tag.active2 .dot {
|
||||
background: #ff8413;
|
||||
}
|
@ -1,25 +1,3 @@
|
||||
.modelIndex_page {
|
||||
.model_index_type_tag {
|
||||
width: 82px;
|
||||
height: 24px;
|
||||
color: #154ddd;
|
||||
background: rgba(21, 77, 221, 0.1);
|
||||
border: 1px solid rgba(21, 77, 221, 0.4);
|
||||
border-radius: 12px;
|
||||
.dot {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
margin-right: 4px;
|
||||
background: #154ddd;
|
||||
border-radius: 50%;
|
||||
}
|
||||
&.active2 {
|
||||
color: #ff8413;
|
||||
background: #fff3e8;
|
||||
border: 1px solid #ffbf84;
|
||||
.dot {
|
||||
background: #ff8413;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 业务层样式
|
||||
}
|
||||
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* @Author: donghao donghao@supervision.ltd
|
||||
* @Date: 2024-05-08 14:37:04
|
||||
* @LastEditors: donghao donghao@supervision.ltd
|
||||
* @LastEditTime: 2024-05-10 15:16:41
|
||||
* @FilePath: \general-ai-platform-web\src\services\testApi\businessState.ts
|
||||
* @Description: 设备、服务器状态mock数据映射
|
||||
*/
|
||||
|
||||
// @ts-ignore
|
||||
/* eslint-disable */
|
||||
import { request } from '@umijs/max';
|
||||
|
||||
/** 服务器状态分页列表 */
|
||||
export async function getServerStateList(
|
||||
body: Record<string, any>, //
|
||||
options?: { [key: string]: any },
|
||||
) {
|
||||
return request<API.Response & { data?: API.PageResult; msg?: string }>(
|
||||
`/api/business/serverState/list`,
|
||||
{
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
params: {
|
||||
...body,
|
||||
},
|
||||
...(options || {}),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/** 服务器日志分页列表 */
|
||||
export async function getServerStateLogList(
|
||||
body: Record<string, any>, //
|
||||
options?: { [key: string]: any },
|
||||
) {
|
||||
return request<API.Response & { data?: API.PageResult; msg?: string }>(
|
||||
`/api/business/serverState/logList`,
|
||||
{
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
params: {
|
||||
...body,
|
||||
},
|
||||
...(options || {}),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/** 设备状态分页列表 */
|
||||
export async function getDeviceStateList(
|
||||
body: Record<string, any>, //
|
||||
options?: { [key: string]: any },
|
||||
) {
|
||||
return request<API.Response & { data?: API.PageResult; msg?: string }>(
|
||||
`/api/business/deviceState/list`,
|
||||
{
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
params: {
|
||||
...body,
|
||||
},
|
||||
...(options || {}),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/** 设备日志分页列表 */
|
||||
export async function getDeviceStateLogList(
|
||||
body: Record<string, any>, //
|
||||
options?: { [key: string]: any },
|
||||
) {
|
||||
return request<API.Response & { data?: API.PageResult; msg?: string }>(
|
||||
`/api/business/deviceState/logList`,
|
||||
{
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
params: {
|
||||
...body,
|
||||
},
|
||||
...(options || {}),
|
||||
},
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue