Browse Source

(*)网关设备列表 代码暂交

master
wuqun 2 years ago
parent
commit
7fe071bb8c
  1. 4
      code/web/client/src/components/index.js
  2. 18
      code/web/client/src/components/skeletonScreen.jsx
  3. 39
      code/web/client/src/sections/edition/actions/index.js
  4. 151
      code/web/client/src/sections/edition/containers/gateway.jsx
  5. 33
      code/web/client/src/sections/edition/containers/gatewayEditModal.jsx
  6. 53
      code/web/client/src/sections/edition/containers/gatewayStatusModal.jsx
  7. 3
      code/web/client/src/utils/webapi.js

4
code/web/client/src/components/index.js

@ -1,6 +1,8 @@
'use strict'; 'use strict';
import Coming from './coming' import Coming from './coming'
import { SkeletonScreen } from './skeletonScreen'
export { export {
Coming Coming,
SkeletonScreen
}; };

18
code/web/client/src/components/skeletonScreen.jsx

@ -0,0 +1,18 @@
import React, { useState, useEffect } from "react";
import { Skeleton } from "@douyinfe/semi-ui";
export function SkeletonScreen () {
return <>
<Skeleton.Title style={{ width: "95%", height: 24, margin: "8px 20px" }} />
<Skeleton.Title style={{ width: "80%", height: 28, margin: "16px 20px" }} />
<Skeleton.Title style={{ width: "50%", height: 28, margin: "16px 20px" }} />
<Skeleton.Title style={{ width: "60%", height: 28, margin: "16px 20px" }} />
<Skeleton.Title style={{ width: "90%", height: 28, margin: "16px 20px" }} />
<Skeleton.Title style={{ width: "70%", height: 28, margin: "16px 20px" }} />
<Skeleton.Title style={{ width: "50%", height: 28, margin: "16px 20px" }} />
<Skeleton.Title style={{ width: "40%", height: 28, margin: "16px 20px" }} />
<Skeleton.Title style={{ width: "60%", height: 28, margin: "16px 20px" }} />
<Skeleton.Title style={{ width: "40%", height: 28, margin: "16px 20px" }} />
</>
}

39
code/web/client/src/sections/edition/actions/index.js

@ -1,6 +1,43 @@
'use strict'; 'use strict';
import { basicAction } from '@peace/utils'
import { ApiTable } from '$utils'
export default { export function getGateways(query = {}) {
return dispatch => basicAction({
type: 'get',
dispatch: dispatch,
query: query,
actionType: 'GET_GATEWAY_LIST',
url: ApiTable.getGateways,
msg: { option: '查询网关列表' },
reducer: { name: 'getGateways' }
});
}
export function getGatewayStatus(id) {
return dispatch => basicAction({
type: 'get',
dispatch: dispatch,
actionType: 'GET_GATEWAY_STATUS',
url: ApiTable.getGatewayStatus.replace('{id}', id),
msg: { option: '查询网关状态指标' },
reducer: { name: 'getGatewayStatus' }
});
}
export function ableGateway(id, data) {
return dispatch => basicAction({
type: 'put',
data: data,
dispatch: dispatch,
actionType: 'ABLE_GATEWAY',
url: ApiTable.ableGateway.replace('{id}', id),
msg: { option: '使能网关' },
});
}
export default {
getGateways,
getGatewayStatus,
ableGateway
}; };

151
code/web/client/src/sections/edition/containers/gateway.jsx

