feat: 分布式设备状态模块静态交互完成

develop
zhoux 1 year ago
parent 5280a4d032
commit 04770db8ae

@ -2,7 +2,7 @@
* @Author: zhoux zhouxia@supervision.ltd * @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-14 15:49:36 * @Date: 2023-11-14 15:49:36
* @LastEditors: zhoux zhouxia@supervision.ltd * @LastEditors: zhoux zhouxia@supervision.ltd
* @LastEditTime: 2023-11-16 15:10:41 * @LastEditTime: 2023-12-11 10:30:54
* @FilePath: \general-ai-platform-web\src\components\TableActionCard\index.tsx * @FilePath: \general-ai-platform-web\src\components\TableActionCard\index.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
*/ */
@ -14,11 +14,12 @@ import React from 'react';
//TODO 表单的操作按钮集合 key的报错未解决 //TODO 表单的操作按钮集合 key的报错未解决
type actionsProps = { type actionsProps = {
key: string; key: string;
renderDom: any renderDom: any;
} }
export type TableActionItemProps = { export type TableActionItemProps = {
renderActions: actionsProps[]; renderActions: actionsProps[];
listType?: 'proTable' | 'proList'
}; };
const TableActionCard: React.FC<TableActionItemProps> = (props) => { const TableActionCard: React.FC<TableActionItemProps> = (props) => {
@ -43,10 +44,10 @@ const TableActionCard: React.FC<TableActionItemProps> = (props) => {
}); });
} }
return ( return (
<div> <div className={`${ props?.listType ? props?.listType : 'proTable'}ActionBox`}>
{prevActions.map((item) => { {prevActions.map((item) => {
return ( return (
<span style={{ paddingRight: 8 }} key={item.key}> <span style={ props?.listType === 'proList' ? { paddingLeft: 8} : { paddingRight: 8 }} key={item.key}>
{item.renderDom} {item.renderDom}
</span> </span>
); );

@ -2,7 +2,7 @@
* @Author: zhoux zhouxia@supervision.ltd * @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-16 14:30:15 * @Date: 2023-11-16 14:30:15
* @LastEditors: zhoux zhouxia@supervision.ltd * @LastEditors: zhoux zhouxia@supervision.ltd
* @LastEditTime: 2023-11-16 16:22:15 * @LastEditTime: 2023-12-11 15:20:25
* @FilePath: \general-ai-platform-web\src\components\BatchOperation\isBatchDelete.tsx * @FilePath: \general-ai-platform-web\src\components\BatchOperation\isBatchDelete.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
*/ */
@ -18,6 +18,8 @@ type isConfirmActionProps = {
description?: string; description?: string;
buttonText?: string; buttonText?: string;
buttonFormatText?: string; buttonFormatText?: string;
buttonType?: 'link' | 'text' | 'default' | 'primary' | 'dashed' | undefined;
danger?: boolean
}; };
const IsConfirmAction: React.FC<isConfirmActionProps> = (props) => { const IsConfirmAction: React.FC<isConfirmActionProps> = (props) => {
@ -35,7 +37,8 @@ const IsConfirmAction: React.FC<isConfirmActionProps> = (props) => {
cancelText={intl.formatMessage({ id: 'common.no', defaultMessage: '$$$' })} cancelText={intl.formatMessage({ id: 'common.no', defaultMessage: '$$$' })}
> >
<Button <Button
type="link" type={props?.buttonType ? props.buttonType : 'link'}
danger={props?.danger}
size="small" size="small"
onClick={() => { onClick={() => {
// setPublishModalOpen(true); // setPublishModalOpen(true);

@ -4,27 +4,27 @@
export const deviceStatusEnums : Record<string,any> = { export const deviceStatusEnums : Record<string,any> = {
'allStatus': { 'allStatus': {
miniName: '全部', miniName: '全部',
value: '', value: '0',
color: '' color: ''
}, },
'onlineStatus': { 'onlineStatus': {
miniName: '在线', miniName: '在线',
value: '', value: '1',
color: 'success' color: 'success'
}, },
'outlineStatus': { 'outlineStatus': {
miniName: '离线', miniName: '离线',
value: '', value: '2',
color: 'default' color: 'default'
}, },
'processingStatus': { 'processingStatus': {
miniName: '运行中', miniName: '运行中',
value: '', value: '3',
color: 'warning' color: 'warning'
}, },
'errorStatus': { 'errorStatus': {
miniName: '故障', miniName: '故障',
value: '', value: '4',
color: 'error' color: 'error'
} }
} }

@ -113,13 +113,6 @@ a.ant-dropdown-trigger {
.theme_bg_color { .theme_bg_color {
background-color: #155BD4; background-color: #155BD4;
} }
.ant-btn-link.ant-btn-dangerous,
.ant-btn-default.ant-btn-dangerous {
color: #E80D0D;
}
.ant-btn-default.ant-btn-dangerous {
border-color: #E80D0D;
}
.ant-menu-light .ant-menu-item-selected, .ant-menu-light .ant-menu-item-selected,
.ant-menu-light > .ant-menu .ant-menu-item-selected { .ant-menu-light > .ant-menu .ant-menu-item-selected {
background-color: #e8effb; background-color: #e8effb;
@ -138,6 +131,13 @@ a.ant-dropdown-trigger {
.ant-steps .ant-steps-item-active > .ant-steps-item-container > .ant-steps-item-content > .ant-steps-item-description { .ant-steps .ant-steps-item-active > .ant-steps-item-container > .ant-steps-item-content > .ant-steps-item-description {
color: #155BD4; color: #155BD4;
} }
.ant-btn-link.ant-btn-dangerous,
.ant-btn-default.ant-btn-dangerous {
color: #E80D0D;
}
.ant-btn-default.ant-btn-dangerous {
border-color: #E80D0D;
}
.ant-tree-treenode.ant-tree-treenode-switcher-open.ant-tree-treenode-selected { .ant-tree-treenode.ant-tree-treenode-switcher-open.ant-tree-treenode-selected {
background-color: #e8effb; background-color: #e8effb;
width: 100%; width: 100%;
@ -168,6 +168,17 @@ a.ant-dropdown-trigger {
.ant-pro-table .ant-pro-table-search .ant-form .ant-pro-query-filter-row-split { .ant-pro-table .ant-pro-table-search .ant-form .ant-pro-query-filter-row-split {
padding-right: 0 !important; padding-right: 0 !important;
} }
.ant-pro-list .ant-pro-query-filter.ant-pro-query-filter {
background-color: white;
padding: 20px;
border-radius: 8px;
}
.ant-pro-list .ant-pro-table-list-toolbar-left {
flex: 0.8;
}
.ant-popover .ant-popover-content {
min-width: 200px;
}
.rc-virtual-list-scrollbar-thumb { .rc-virtual-list-scrollbar-thumb {
display: none; display: none;
} }
@ -197,6 +208,28 @@ a.ant-dropdown-trigger {
background-color: #878987; background-color: #878987;
-webkit-border-radius: 6px; -webkit-border-radius: 6px;
} }
.ant-tag-default {
border-radius: 2px;
border: 1px solid #CCC;
background: rgba(204, 204, 204, 0.1);
color: #999;
}
.ant-tag-success {
border-radius: 2px;
border: 1px solid #52C41A;
background: rgba(82, 196, 26, 0.1);
}
.ant-tag-warning {
border-radius: 2px;
border: 1px solid var(--1, #FAAD14);
background: rgba(250, 173, 20, 0.1);
}
.ant-tag-error {
border-radius: 2px;
border: 1px solid #E80D0D;
color: #E80D0D;
background: rgba(232, 13, 13, 0.1);
}
.gn { .gn {
/* UI // update 使 /* UI // update 使
@ -208,6 +241,19 @@ a.ant-dropdown-trigger {
padding-inline: 0; padding-inline: 0;
padding-block: 0; padding-block: 0;
} }
.gn .ant-pro-checkcard {
margin-inline-end: 0;
margin-block-end: 0;
}
.gn .ant-pro-list-row-card {
margin-block: 6px;
margin-inline: 0;
padding-block: 0;
padding-inline: 6px;
}
.gn .ant-list .ant-list-pagination {
margin-block-start: 10px;
}
.gn .ant-table-wrapper table tr th.ant-table-selection-column, .gn .ant-table-wrapper table tr th.ant-table-selection-column,
.gn .ant-table-wrapper table tr td.ant-table-selection-column, .gn .ant-table-wrapper table tr td.ant-table-selection-column,
.gn .ant-table-wrapper .ant-table-selection-column { .gn .ant-table-wrapper .ant-table-selection-column {
@ -247,6 +293,13 @@ a.ant-dropdown-trigger {
border-start-start-radius: 4px; border-start-start-radius: 4px;
border-end-start-radius: 4px; border-end-start-radius: 4px;
} }
.gn .proListActionBox .ant-btn.ant-btn-sm {
padding: 0;
font-size: 12px;
}
.gn.fw7 {
font-weight: 700;
}
.gn.h2 { .gn.h2 {
font-size: 18px; font-size: 18px;
} }
@ -259,6 +312,24 @@ a.ant-dropdown-trigger {
line-height: 18px; line-height: 18px;
color: #333333; color: #333333;
} }
.gn.text_0 {
color: '#000';
}
.gn.text_1 {
color: '#333';
}
.gn.text_2 {
color: '#666';
}
.gn.text_3 {
color: '#999';
}
.gn.text_green {
color: #52C41A;
}
.gn.fs14 {
font-size: 14px;
}
.gn .des_1 { .gn .des_1 {
font-size: 12px; font-size: 12px;
font-weight: 400; font-weight: 400;
@ -274,3 +345,10 @@ a.ant-dropdown-trigger {
.ant-pro-global-header-logo img { .ant-pro-global-header-logo img {
height: 48px; height: 48px;
} }
.rectProgress_box .ant-progress .ant-progress-inner {
border-radius: 2px;
}
.rectProgress_box .ant-progress .ant-progress-success-bg,
.rectProgress_box .ant-progress .ant-progress-bg {
border-radius: 2px;
}

@ -138,12 +138,7 @@ a.ant-dropdown-trigger{
background-color: #155BD4; background-color: #155BD4;
} }
.ant-btn-link.ant-btn-dangerous, .ant-btn-default.ant-btn-dangerous {
color: #E80D0D;
}
.ant-btn-default.ant-btn-dangerous{
border-color: #E80D0D;
}
.ant-menu-light .ant-menu-item-selected, .ant-menu-light>.ant-menu .ant-menu-item-selected { .ant-menu-light .ant-menu-item-selected, .ant-menu-light>.ant-menu .ant-menu-item-selected {
background-color: #e8effb; background-color: #e8effb;
@ -169,6 +164,13 @@ a.ant-dropdown-trigger{
} }
} }
.ant-btn-link.ant-btn-dangerous, .ant-btn-default.ant-btn-dangerous {
color: #E80D0D;
}
.ant-btn-default.ant-btn-dangerous{
border-color: #E80D0D;
}
.ant-tree-treenode.ant-tree-treenode-switcher-open.ant-tree-treenode-selected { .ant-tree-treenode.ant-tree-treenode-switcher-open.ant-tree-treenode-selected {
background-color: #e8effb; background-color: #e8effb;
width: 100%; width: 100%;
@ -213,6 +215,27 @@ a.ant-dropdown-trigger{
} }
} }
} }
// proList
.ant-pro-list{
.ant-pro-query-filter.ant-pro-query-filter {
background-color: white;
padding: 20px;
border-radius: 8px;
}
.ant-pro-table-list-toolbar-left{
flex: 0.8
}
}
// 气泡框
.ant-popover .ant-popover-content {
min-width: 200px;
}
.rc-virtual-list-scrollbar-thumb{ .rc-virtual-list-scrollbar-thumb{
display: none display: none
} }
@ -246,6 +269,29 @@ a.ant-dropdown-trigger{
background-color: #878987; background-color: #878987;
-webkit-border-radius: 6px -webkit-border-radius: 6px
} }
// 动作按钮
.ant-tag-default {
border-radius: 2px;
border: 1px solid #CCC;
background: rgba(204, 204, 204, 0.10);
color: #999;
}
.ant-tag-success{
border-radius: 2px;
border: 1px solid #52C41A;
background: rgba(82, 196, 26, 0.10);
}
.ant-tag-warning {
border-radius: 2px;
border: 1px solid var(--1, #FAAD14);
background: rgba(250, 173, 20, 0.10);
}
.ant-tag-error {
border-radius: 2px;
border: 1px solid #E80D0D;
color: #E80D0D;
background: rgba(232, 13, 13, 0.10);
}
.gn { .gn {
// TODO_update 重置覆盖默认样式使用统一类名gn + 需要覆盖的类名 // TODO_update 重置覆盖默认样式使用统一类名gn + 需要覆盖的类名
@ -253,6 +299,21 @@ a.ant-dropdown-trigger{
padding-inline: 0; padding-inline: 0;
padding-block: 0; padding-block: 0;
} }
.ant-pro-checkcard {
margin-inline-end: 0;
margin-block-end: 0;
}
.ant-pro-list-row-card {
margin-block: 6px;
margin-inline: 0;
padding-block: 0;
padding-inline: 6px;
}
.ant-list .ant-list-pagination {
margin-block-start: 10px;
}
.ant-table-wrapper table tr th.ant-table-selection-column, .ant-table-wrapper table tr th.ant-table-selection-column,
.ant-table-wrapper table tr td.ant-table-selection-column, .ant-table-wrapper table tr td.ant-table-selection-column,
.ant-table-wrapper .ant-table-selection-column{ .ant-table-wrapper .ant-table-selection-column{
@ -297,7 +358,14 @@ a.ant-dropdown-trigger{
.ant-input-search .ant-input-group .ant-input-affix-wrapper:not(:last-child) { .ant-input-search .ant-input-group .ant-input-affix-wrapper:not(:last-child) {
border-start-start-radius: 4px; border-start-start-radius: 4px;
border-end-start-radius: 4px; border-end-start-radius: 4px;
} }
.proListActionBox{
.ant-btn.ant-btn-sm{
padding: 0;
font-size: 12px;
}
}
/* UI 规范表 // update 使用中 /* UI 规范表 // update 使用中
适用说明 适用说明
@ -308,6 +376,9 @@ a.ant-dropdown-trigger{
// line-height: ; // line-height: ;
// font-weight: 600; // font-weight: 600;
// } // }
&.fw7{
font-weight: 700;
}
&.h2{ &.h2{
font-size: 18px; font-size: 18px;
} }
@ -321,7 +392,24 @@ a.ant-dropdown-trigger{
font-weight: 700; font-weight: 700;
line-height: 18px; line-height: 18px;
color: rgba(51, 51, 51, 1); color: rgba(51, 51, 51, 1);
}
&.text_0{
color: '#000';
}
&.text_1{
color: '#333';
}
&.text_2{
color: '#666';
}
&.text_3{
color: '#999';
}
&.text_green{
color: #52C41A;
}
&.fs14{
font-size: 14px;
} }
.des_1{ .des_1{
@ -342,6 +430,15 @@ a.ant-dropdown-trigger{
.ant-pro-global-header-logo img { .ant-pro-global-header-logo img {
height: 48px; height: 48px;
} }
.rectProgress_box{
.ant-progress .ant-progress-inner{
border-radius: 2px;
}
.ant-progress .ant-progress-success-bg, .ant-progress .ant-progress-bg{
border-radius: 2px;
}
}
// .p1{ // .p1{
// } // }

@ -1,16 +1,304 @@
import { Modal, Tabs } from 'antd'; import { Modal, Tabs } from 'antd';
import { proFormMaxModelWidth } from '../../../../../config/defaultForm'; import { proFormMaxModelWidth } from '../../../../../config/defaultForm';
import { ProColumns, ProTable } from '@ant-design/pro-components'; import ProjectCard from '@/pages/Setting/components/ProjectCard';
import { ProCard, ProColumns, ProDescriptions, ProTable } from '@ant-design/pro-components';
import { FormattedMessage, useIntl } from '@umijs/max'; import { FormattedMessage, useIntl } from '@umijs/max';
import ReactEcharts from 'echarts-for-react';
import React, { useState } from 'react'; import React, { useState } from 'react';
import { proTablePaginationOptions } from '../../../../../config/defaultTable';
import { format } from 'echarts';
// 各类别占比环形图
type DetailChartProps = {
title: string;
chartOptions: Record<string, any>[];
};
const DetailChart: React.FC<DetailChartProps> = (props) => {
const { title, chartOptions } = props;
const getOption = () => {
return {
tooltip: {
trigger: 'item',
formatter: '{b} : {c} ({d}%)',
},
legend: {
// icon: 'circle',
// orient: 'vertical',
orient: 'vertical', // 图例的布局方向,可以设置为 'horizontal' 水平布局
// left: 'right', // 图例在容器中的位置
itemWidth: 8, // 图例标记的宽度
itemHeight: 8, // 图例标记的高度
// right: 15,
// itemBorderRadius: 100,
// borderRadius: 100,
textStyle: {
color: '#666', // 图例文字的颜色
// label: '123''{a} <br/>{b} : {c} ({d}%)'
},
data: chartOptions.map((item) => item.name),
formatter: function (name: string) {
// let total = 0
// let currCount = 0
// chartOptions.forEach(item=>{
// total+=item.value
// if(item.name === name){
// currCount = item.value
// }
// })
// console.log('itemFormatter',currCount, total)
// let currProgress = Math.round(currCount/total * 1000)
// for(let i=0; i<chartOptions.length; i++) {
// total+=
// }
// 在图例中显示比例
return `${name}`;
},
right: 15,
top: 'center',
// data: [chartOptions[0].name, chartOptions[1].name],
},
series: [
{
center: ['30%', '50%'],
radius: '85%',
// name: format(name),
type: 'pie',
color: [chartOptions[0].color, chartOptions[1].color],
avoidLabelOverlap: false,
label: {
show: true,
position: 'inside', // 将标签显示在饼图的内部
formatter: '{d}%', // 在饼图块内显示标签内容,包括名称和百分比
color: 'white'
},
emphasis: {
label: {
show: false,
fontWeight: 'bold',
},
},
labelLine: {
show: false,
},
data: chartOptions,
},
],
};
};
return (
<div style={{ background: '#F8FAFD', borderRadius: 4, width: 'calc(25% - 12px)', padding: 15 }}>
<span style={{ fontWeight: 700, fontSize: 16 }}>{title}</span>
<ReactEcharts style={{ width: 200, height: 119 }} option={getOption()} />
</div>
);
};
// 设备信息 // 设备信息
const DeviceBaseInfo: React.FC = () => { const DeviceBaseInfo: React.FC = () => {
const baseColumns: ProColumns<Record<string, any>[]> = [
{
title: '设备组',
dataIndex: 'label1',
},
{
title: '设备分类',
dataIndex: 'label2',
},
{
title: '设备名称',
dataIndex: 'label3',
},
{
title: '设备ID',
dataIndex: 'label4',
},
{
title: '设备IP',
dataIndex: 'label5',
},
// TODO 这边根据对应状态使用不同颜色字体
{
title: '设备状态',
dataIndex: 'label8',
render(dom, entity, index, action, schema) {
return <span className="gn text_green">{dom}</span>;
},
},
{
title: '备注',
dataIndex: 'label7',
},
];
// 基本信息测试数据
const testBaseData: Record<string, any> = {
label1: '设备组001',
label2: '区域监控',
label3: '设备001',
label4: '001001',
label5: '192.168.192.168',
label8: '在线',
label7: '这是备注这是备注这是备注这是备注这是备注',
};
// 硬件信息测试数据
const chartList: Record<string, any>[] = [
{
title: 'CPU',
type: 0,
chartOptions: [
{
name: '已占用',
value: 123,
color: '#FFAB00',
},
{
name: '未占用',
color: '#477BFF',
value: 233,
},
],
},
{
title: '内存',
type: 1,
chartOptions: [
{
name: '已占用',
value: 160,
color: '#00C45A',
},
{
name: '未占用',
color: '#FF8110',
value: 40,
},
],
},
{
title: '存储',
type: 2,
chartOptions: [
{
name: '已占用',
value: 60,
color: '#FF8110',
},
{
name: '未占用',
color: '#47A3FF',
value: 140,
},
],
},
{
title: 'GPU',
type: 3,
chartOptions: [
{
name: '已占用',
value: 60,
color: '#FFAB00',
},
{
name: '未占用',
color: '#477BFF',
value: 140,
},
],
},
];
// 当前任务
const taskList: Record<string, any>[] = [
{
id: '001',
modelName: '模型名称1',
version: '版本号1',
updateTime: '2023-12-12 10:10:56',
},
{
id: '001',
modelName: '模型名称2',
version: '版本号1',
updateTime: '2023-12-12 10:10:56',
},
{
id: '001',
modelName: '模型名称3',
version: '版本号1',
updateTime: '2023-12-12 10:10:56',
},
{
id: '001',
modelName: '模型名称4',
version: '版本号1',
updateTime: '2023-12-12 10:10:56',
},
];
return ( return (
<ul> <ul>
<li></li> <li>
<p className="gn text_0 fs14 fw7" style={{}}>
</p>
<ProDescriptions
column={5}
dataSource={testBaseData}
columns={baseColumns}
></ProDescriptions>
</li>
<li style={{ paddingBottom: 16 }}>
<p className="gn text_0 fs14 fw7" style={{}}>
</p>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
{chartList.map((item, index) => {
return (
<DetailChart
key={index}
title={item.title}
chartOptions={item.chartOptions}
></DetailChart>
);
})}
</div>
</li>
<li>
<p className="gn text_0 fs14 fw7" style={{}}>
</p>
<div style={{ display: 'flex', flexWrap: 'wrap', maxHeight: '30vh', overflowY: 'scroll' }}>
{taskList.map((item, index) => {
return (
<div key={index} style={{ paddingRight: 16, paddingBottom: 16 }}>
<ProCard
style={{
backgroundColor: 'rgba(21, 91, 212, 0.03)',
width: 289,
border: '1px solid rgba(21, 77, 221, 0.10)',
}}
bodyStyle={{ margin: 0, padding: 0 }}
>
<div
style={{
display: 'flex',
padding: 15,
}}
>
<div>
<img src="/images/icons/logo.svg" alt="" style={{ width: '64px' }} />
</div>
</div>
<ProjectCard info={item}></ProjectCard>
</ProCard>
</div>
);
})}
</div>
</li>
</ul> </ul>
); );
}; };
@ -18,6 +306,8 @@ const DeviceBaseInfo: React.FC = () => {
// 设备信息 // 设备信息
const DeviceLogInfo: React.FC = () => { const DeviceLogInfo: React.FC = () => {
// 动态设置每页数量
const [currentPageSize, setCurrentPageSize] = useState<number>(10);
const columns: ProColumns<Record<string, any>[]> = [ const columns: ProColumns<Record<string, any>[]> = [
{ {
title: ( title: (
@ -75,6 +365,7 @@ const DeviceLogInfo: React.FC = () => {
hideInSearch: true, hideInSearch: true,
}, },
]; ];
let testData: Record<string, any>[] = []; let testData: Record<string, any>[] = [];
for (let i = 0; i < 8; i++) { for (let i = 0; i < 8; i++) {
testData.push({ testData.push({
@ -93,32 +384,43 @@ const DeviceLogInfo: React.FC = () => {
search={false} search={false}
options={{ fullScreen: false, setting: false, density: false, reload: false }} options={{ fullScreen: false, setting: false, density: false, reload: false }}
rowKey="key" rowKey="key"
request={async () => { request={async (params = {}, sort) => {
// const {current, ...rest} = params const { current, ...rest } = params;
// const reqParams = { const reqParams = {
// page: current, page: current,
// desc: false, desc: false,
// orderKey: "", orderKey: '',
// ...rest, ...rest,
// } };
// if (sort && Object.keys(sort).length) { if (sort && Object.keys(sort).length) {
// reqParams.orderKey = Object.keys(sort)[0] reqParams.orderKey = Object.keys(sort)[0];
// let sort_select = sort[reqParams.orderKey] let sort_select = sort[reqParams.orderKey];
// reqParams.desc = sort_select === 'descend'; reqParams.desc = sort_select === 'descend';
// } }
// let resp = await getSysOperationRecordGetOperationRecordList({...reqParams}) // TODO 联调查询设备日志接口
// let resps = await postDeviceGroupGetDeviceGroupList({ ...reqParams });
let resp = { let resp = {
success: true, success: true,
data: {
list: testData,
total: 8,
page: 1,
pageSize: 8,
},
}; };
return { return {
data: testData, data: resp.data.list,
success: resp.success, success: resp.success,
// total: resp.data.total, total: resp.data.total,
// current: resp.data.page, current: resp.data.page,
// pageSize: resp.data.pageSize pageSize: resp.data.pageSize,
}; };
}} }}
pagination={false} pagination={{
...proTablePaginationOptions,
pageSize: currentPageSize,
onChange: (page, pageSize) => setCurrentPageSize(pageSize),
}}
columns={columns} columns={columns}
></ProTable> ></ProTable>
); );
@ -153,7 +455,7 @@ const DetailInfoCard: React.FC<DetailInfoCardProps> = (props) => {
{ {
key: 'deviceInfo', key: 'deviceInfo',
label: intl.formatMessage({ label: intl.formatMessage({
id: 'pages.login.accountLogin.tab', id: 'DCSDeviceList.deviceStatus.detailModel.baseInfo',
defaultMessage: '设备信息', defaultMessage: '设备信息',
}), }),
}, },

@ -2,7 +2,7 @@
* @Author: zhoux zhouxia@supervision.ltd * @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-06 16:12:17 * @Date: 2023-11-06 16:12:17
* @LastEditors: zhoux zhouxia@supervision.ltd * @LastEditors: zhoux zhouxia@supervision.ltd
* @LastEditTime: 2023-12-08 14:05:45 * @LastEditTime: 2023-12-11 16:12:17
* @FilePath: \general-ai-platform-web\src\pages\Setting\components\ProjectCardList.tsx * @FilePath: \general-ai-platform-web\src\pages\Setting\components\ProjectCardList.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
*/ */
@ -21,9 +21,9 @@ const listItemStyle = {
display: 'flex', display: 'flex',
fontSize: 14, fontSize: 14,
color: '#333333', color: '#333333',
maxWidth: '22vh', width: '100%',
alignItems: 'center', alignItems: 'center',
padding: '5px 0', padding: '8px 0 0',
}; };
const listItemLabelStyle = { const listItemLabelStyle = {
@ -48,7 +48,7 @@ type DeviceItemProgress = {
}; };
// 进度条 // 进度条
// TODO 进度条的边框圆角调整为矩形
const DeviceItemProgress: React.FC<DeviceItemProgress> = (props) => { const DeviceItemProgress: React.FC<DeviceItemProgress> = (props) => {
let strokeColor = 'rgb(243,48,5)'; let strokeColor = 'rgb(243,48,5)';
switch (props.label) { switch (props.label) {
@ -61,15 +61,15 @@ const DeviceItemProgress: React.FC<DeviceItemProgress> = (props) => {
case '存储': case '存储':
strokeColor = 'rgb(33,169,122)'; strokeColor = 'rgb(33,169,122)';
break; break;
case 'NPU': case 'GPU':
strokeColor = 'rgb(250,173,20)'; strokeColor = 'rgb(250,173,20)';
break; break;
} }
return ( return (
<div style={{ width: '100%', display: 'flex' }}> <div style={{ width: '100%', display: 'flex' }} className='rectProgress_box'>
<span style={listItemLabelStyle}>{props.label}</span> <span style={listItemLabelStyle}>{props.label}</span>
<Progress height={46} percent={props.percent * 100} strokeColor={strokeColor} showInfo={false} /> <Progress style={{padding:0, margin: 0, borderRadius: 0}} size={['100%', 10]} height={46} percent={props.percent * 100} strokeColor={strokeColor} showInfo={false} />
</div> </div>
); );
}; };
@ -94,7 +94,7 @@ const DeviceStatusCard: React.FC<UpdateProjectProps> = ({
<span style={{ fontWeight: 700, fontSize: 14, paddingRight: 10 }}></span> <span style={{ fontWeight: 700, fontSize: 14, paddingRight: 10 }}></span>
<Tag color="#44AEF5"></Tag> <Tag color="#44AEF5"></Tag>
</div> */} </div> */}
<ul> <ul style={{width: '100%'}}>
<li style={listItemStyle}> <li style={listItemStyle}>
<DeviceItemProgress label="CPU" percent={0.79}></DeviceItemProgress> <DeviceItemProgress label="CPU" percent={0.79}></DeviceItemProgress>
</li> </li>
@ -105,7 +105,7 @@ const DeviceStatusCard: React.FC<UpdateProjectProps> = ({
<DeviceItemProgress label="存储" percent={0.16}></DeviceItemProgress> <DeviceItemProgress label="存储" percent={0.16}></DeviceItemProgress>
</li> </li>
<li style={listItemStyle}> <li style={listItemStyle}>
<DeviceItemProgress label="NPU" percent={0.58}></DeviceItemProgress> <DeviceItemProgress label="GPU" percent={0.58}></DeviceItemProgress>
</li> </li>
</ul> </ul>
</div> </div>

@ -2,19 +2,20 @@
* @Author: zhoux zhouxia@supervision.ltd * @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-12-08 10:11:54 * @Date: 2023-12-08 10:11:54
* @LastEditors: zhoux zhouxia@supervision.ltd * @LastEditors: zhoux zhouxia@supervision.ltd
* @LastEditTime: 2023-12-08 16:01:26 * @LastEditTime: 2023-12-11 17:15:39
* @FilePath: \general-ai-platform-web\src\pages\DCSDevice\DeviceStatus\index.tsx * @FilePath: \general-ai-platform-web\src\pages\DCSDevice\DeviceStatus\index.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
*/ */
import TableActionCard from '@/components/TableActionCard'; import TableActionCard from '@/components/TableActionCard';
import IsConfirmAction from '@/components/TableActionCard/isConfirmAction'; import IsConfirmAction from '@/components/TableActionCard/isConfirmAction';
import { deviceStatusEnums } from '@/enums/status'; import { deviceStatusEnums } from '@/enums/status';
import { PageContainer, ProCard, ProList } from '@ant-design/pro-components'; import { PageContainer, ProCard, ProColumns, ProList } from '@ant-design/pro-components';
import { FormattedMessage } from '@umijs/max'; import { FormattedMessage } from '@umijs/max';
import { Button, Tag } from 'antd'; import { Button, Tag } from 'antd';
import React, { useState } from 'react'; import React, { useState } from 'react';
import DeviceStatusCard from './components/DeviceStatusCard'; import { proTableCommonOptions, proTablePaginationOptions } from '../../../../config/defaultTable';
import DetailInfoCard from './components/DetailInfoCard'; import DetailInfoCard from './components/DetailInfoCard';
import DeviceStatusCard from './components/DeviceStatusCard';
/** /**
* @ * @
@ -30,185 +31,275 @@ const tabOptions: Record<string, any> = {
errorStatus: 20, errorStatus: 20,
}; };
const DeviceStatus: React.FC = () => { const DeviceStatus: React.FC = () => {
const [cardActionProps, setCardActionProps] = useState<'actions' | 'extra'>('extra'); const [cardActionProps, setCardActionProps] = useState<'actions' | 'extra'>('extra');
const [detailModalOpen, setDetailModalOpen] = useState<boolean>(false); const [detailModalOpen, setDetailModalOpen] = useState<boolean>(false);
const [currentRow, setCurrentRow] = useState<Record<string,any>>({}); const [currentRow, setCurrentRow] = useState<Record<string, any>>({});
// 动态设置每页数量
const [currentPageSize, setCurrentPageSize] = useState<number>(8);
const [activeTabIndex, setActiveTabIndex] = useState<number>(0); const [activeTabIndex, setActiveTabIndex] = useState<number>(0);
const [ghost, setGhost] = useState<boolean>(false);
const handleDetailModal = () => { const handleDetailModal = () => {
if (detailModalOpen) { if (detailModalOpen) {
setDetailModalOpen(false); setDetailModalOpen(false);
setCurrentRow({}); setCurrentRow({});
} else { } else {
setDetailModalOpen(true); setDetailModalOpen(true);
} }
}; };
const data = [{status: '在线'},{status: '在线'}, {status: '故障'},{status: '故障'},{status: '运行中'},{status: '在线'},{status: '在线'}, {status: '离线'}].map( const dataTestList = [
(record, index) => { { status: '在线' },
let currColor = 'default'; { status: '在线' },
switch (record.status) { { status: '故障' },
case '在线': { status: '故障' },
currColor = 'success'; { status: '运行中' },
break; { status: '在线' },
case '故障': { status: '在线' },
currColor = 'error'; { status: '离线' },
break; ].map((record, index) => {
case '运行中': let currColor = 'default';
currColor = 'warning'; switch (record.status) {
break; case '在线':
default: currColor = 'success';
currColor = 'default'; break;
break; case '故障':
} currColor = 'error';
return { break;
content: ( case '运行中':
<ProCard style={{ backgroundColor: '#FAFAFA' }} bodyStyle={{ margin: 0, padding: 0 }}> currColor = 'warning';
<div break;
style={{ default:
display: 'flex', currColor = 'default';
alignItems: 'center', break;
padding: 15, }
justifyContent: 'space-between', return {
}} content: (
> <ProCard className="gn"
<div> style={{ backgroundColor: '#FAFAFA', margin: 0, padding: 0 }} bodyStyle={{ margin: 0, padding: 0 }}>
<Tag color={currColor}>{record.status}</Tag> <div
<span>{index + 1}</span> style={{
</div> display: 'flex',
<TableActionCard alignItems: 'center',
key="TableActionCardRef" padding: 12,
renderActions={[ justifyContent: 'space-between',
{ borderBottom: '1px solid rgba(224, 224, 224, 1)'
key: 'update', }}
renderDom: ( >
<IsConfirmAction <div style={{
key="reOpen" display: 'flex',
title={'重启'} alignItems: 'center',
buttonFormatText={'pages.searchTable.reOpen'} maxWidth: '60%'
confirmAction={() => { }}>
// setPublishModalOpen(true); <Tag color={currColor}>{record.status}</Tag>
// putAlgorithmModelUpdateAlgorithmModel({ <p className='gn single_line text_1 fw7' style={{maxWidth: '80%', padding: 0, margin: 0}}>{index + 1}</p>
// id: record.modelFkId,
// defaultVersionFkId: record.id,
// })
// .then(() => {
// message.success(
// intl.formatMessage({ id: 'common.success', defaultMessage: '$$$' }),
// );
// })
// .catch(() => {
// message.error(
// intl.formatMessage({ id: 'common.failure', defaultMessage: '$$$' }),
// );
// });
}}
></IsConfirmAction>
),
},
{
key: 'detail',
renderDom: (
<Button
key="detail"
type="link"
size="small"
onClick={() => {
handleDetailModal()
setCurrentRow(record);
// doToDetail(record);
// setShowDetail(true);
}}
>
<FormattedMessage id="pages.searchTable.detail" defaultMessage="Update" />
</Button>
),
},
]}
></TableActionCard>
</div> </div>
<DeviceStatusCard info={record}></DeviceStatusCard>{' '} <TableActionCard
</ProCard> key="TableActionCardRef"
), listType="proList"
}; renderActions={[
{
key: 'update',
renderDom: (
<IsConfirmAction
key="reOpen"
title={'重启'}
buttonFormatText={'pages.searchTable.reOpen'}
danger={true}
confirmAction={() => {
// setPublishModalOpen(true);
// putAlgorithmModelUpdateAlgorithmModel({
// id: record.modelFkId,
// defaultVersionFkId: record.id,
// })
// .then(() => {
// message.success(
// intl.formatMessage({ id: 'common.success', defaultMessage: '$$$' }),
// );
// })
// .catch(() => {
// message.error(
// intl.formatMessage({ id: 'common.failure', defaultMessage: '$$$' }),
// );
// });
}}
></IsConfirmAction>
),
},
{
key: 'detail',
renderDom: (
<Button
key="detail"
type="link"
size="small"
onClick={() => {
handleDetailModal();
setCurrentRow(record);
// doToDetail(record);
// setShowDetail(true);
}}
>
<FormattedMessage id="pages.searchTable.detail" defaultMessage="Update" />
</Button>
),
},
]}
></TableActionCard>
</div>
<DeviceStatusCard info={record}></DeviceStatusCard>{' '}
</ProCard>
),
};
});
const columns: ProColumns<Record<string, any>>[] = [
{
title: '123',
dataIndex: 'status',
// hideInSearch: true,
}, },
); ];
return ( return (
<PageContainer> <PageContainer>
<ProCard bodyStyle={{ padding: 16, margin: 0 }}> <ProList<any>
<div> className="gn"
{Object.keys(tabOptions).map((item, index) => { ghost={true}
// eslint-disable-next-line react/jsx-key itemCardProps={{
return ( ghost: true,
<Button bodyStyle: { padding: 0, margin: 0 },
style={{ marginRight: 12 }} }}
type={activeTabIndex === index ? 'primary' : 'default'} search={{
key={index} labelWidth: proTableCommonOptions.searchLabelWidth,
onClick={() => { }}
setActiveTabIndex(index); headerTitle={
}} <>
> <div>
{Object.keys(deviceStatusEnums).includes(item) {Object.keys(tabOptions).map((item, index) => {
? deviceStatusEnums[item].miniName // eslint-disable-next-line react/jsx-key
: ''} return (
{tabOptions[item]} <Button
</Button> style={{ marginRight: 12 }}
); type={activeTabIndex === index ? 'primary' : 'default'}
})} key={index}
</div> onClick={() => {
<ProList<any> setActiveTabIndex(index);
className="gn" }}
ghost={true} >
itemCardProps={{ {Object.keys(deviceStatusEnums).includes(item)
ghost: true, ? deviceStatusEnums[item].miniName
bodyStyle: { padding: 0, margin: 0 }, : ''}
}} {tabOptions[item]}
pagination={{ </Button>
defaultPageSize: 8, );
showSizeChanger: false, })}
}} </div>
showActions="hover" </>
rowSelection={false} }
grid={{ gutter: 16, xs: 1, md: 2, lg: 3, xl: 4, xxl: 4 }} cardProps={{
metas={{ bodyStyle: {
type: {}, background: 'white',
content: {}, padding: '8px 16px 16px',
actions: { borderRadius: 8
cardActionProps, }
}}
pagination={{
...proTablePaginationOptions,
pageSize: currentPageSize,
onChange: (page, pageSize) => setCurrentPageSize(pageSize),
}}
showActions="hover"
rowSelection={false}
grid={{ gutter: 16, xs: 1, md: 2, lg: 3, xl: 4, xxl: 4 }}
metas={{
type: {
hideInSearch: true,
},
content: {
hideInSearch: true,
},
actions: {
cardActionProps,
},
status1: {
// 自己扩展的字段,主要用于筛选,不在列表中显示
title: '设备组',
valueType: 'select',
valueEnum: {
'0': { text: '全部设备分组', status: '0' },
'1': {
text: '设备分组1',
status: '1',
},
'2': {
text: '设备分组2',
status: '2',
},
'3': {
text: '设备分组3',
status: '3',
},
}, },
}} },
headerTitle="" status2: {
// toolBarRender={(action, rows) => { // 自己扩展的字段,主要用于筛选,不在列表中显示
// console.log(action, rows, 'toolBarRender'); title: '分类',
// // TODO 需要对接接口 valueType: 'select',
// const isProcess: boolean = false; valueEnum: {
// return isProcess ? ( '0': { text: '全部分类', status: '0' },
// <Button type="primary" danger> '1': {
// 结束运行 text: '外围监控',
// </Button> status: '1',
// ) : ( },
// <Button type="primary"> '2': {
// 开始运行 text: '室内监控',
// </Button> status: '2',
// ); },
// }} '3': {
dataSource={data} text: '违规监控',
/> status: '3',
</ProCard> },
},
<DetailInfoCard detailModalOpen={detailModalOpen} handleDetailModal={handleDetailModal}> },
}}
request={async (params = {}, sort) => {
</DetailInfoCard> const { current, ...rest } = params;
const reqParams = {
page: current,
desc: false,
orderKey: '',
...rest,
};
if (sort && Object.keys(sort).length) {
reqParams.orderKey = Object.keys(sort)[0];
let sort_select = sort[reqParams.orderKey];
reqParams.desc = sort_select === 'descend';
}
// TODO 联调查询设备状态接口
// let resps = await postDeviceGroupGetDeviceGroupList({ ...reqParams });
let resp = {
success: true,
data: {
list: dataTestList,
total: 8,
page: 1,
pageSize: 8,
},
};
return {
data: resp.data.list,
success: resp.success,
total: resp.data.total,
current: resp.data.page,
pageSize: resp.data.pageSize,
};
}}
/>
<DetailInfoCard
detailModalOpen={detailModalOpen}
handleDetailModal={handleDetailModal}
></DetailInfoCard>
</PageContainer> </PageContainer>
); );
}; };

Loading…
Cancel
Save