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

develop
zhoux 1 year ago
parent 5280a4d032
commit 04770db8ae

@ -2,7 +2,7 @@
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-14 15:49:36
* @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
* @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的报错未解决
type actionsProps = {
key: string;
renderDom: any
renderDom: any;
}
export type TableActionItemProps = {
renderActions: actionsProps[];
listType?: 'proTable' | 'proList'
};
const TableActionCard: React.FC<TableActionItemProps> = (props) => {
@ -43,10 +44,10 @@ const TableActionCard: React.FC<TableActionItemProps> = (props) => {
});
}
return (
<div>
<div className={`${ props?.listType ? props?.listType : 'proTable'}ActionBox`}>
{prevActions.map((item) => {
return (
<span style={{ paddingRight: 8 }} key={item.key}>
<span style={ props?.listType === 'proList' ? { paddingLeft: 8} : { paddingRight: 8 }} key={item.key}>
{item.renderDom}
</span>
);

@ -2,7 +2,7 @@
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-16 14:30:15
* @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
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
@ -18,6 +18,8 @@ type isConfirmActionProps = {
description?: string;
buttonText?: string;
buttonFormatText?: string;
buttonType?: 'link' | 'text' | 'default' | 'primary' | 'dashed' | undefined;
danger?: boolean
};
const IsConfirmAction: React.FC<isConfirmActionProps> = (props) => {
@ -35,7 +37,8 @@ const IsConfirmAction: React.FC<isConfirmActionProps> = (props) => {
cancelText={intl.formatMessage({ id: 'common.no', defaultMessage: '$$$' })}
>
<Button
type="link"
type={props?.buttonType ? props.buttonType : 'link'}
danger={props?.danger}
size="small"
onClick={() => {
// setPublishModalOpen(true);

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

@ -113,13 +113,6 @@ a.ant-dropdown-trigger {
.theme_bg_color {
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 {
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 {
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 {
background-color: #e8effb;
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 {
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 {
display: none;
}
@ -197,6 +208,28 @@ a.ant-dropdown-trigger {
background-color: #878987;
-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 {
/* UI // update 使
@ -208,6 +241,19 @@ a.ant-dropdown-trigger {
padding-inline: 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 td.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-end-start-radius: 4px;
}
.gn .proListActionBox .ant-btn.ant-btn-sm {
padding: 0;
font-size: 12px;
}
.gn.fw7 {
font-weight: 700;
}
.gn.h2 {
font-size: 18px;
}
@ -259,6 +312,24 @@ a.ant-dropdown-trigger {
line-height: 18px;
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 {
font-size: 12px;
font-weight: 400;
@ -274,3 +345,10 @@ a.ant-dropdown-trigger {
.ant-pro-global-header-logo img {
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;
}
.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 {
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 {
background-color: #e8effb;
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{
display: none
}
@ -246,6 +269,29 @@ a.ant-dropdown-trigger{
background-color: #878987;
-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 {
// TODO_update 重置覆盖默认样式使用统一类名gn + 需要覆盖的类名
@ -253,6 +299,21 @@ a.ant-dropdown-trigger{
padding-inline: 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 td.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) {
border-start-start-radius: 4px;
border-end-start-radius: 4px;
}
}
.proListActionBox{
.ant-btn.ant-btn-sm{
padding: 0;
font-size: 12px;
}
}
/* UI 规范表 // update 使用中
适用说明
@ -308,6 +376,9 @@ a.ant-dropdown-trigger{
// line-height: ;
// font-weight: 600;
// }
&.fw7{
font-weight: 700;
}
&.h2{
font-size: 18px;
}
@ -321,7 +392,24 @@ a.ant-dropdown-trigger{
font-weight: 700;
line-height: 18px;
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{
@ -342,6 +430,15 @@ a.ant-dropdown-trigger{
.ant-pro-global-header-logo img {
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{
// }

@ -1,16 +1,304 @@
import { Modal, Tabs } from 'antd';
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 ReactEcharts from 'echarts-for-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 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 (
<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>
);
};
@ -18,6 +306,8 @@ const DeviceBaseInfo: React.FC = () => {
// 设备信息
const DeviceLogInfo: React.FC = () => {
// 动态设置每页数量
const [currentPageSize, setCurrentPageSize] = useState<number>(10);
const columns: ProColumns<Record<string, any>[]> = [
{
title: (
@ -75,6 +365,7 @@ const DeviceLogInfo: React.FC = () => {
hideInSearch: true,
},
];
let testData: Record<string, any>[] = [];
for (let i = 0; i < 8; i++) {
testData.push({
@ -93,32 +384,43 @@ const DeviceLogInfo: React.FC = () => {
search={false}
options={{ fullScreen: false, setting: false, density: false, reload: false }}
rowKey="key"
request={async () => {
// 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';
// }
// let resp = await getSysOperationRecordGetOperationRecordList({...reqParams})
request={async (params = {}, sort) => {
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: testData,
total: 8,
page: 1,
pageSize: 8,
},
};
return {
data: testData,
data: resp.data.list,
success: resp.success,
// total: resp.data.total,
// current: resp.data.page,
// pageSize: resp.data.pageSize
total: resp.data.total,
current: resp.data.page,
pageSize: resp.data.pageSize,
};
}}
pagination={false}
pagination={{
...proTablePaginationOptions,
pageSize: currentPageSize,
onChange: (page, pageSize) => setCurrentPageSize(pageSize),
}}
columns={columns}
></ProTable>
);
@ -153,7 +455,7 @@ const DetailInfoCard: React.FC<DetailInfoCardProps> = (props) => {
{
key: 'deviceInfo',
label: intl.formatMessage({
id: 'pages.login.accountLogin.tab',
id: 'DCSDeviceList.deviceStatus.detailModel.baseInfo',
defaultMessage: '设备信息',
}),
},

@ -2,7 +2,7 @@
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-06 16:12:17
* @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
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
@ -21,9 +21,9 @@ const listItemStyle = {
display: 'flex',
fontSize: 14,
color: '#333333',
maxWidth: '22vh',
width: '100%',
alignItems: 'center',
padding: '5px 0',
padding: '8px 0 0',
};
const listItemLabelStyle = {
@ -48,7 +48,7 @@ type DeviceItemProgress = {
};
// 进度条
// TODO 进度条的边框圆角调整为矩形
const DeviceItemProgress: React.FC<DeviceItemProgress> = (props) => {
let strokeColor = 'rgb(243,48,5)';
switch (props.label) {
@ -61,15 +61,15 @@ const DeviceItemProgress: React.FC<DeviceItemProgress> = (props) => {
case '存储':
strokeColor = 'rgb(33,169,122)';
break;
case 'NPU':
case 'GPU':
strokeColor = 'rgb(250,173,20)';
break;
}
return (
<div style={{ width: '100%', display: 'flex' }}>
<div style={{ width: '100%', display: 'flex' }} className='rectProgress_box'>
<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>
);
};
@ -94,7 +94,7 @@ const DeviceStatusCard: React.FC<UpdateProjectProps> = ({
<span style={{ fontWeight: 700, fontSize: 14, paddingRight: 10 }}></span>
<Tag color="#44AEF5"></Tag>
</div> */}
<ul>
<ul style={{width: '100%'}}>
<li style={listItemStyle}>
<DeviceItemProgress label="CPU" percent={0.79}></DeviceItemProgress>
</li>
@ -105,7 +105,7 @@ const DeviceStatusCard: React.FC<UpdateProjectProps> = ({
<DeviceItemProgress label="存储" percent={0.16}></DeviceItemProgress>
</li>
<li style={listItemStyle}>
<DeviceItemProgress label="NPU" percent={0.58}></DeviceItemProgress>
<DeviceItemProgress label="GPU" percent={0.58}></DeviceItemProgress>
</li>
</ul>
</div>

@ -2,19 +2,20 @@
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-12-08 10:11:54
* @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
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import TableActionCard from '@/components/TableActionCard';
import IsConfirmAction from '@/components/TableActionCard/isConfirmAction';
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 { Button, Tag } from 'antd';
import React, { useState } from 'react';
import DeviceStatusCard from './components/DeviceStatusCard';
import { proTableCommonOptions, proTablePaginationOptions } from '../../../../config/defaultTable';
import DetailInfoCard from './components/DetailInfoCard';
import DeviceStatusCard from './components/DeviceStatusCard';
/**
* @
@ -30,185 +31,275 @@ const tabOptions: Record<string, any> = {
errorStatus: 20,
};
const DeviceStatus: React.FC = () => {
const [cardActionProps, setCardActionProps] = useState<'actions' | 'extra'>('extra');
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 [ghost, setGhost] = useState<boolean>(false);
const handleDetailModal = () => {
if (detailModalOpen) {
setDetailModalOpen(false);
setCurrentRow({});
} else {
setDetailModalOpen(true);
}
};
const data = [{status: '在线'},{status: '在线'}, {status: '故障'},{status: '故障'},{status: '运行中'},{status: '在线'},{status: '在线'}, {status: '离线'}].map(
(record, index) => {
let currColor = 'default';
switch (record.status) {
case '在线':
currColor = 'success';
break;
case '故障':
currColor = 'error';
break;
case '运行中':
currColor = 'warning';
break;
default:
currColor = 'default';
break;
}
return {
content: (
<ProCard style={{ backgroundColor: '#FAFAFA' }} bodyStyle={{ margin: 0, padding: 0 }}>
<div
style={{
display: 'flex',
alignItems: 'center',
padding: 15,
justifyContent: 'space-between',
}}
>
<div>
<Tag color={currColor}>{record.status}</Tag>
<span>{index + 1}</span>
</div>
<TableActionCard
key="TableActionCardRef"
renderActions={[
{
key: 'update',
renderDom: (
<IsConfirmAction
key="reOpen"
title={'重启'}
buttonFormatText={'pages.searchTable.reOpen'}
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>
const dataTestList = [
{ status: '在线' },
{ status: '在线' },
{ status: '故障' },
{ status: '故障' },
{ status: '运行中' },
{ status: '在线' },
{ status: '在线' },
{ status: '离线' },
].map((record, index) => {
let currColor = 'default';
switch (record.status) {
case '在线':
currColor = 'success';
break;
case '故障':
currColor = 'error';
break;
case '运行中':
currColor = 'warning';
break;
default:
currColor = 'default';
break;
}
return {
content: (
<ProCard className="gn"
style={{ backgroundColor: '#FAFAFA', margin: 0, padding: 0 }} bodyStyle={{ margin: 0, padding: 0 }}>
<div
style={{
display: 'flex',
alignItems: 'center',
padding: 12,
justifyContent: 'space-between',
borderBottom: '1px solid rgba(224, 224, 224, 1)'
}}
>
<div style={{
display: 'flex',
alignItems: 'center',
maxWidth: '60%'
}}>
<Tag color={currColor}>{record.status}</Tag>
<p className='gn single_line text_1 fw7' style={{maxWidth: '80%', padding: 0, margin: 0}}>{index + 1}</p>
</div>
<DeviceStatusCard info={record}></DeviceStatusCard>{' '}
</ProCard>
),
};
<TableActionCard
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 (
<PageContainer>
<ProCard bodyStyle={{ padding: 16, margin: 0 }}>
<div>
{Object.keys(tabOptions).map((item, index) => {
// eslint-disable-next-line react/jsx-key
return (
<Button
style={{ marginRight: 12 }}
type={activeTabIndex === index ? 'primary' : 'default'}
key={index}
onClick={() => {
setActiveTabIndex(index);
}}
>
{Object.keys(deviceStatusEnums).includes(item)
? deviceStatusEnums[item].miniName
: ''}
{tabOptions[item]}
</Button>
);
})}
</div>
<ProList<any>
className="gn"
ghost={true}
itemCardProps={{
ghost: true,
bodyStyle: { padding: 0, margin: 0 },
}}
pagination={{
defaultPageSize: 8,
showSizeChanger: false,
}}
showActions="hover"
rowSelection={false}
grid={{ gutter: 16, xs: 1, md: 2, lg: 3, xl: 4, xxl: 4 }}
metas={{
type: {},
content: {},
actions: {
cardActionProps,
<ProList<any>
className="gn"
ghost={true}
itemCardProps={{
ghost: true,
bodyStyle: { padding: 0, margin: 0 },
}}
search={{
labelWidth: proTableCommonOptions.searchLabelWidth,
}}
headerTitle={
<>
<div>
{Object.keys(tabOptions).map((item, index) => {
// eslint-disable-next-line react/jsx-key
return (
<Button
style={{ marginRight: 12 }}
type={activeTabIndex === index ? 'primary' : 'default'}
key={index}
onClick={() => {
setActiveTabIndex(index);
}}
>
{Object.keys(deviceStatusEnums).includes(item)
? deviceStatusEnums[item].miniName
: ''}
{tabOptions[item]}
</Button>
);
})}
</div>
</>
}
cardProps={{
bodyStyle: {
background: 'white',
padding: '8px 16px 16px',
borderRadius: 8
}
}}
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=""
// toolBarRender={(action, rows) => {
// console.log(action, rows, 'toolBarRender');
// // TODO 需要对接接口
// const isProcess: boolean = false;
// return isProcess ? (
// <Button type="primary" danger>
// 结束运行
// </Button>
// ) : (
// <Button type="primary">
// 开始运行
// </Button>
// );
// }}
dataSource={data}
/>
</ProCard>
<DetailInfoCard detailModalOpen={detailModalOpen} handleDetailModal={handleDetailModal}>
</DetailInfoCard>
},
status2: {
// 自己扩展的字段,主要用于筛选,不在列表中显示
title: '分类',
valueType: 'select',
valueEnum: {
'0': { text: '全部分类', status: '0' },
'1': {
text: '外围监控',
status: '1',
},
'2': {
text: '室内监控',
status: '2',
},
'3': {
text: '违规监控',
status: '3',
},
},
},
}}
request={async (params = {}, sort) => {
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>
);
};

Loading…
Cancel
Save