@ -1,24 +1,159 @@
'use strict'; 'use strict';
import React, { useEffect, useRef } from 'react'; import React, { useEffect, useState, useRef } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { push } from 'react-router-redux'; import { push } from 'react-router-redux';
import { Form, Button, Toast, Table } from '@douyinfe/semi-ui'; import { Popconfirm, Button, Toast, Skeleton, Table, Tag } from '@douyinfe/semi-ui';
import { IconLock, IconUser } from '@douyinfe/semi-icons'; import { IconChevronDown } from '@douyinfe/semi-icons';
import { SkeletonScreen } from "$components";
import GatewayStatusModal from './gatewayStatusModal'
import GatewayEditModal from './gatewayEditModal'
const GatewayManage = props => { const GatewayManage = props => {
const { dispatch, user, error, actions, apiRoot, isRequesting } = props const { dispatch, user, error, actions } = props
const { edition } = actions;
const [query, setQuery] = useState({ limit: 10, page: 0 }); //
const [tableData, setTableData] = useState([]);
const [limits, setLimits] = useState()//
const [detailV, setDetailV] = useState(false)
const [editV, setEditV] = useState(false)
const [dataToModal, setDataToModal] = useState(null)
useEffect(() => { useEffect(() => {
getTableData(query)
}, [])
const getTableData = (obj) => {
let { limit, page } = obj
let queryObj = { limit, offset: limit * page }
dispatch(edition.getGateways(queryObj)).then(res => {//
if (res.success) {
setTableData(res.payload.data.data);
setLimits(res.payload.data.total);
}
})
}
const ableDevice = (id, v) => {
let ableObj = { "enabled": v }
dispatch(edition.ableGateway(id, ableObj)).then(r => {
if (r.success) {
getTableData(query)
}
})
}
const aStyle = { color: '#40a9ff', cursor: 'pointer' }
const columns = [
{
title: "序列号",
dataIndex: "serialNo",
key: "serialNo",
}, {
title: "名称",
dataIndex: "name",
key: "name",
}, {
title: "在线状态",
dataIndex: "state",
key: "state",
render: (text, record) => {
return text ? <Tag color='green'>在线</Tag> : <Tag color='grey'>离线</Tag>
}
}, {
title: "固件信息",
dataIndex: "hardwareName",
key: "hardwareName",
}, {
title: "软件信息",
dataIndex: "softwareVer",
key: "softwareVer",
render: (text, record) => <span>{text || '-'}</span>
}, {
title: "绑定结构物数",
dataIndex: "thingIds",
key: "thingIds",
render: (text, record) => <span>{text.length}</span>
}, {
title: "是否启用",
dataIndex: "enabled",
key: "enabled",
render: (text, record) => <span>{text ? '是' : '否'}</span>
}, {
title: "状态详情",
dataIndex: "detail",
key: "detail",
render: (text, record) => <a style={aStyle} onClick={() => {
setDetailV(true)
setDataToModal(record)
}}>查看</a>
}, {
title: "操作",
dataIndex: "action",
key: "action",
render: (text, record) => {
return <div>
<Popconfirm
title="提示"
content={`确认${record.enabled ? '禁用' : '启用'}该网关?`}
onConfirm={() => {
ableDevice(record.id, !record.enabled)
}}>
<a style={aStyle}>{record.enabled ? '禁用' : '启用'}</a>
</Popconfirm>
<a style={{ ...aStyle, marginLeft: 15 }} onClick={() => {
setEditV(true)
setDataToModal(record)
}}>编辑</a>
<a style={{ ...aStyle, marginLeft: 15 }} onClick={() => {
}, []) }}>删除</a>
<span style={{ ...aStyle, marginLeft: 15 }} onClick={() => {
}}>更多<IconChevronDown /></span>
</div>
}
}
];
return ( return (
<div style={{}}> <div style={{}}>
网关设备列表 <Skeleton
loading={false}
active={true}
placeholder={SkeletonScreen()}
>
<Table
columns={columns}
dataSource={tableData}
bordered={false}
empty="暂无数据"
style={{
padding: "0px 20px",
}}
pagination={{
current: query.page + 1,
total: limits,
showSizeChanger: true,
showQuickJumper: true,
showTotal: (total) => {
return <span style={{ fontSize: 15 }}>{`${Math.ceil(total / limits)}页,${total}`}</span>
},
onChange: (page, pageSize) => {
setQuery({ limit: pageSize, page: page - 1 });
getTableData({ limit: pageSize, page: page - 1 });
}
}}
/>
</Skeleton>
{
detailV ? <GatewayStatusModal
onCancel={() => setDetailV(false)}
dataToModal={dataToModal} /> : ''
}
{
editV ? <GatewayEditModal
onCancel={() => setEditV(false)}
dataToModal={dataToModal} /> : ''
}
</div> </div>
); );
} }

33
code/web/client/src/sections/edition/containers/gatewayEditModal.jsx

@ -0,0 +1,33 @@
import React, { useEffect, useRef, useState } from 'react';
import moment from 'moment';
import { connect } from "react-redux";
import { Select, Modal, Form, Button } from "@douyinfe/semi-ui";
const GatewayEditModal = (props) => {
const { dispatch, actions, user, onCancel, dataToModal } = props;
const { edition } = actions;
//
useEffect(() => {
}, []);
return (
<Modal title={dataToModal.name}
visible={true} destroyOnClose onCancel={onCancel}
footer={[<Button onClick={onCancel}>关闭</Button>]}>
<div></div>
</Modal>
)
}
function mapStateToProps(state) {
const { auth, global } = state;
return {
user: auth.user,
error: auth.error,
actions: global.actions,
};
}
export default connect(mapStateToProps)(GatewayEditModal);

53
code/web/client/src/sections/edition/containers/gatewayStatusModal.jsx

@ -0,0 +1,53 @@
import React, { useEffect, useRef, useState } from 'react';
import { connect } from "react-redux";
import { Select, Modal, Form, Button } from "@douyinfe/semi-ui";
const GatewayStatusModal = (props) => {
const { dispatch, actions, user, onCancel, dataToModal } = props;
const { edition } = actions;
const [listData, setListData] = useState(null);
//
useEffect(() => {
dispatch(edition.getGatewayStatus(dataToModal.id)).then(res => {//
if (res.success) {
setListData(res.payload.data)
}
})
}, []);
const statusKeys = {
status: '状态',
streamIn: '流入',
streamOut: '流出',
memUsedPercent: '内存使用',
diskPercent: '磁盘使用',
timeDiff: '时间偏差(最新心跳 服务器时间-设备时间)',
uptime: '本次在线时常',//???
sysVersion: '系统',
status: '软件信息',//???
status: '配置版本',//???
acqConfVersion: '采集参数版本',//???
pluginVersion: '插件版本',
load1: 'Load1',
load5: 'Load5',
load15: 'Load15',
}
return (
<Modal title={dataToModal.name}
visible={true} destroyOnClose onCancel={onCancel}
footer={[<Button onClick={onCancel}>关闭</Button>]}>
<div></div>
</Modal>
)
}
function mapStateToProps(state) {
const { auth, global } = state;
return {
user: auth.user,
error: auth.error,
actions: global.actions,
};
}
export default connect(mapStateToProps)(GatewayStatusModal);

3
code/web/client/src/utils/webapi.js

@ -5,6 +5,9 @@ export const ApiTable = {
logout: 'v1/logout', logout: 'v1/logout',
crossCheck: 'cross_token/check', crossCheck: 'cross_token/check',
getGateways: 'v1/edges',
ableGateway: 'v1/edge/{id}/enable',
getGatewayStatus: 'v1/edge/{id}/metrics'
}; };
export const RouteTable = { export const RouteTable = {

Loading…
Cancel
Save