19 changed files with 743 additions and 9 deletions
After Width: | Height: | Size: 577 B |
@ -0,0 +1,56 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
import { basicAction } from '@peace/utils' |
||||
|
import { ApiTable } from '$utils' |
||||
|
|
||||
|
export function getDeviceList(query) { |
||||
|
return dispatch => basicAction({ |
||||
|
type: 'get', |
||||
|
dispatch: dispatch, |
||||
|
query: query || {}, |
||||
|
actionType: 'GET_Device_REPORT', |
||||
|
url: `${ApiTable.getDeviceList}`, |
||||
|
msg: { error: '获取设备列表失败' }, |
||||
|
reducer: { name: 'device' } |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
export function addDevice(params) { |
||||
|
return (dispatch) => basicAction({ |
||||
|
type: 'post', |
||||
|
data: params, |
||||
|
dispatch, |
||||
|
actionType: 'ADD_Device_REPORT', |
||||
|
url: ApiTable.addDevice, |
||||
|
msg: { |
||||
|
option: '设备新增', |
||||
|
}, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
export function deleteDevice(id) { |
||||
|
return (dispatch) => basicAction({ |
||||
|
type: 'del', |
||||
|
dispatch, |
||||
|
actionType: 'DELETE_Device_REPORT', |
||||
|
url: ApiTable.modifyDevice.replace('{id}', id), |
||||
|
msg: { |
||||
|
option: '设备删除', |
||||
|
}, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
export function modifyDevice(id, params, msg) { |
||||
|
return (dispatch) => basicAction({ |
||||
|
type: 'put', |
||||
|
data: params, |
||||
|
dispatch, |
||||
|
actionType: 'MODIFY_Device_REPORT', |
||||
|
url: ApiTable.modifyDevice.replace('{id}', id), |
||||
|
msg: { |
||||
|
option: msg || '设备编辑', |
||||
|
}, |
||||
|
}); |
||||
|
} |
||||
|
|
@ -0,0 +1,7 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
import * as device from './device' |
||||
|
|
||||
|
export default { |
||||
|
...device |
||||
|
} |
@ -0,0 +1,213 @@ |
|||||
|
'use strict'; |
||||
|
import React, { useState, useEffect } from 'react'; |
||||
|
import { connect } from 'react-redux'; |
||||
|
import moment from 'moment'; |
||||
|
import { Modal, Form, Button, Upload, message } from 'antd'; |
||||
|
import { DownloadOutlined } from '@ant-design/icons'; |
||||
|
import XLSX from 'xlsx'; |
||||
|
import { DEVICE_TYPES } from './modelModal'; |
||||
|
// import porvince from './province.json'
|
||||
|
const workerKeys = { |
||||
|
name: '设备名称', |
||||
|
type: '设备类型', |
||||
|
specification: '规格型号', |
||||
|
dateProduced: '生产日期', |
||||
|
dateInstall: '安装时间', |
||||
|
dateGuarantee: '质保期', |
||||
|
dateMainten: '维保期', |
||||
|
} |
||||
|
//下载模板和上传文件读取
|
||||
|
const ImportDeviceModal = props => { |
||||
|
const { dispatch, actions, onCancel, onOk, devices } = props; |
||||
|
const { deviceManage } = actions; |
||||
|
const [msg, setMsg] = useState(''); |
||||
|
const [loading, setLoading] = useState(false); |
||||
|
const [postData, setPostData] = useState([]); |
||||
|
|
||||
|
//初始化
|
||||
|
useEffect(() => { |
||||
|
|
||||
|
}, []); |
||||
|
|
||||
|
const confirm = () => { |
||||
|
if (postData.length) { |
||||
|
setLoading(true) |
||||
|
//导入明细接口通用
|
||||
|
dispatch(deviceManage?.addDevice(postData)).then(res => { |
||||
|
if (res.success) { |
||||
|
onOk() |
||||
|
} |
||||
|
setLoading(false) |
||||
|
}) |
||||
|
} else { |
||||
|
message.warning({ content: '没有数据可以提交,请上传数据文件', duration: 2 }) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
const dldCsvMb = () => { |
||||
|
//表头
|
||||
|
let head = []; |
||||
|
Object.keys(workerKeys).map(key => { |
||||
|
head.push(workerKeys[key]); |
||||
|
}) |
||||
|
head = head.join(',') + "\n"; |
||||
|
//数据
|
||||
|
//let data = 1 + ',' + 2 + ',' + 3 + ',' + 4 + ',' + 5
|
||||
|
let templateCsv = "data:text/xls;charset=utf-8,\ufeff" + head; |
||||
|
//创建一个a标签
|
||||
|
let link = document.createElement("a"); |
||||
|
//为a标签设置属性
|
||||
|
link.setAttribute("href", templateCsv); |
||||
|
link.setAttribute("download", `设备导入模板.xls`); |
||||
|
//点击a标签
|
||||
|
link.click(); |
||||
|
} |
||||
|
const download = () => { |
||||
|
dldCsvMb(); |
||||
|
} |
||||
|
|
||||
|
const judgeTimeValid = (v) => { |
||||
|
let valid = true; |
||||
|
if (v.split('/').length !== 3) { |
||||
|
valid = false; |
||||
|
} else { |
||||
|
let time = new Date(v); |
||||
|
// if (!time) {
|
||||
|
// return valid;//可以不填
|
||||
|
// }
|
||||
|
const ymd = /^((19|20)[0-9]{2})[\/\-]((0[1-9])|(1[0-2]))[\/\-]((0[1-9])|((1|2)[0-9])|(3[0-1]))$/;//年月日
|
||||
|
if (time instanceof Date) { |
||||
|
let timeStr = moment(time).format('YYYY/MM/DD'); |
||||
|
if (!ymd.test(timeStr)) { |
||||
|
valid = false; |
||||
|
} |
||||
|
} else { |
||||
|
valid = false; |
||||
|
} |
||||
|
} |
||||
|
return valid; |
||||
|
} |
||||
|
|
||||
|
return (<Modal |
||||
|
title={"导入设备信息"} visible={true} |
||||
|
onOk={confirm} width={520} |
||||
|
confirmLoading={loading} |
||||
|
onCancel={() => { |
||||
|
setMsg('') |
||||
|
setLoading(false) |
||||
|
setPostData([]) |
||||
|
onCancel() |
||||
|
}} |
||||
|
> |
||||
|
<Form> |
||||
|
<Upload |
||||
|
action={'/'} accept={'.xls,.xlsx'} |
||||
|
maxCount={1} |
||||
|
onRemove={(currentFile, fileList, fileItem) => { |
||||
|
setMsg(''); |
||||
|
setPostData([]); |
||||
|
}} |
||||
|
customRequest={async (data) => { |
||||
|
const { file, onSuccess, onError } = data |
||||
|
const error = (msg) => { |
||||
|
setMsg(msg) |
||||
|
onError({ message: msg }) |
||||
|
} |
||||
|
let isLt = file.size / 1024 / 1024 < 200 |
||||
|
if (!isLt) { |
||||
|
error(`文件最大不超过200M`); |
||||
|
return; |
||||
|
} |
||||
|
const reader = new FileReader(); |
||||
|
reader.onload = function (e) { |
||||
|
const data = e.target.result; |
||||
|
const workbook = XLSX.read(data, { type: 'binary', codepage: 936 }); |
||||
|
const firstSheetName = workbook.SheetNames[0]; |
||||
|
const worksheet = workbook.Sheets[firstSheetName]; |
||||
|
|
||||
|
//XLSX.utils.sheet_to_json解析 ------把身份证号和手机号变成 字符串------
|
||||
|
Object.keys(worksheet).forEach(k => { |
||||
|
worksheet[k].w ? worksheet[k].v = worksheet[k].w : '' |
||||
|
}) |
||||
|
//------------------end------------------
|
||||
|
|
||||
|
const res = XLSX.utils.sheet_to_json(worksheet); |
||||
|
|
||||
|
if (res.length > 1000) { |
||||
|
error('一次性上传数据行数应小于1000行,请分批上传') |
||||
|
return |
||||
|
} |
||||
|
if (!res.length) { |
||||
|
error('请填写至少一行数据') |
||||
|
return |
||||
|
} |
||||
|
let postData = [] |
||||
|
|
||||
|
for (let i = 0; i < res.length; i++) { |
||||
|
let d = res[i] |
||||
|
let obj = {}; |
||||
|
Object.keys(workerKeys).map(key => { |
||||
|
obj[key] = d[workerKeys[key]] || null; |
||||
|
}) |
||||
|
//必填项
|
||||
|
let notNullKeys = ['name', 'type', 'specification', 'dateProduced', 'dateGuarantee', 'dateMainten', 'dateInstall'] |
||||
|
for (let k = 0; k < notNullKeys.length; k++) { |
||||
|
let key = notNullKeys[k]; |
||||
|
if (!obj[key]) { |
||||
|
error(`第${i + 2}行【${workerKeys[key]}】不能为空`) |
||||
|
return |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
//判断设备类型
|
||||
|
let ext = DEVICE_TYPES.find(m => m == obj.type); |
||||
|
if (!ext) { |
||||
|
error(`第${i + 2}行的【设备类型】错误,请填写【${DEVICE_TYPES.toString()}】中的一种`) |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
let tValid = judgeTimeValid(obj.dateProduced) && judgeTimeValid(obj.dateGuarantee) |
||||
|
&& judgeTimeValid(obj.dateMainten) && judgeTimeValid(obj.dateInstall); |
||||
|
if (!tValid) { |
||||
|
error(`第${i + 2}行【日期格式】错误,请填写yyyy/mm/dd格式`) |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
let dateInstallValid = moment(obj.dateInstall).valueOf() > moment().startOf('d').add(1, 'd').valueOf(); |
||||
|
if (dateInstallValid) { |
||||
|
error(`第${i + 2}行【安装日期】不能填写今天之后的时间`) |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
postData.push(obj) |
||||
|
} |
||||
|
setPostData(postData) |
||||
|
let msg = '文件解析完成,点击确定按钮上传保存!' |
||||
|
setMsg(msg) |
||||
|
onSuccess({ message: msg }) |
||||
|
} |
||||
|
reader.readAsBinaryString(file); |
||||
|
}}> |
||||
|
<Button icon={<DownloadOutlined />} theme="light"> |
||||
|
请选择文件 |
||||
|
</Button> |
||||
|
</Upload> |
||||
|
<span>{msg}</span> |
||||
|
<div style={{ color: '#ccc', marginTop: 20 }}>最大不超过200M,导入文件需与 |
||||
|
<span onClick={() => download()} style={{ cursor: 'pointer', color: '#0066FF' }}>导入模板</span> |
||||
|
一致</div> |
||||
|
</Form> |
||||
|
</Modal>) |
||||
|
} |
||||
|
|
||||
|
function mapStateToProps(state) { |
||||
|
const { auth, global } = state; |
||||
|
return { |
||||
|
user: auth.user, |
||||
|
actions: global.actions, |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default connect(mapStateToProps)(ImportDeviceModal); |
@ -0,0 +1,111 @@ |
|||||
|
import React, { useRef } from 'react'; |
||||
|
import { Button, Form } from 'antd'; |
||||
|
import { InfoCircleOutlined } from '@ant-design/icons'; |
||||
|
import { |
||||
|
ModalForm, |
||||
|
ProFormSelect, |
||||
|
ProFormText, |
||||
|
ProFormDatePicker |
||||
|
} from '@ant-design/pro-form'; |
||||
|
import moment from 'moment'; |
||||
|
export default (props) => { |
||||
|
const { title, triggerRender, editData = null, onFinish, devices } = props; |
||||
|
const formItemLayout = { labelCol: { span: 6 }, wrapperCol: { span: 16 } }; |
||||
|
const initialValues = editData ? { |
||||
|
...editData, |
||||
|
} : {}; |
||||
|
const [form] = Form.useForm(); |
||||
|
const formRef = useRef(); |
||||
|
const disabledDate = (value) => { |
||||
|
return value.valueOf() > moment().startOf('d').add(1, 'd').valueOf(); |
||||
|
} |
||||
|
return ( |
||||
|
<ModalForm |
||||
|
formRef={formRef} |
||||
|
title={title || ''} |
||||
|
initialValues={initialValues} |
||||
|
trigger={ |
||||
|
triggerRender ? triggerRender : <Button type="primary" > |
||||
|
{title || ''} |
||||
|
</Button> |
||||
|
} |
||||
|
layout="horizontal" |
||||
|
grid={true} |
||||
|
{...formItemLayout} |
||||
|
modalProps={{ |
||||
|
destroyOnClose: true, |
||||
|
onCancel: () => { }, |
||||
|
}} |
||||
|
onFinish={async (values) => { |
||||
|
return onFinish && await onFinish(values, editData, form) |
||||
|
// return true;
|
||||
|
}} |
||||
|
width={500} |
||||
|
> |
||||
|
|
||||
|
|
||||
|
<ProFormText |
||||
|
rules={[ |
||||
|
{ required: true, message: '请输入设备名称' }, |
||||
|
{ max: 255, message: '设备名称长度不能大于255个字符' }, |
||||
|
]} |
||||
|
name="name" |
||||
|
label="设备名称" |
||||
|
/> |
||||
|
|
||||
|
<ProFormSelect |
||||
|
rules={[{ required: true, message: '请选择设备类型' }]} |
||||
|
options={ |
||||
|
DEVICE_TYPES |
||||
|
.map(s => { |
||||
|
return { label: s, value: s } |
||||
|
}) |
||||
|
} |
||||
|
name="type" |
||||
|
label="设备类型" |
||||
|
/> |
||||
|
|
||||
|
<ProFormText |
||||
|
rules={[ |
||||
|
{ required: true, message: '请输入规格型号' }, |
||||
|
{ max: 20, message: '规格型号长度不能大于20个字符' }, |
||||
|
]} |
||||
|
name="specification" |
||||
|
label="规格型号" |
||||
|
/> |
||||
|
|
||||
|
<ProFormDatePicker |
||||
|
rules={[{ required: true, message: '请输入生产日期' }]} |
||||
|
name="dateProduced" |
||||
|
label="生产日期" |
||||
|
fieldProps={ |
||||
|
{ disabledDate: disabledDate } |
||||
|
} |
||||
|
|
||||
|
/> |
||||
|
<ProFormDatePicker |
||||
|
rules={[{ required: true, message: '请输入安装日期' }]} |
||||
|
name="dateInstall" |
||||
|
label="安装日期" |
||||
|
fieldProps={ |
||||
|
{ disabledDate: disabledDate } |
||||
|
} |
||||
|
|
||||
|
/> |
||||
|
<ProFormDatePicker |
||||
|
rules={[{ required: true, message: '请输入质保期' }]} |
||||
|
name="dateGuarantee" |
||||
|
label="质保期" |
||||
|
/> |
||||
|
<ProFormDatePicker |
||||
|
rules={[{ required: true, message: '请输入维保期' }]} |
||||
|
name="dateMainten" |
||||
|
label="维保期" |
||||
|
/> |
||||
|
|
||||
|
</ModalForm> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
export const DEVICE_TYPES = ['安防系统', '厨房系统', '电梯', '供电系统', '空调', '排水系统', '水系统', '通道门禁', |
||||
|
'通风系统', '通信系统', '显示视频', '消防系统', '照明系统'] |
@ -0,0 +1,254 @@ |
|||||
|
import React, { useEffect, useState } from 'react' |
||||
|
import { Spin, Popconfirm, message, Button, Input } from 'antd'; |
||||
|
import { connect } from 'react-redux'; |
||||
|
import ProTable from '@ant-design/pro-table'; |
||||
|
import DeviceModal from '../components/modelModal' |
||||
|
import moment from 'moment'; |
||||
|
import ImportDeviceModal from '../components/importDevicesModal' |
||||
|
function DeviceManagement(props) { |
||||
|
const { loading, clientHeight, actions, dispatch, devices } = props; |
||||
|
const [pageSize, setPageSize] = useState(10); |
||||
|
const [currentPage, setCurrentPage] = useState(1); |
||||
|
const [rowSelected, setRowSelected] = useState([]) |
||||
|
const [showImportModal, setShowImportModal] = useState(false); |
||||
|
const [name, setName] = useState(); |
||||
|
|
||||
|
const queryData = (search) => { |
||||
|
const query = { |
||||
|
limit: search ? 10 : pageSize || 10, |
||||
|
page: search ? 1 : currentPage || 1, |
||||
|
name: name |
||||
|
} |
||||
|
dispatch(actions.deviceManage.getDeviceList(query)); |
||||
|
} |
||||
|
|
||||
|
useEffect(() => { |
||||
|
queryData(); |
||||
|
}, [pageSize, currentPage]); |
||||
|
|
||||
|
const handleDelete = (id) => { |
||||
|
dispatch(actions.deviceManage.deleteDevice(id)).then(() => { |
||||
|
queryData(); |
||||
|
setRowSelected([]) |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
const onFinish = async (values, editData) => { |
||||
|
if (editData) { |
||||
|
const dataToSave = { ...values } |
||||
|
return dispatch( |
||||
|
actions.deviceManage.modifyDevice(editData.id, dataToSave, values?.msg || ''), |
||||
|
).then((res) => { |
||||
|
if (res.success) { |
||||
|
queryData(); |
||||
|
return true; |
||||
|
} else { |
||||
|
return false; |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
return dispatch(actions.deviceManage.addDevice({ |
||||
|
...values, |
||||
|
})).then(res => { |
||||
|
if (res.success) { |
||||
|
queryData(); |
||||
|
return true; |
||||
|
} else { |
||||
|
return false; |
||||
|
} |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
const columns = [ |
||||
|
{ |
||||
|
title: '设备名称', |
||||
|
dataIndex: 'name', |
||||
|
ellipsis: true, |
||||
|
}, |
||||
|
{ |
||||
|
title: '设备类型', |
||||
|
dataIndex: 'type', |
||||
|
ellipsis: true, |
||||
|
}, |
||||
|
{ |
||||
|
title: '规格型号', |
||||
|
dataIndex: 'specification', |
||||
|
ellipsis: true, |
||||
|
}, |
||||
|
{ |
||||
|
title: '生产日期', |
||||
|
dataIndex: 'dateProduced', |
||||
|
ellipsis: true, |
||||
|
}, |
||||
|
{ |
||||
|
title: '安装时间', |
||||
|
dataIndex: 'dateInstall', |
||||
|
ellipsis: true, |
||||
|
}, |
||||
|
{ |
||||
|
title: '质保期', |
||||
|
dataIndex: 'dateGuarantee', |
||||
|
ellipsis: true, |
||||
|
search: false, |
||||
|
}, |
||||
|
{ |
||||
|
title: '维保期', |
||||
|
dataIndex: 'dateMainten', |
||||
|
ellipsis: true, |
||||
|
}, |
||||
|
{ |
||||
|
title: '设备投入使用时长', |
||||
|
dataIndex: 'length', |
||||
|
ellipsis: true, |
||||
|
render: (text, record) => { |
||||
|
const start = moment(record?.dateInstall); |
||||
|
const end = moment(); |
||||
|
const days = end.diff(start, 'days'); |
||||
|
|
||||
|
return days + '天' |
||||
|
} |
||||
|
|
||||
|
}, |
||||
|
{ |
||||
|
title: '操作', |
||||
|
width: 160, |
||||
|
key: 'option', |
||||
|
valueType: 'option', |
||||
|
render: (text, record) => { |
||||
|
const options = []; |
||||
|
options.push(<DeviceModal |
||||
|
triggerRender={<a>编辑</a>} |
||||
|
editData={record} |
||||
|
title="编辑设备" |
||||
|
onFinish={onFinish} |
||||
|
key="editModel" |
||||
|
/>) |
||||
|
|
||||
|
options.push( |
||||
|
<Popconfirm |
||||
|
key="del" |
||||
|
placement="top" |
||||
|
title="是否确认删除该设备?" |
||||
|
onConfirm={() => handleDelete(record.id)} |
||||
|
okText="是" |
||||
|
cancelText="否" |
||||
|
> |
||||
|
<a>删除</a> |
||||
|
</Popconfirm>) |
||||
|
|
||||
|
return options; |
||||
|
|
||||
|
}, |
||||
|
}, |
||||
|
]; |
||||
|
|
||||
|
return <div id='patrol-record' className='global-main'> |
||||
|
<Spin spinning={loading}> |
||||
|
<div style={{ marginBottom: 19 }}> |
||||
|
<div className='top' style={{ marginBottom: 19 }}> |
||||
|
<div className='title'> |
||||
|
<span className='line'></span> |
||||
|
<span className='cn'>设备管理</span> |
||||
|
<span className='en'> DEVICE</span> |
||||
|
</div> |
||||
|
<div> |
||||
|
<DeviceModal |
||||
|
triggerRender={<Button type='primary'>新建</Button>} |
||||
|
title="新建设备" |
||||
|
onFinish={onFinish} |
||||
|
key="addModel" |
||||
|
/> |
||||
|
<Button type="primary" style={{ marginRight: 10, marginLeft: 10 }} onClick={() => { setShowImportModal(true) }}>批量新增</Button> |
||||
|
<Popconfirm title="确认删除?" onConfirm={() => { |
||||
|
rowSelected?.length > 0 ? handleDelete(rowSelected?.toString()) : message.warning('请先选择要删除的设备') |
||||
|
}}> |
||||
|
<Button>批量删除</Button> |
||||
|
</Popconfirm> |
||||
|
|
||||
|
<Input onChange={e => setName(e?.target?.value)} style={{ width: '13vw', marginLeft: 20, marginRight: 10 }} /> |
||||
|
<Button type="primary" onClick={() => { |
||||
|
setPageSize(10) |
||||
|
setCurrentPage(1) |
||||
|
queryData(true) |
||||
|
}}>查询</Button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<ProTable |
||||
|
columns={columns} |
||||
|
rowKey="id" |
||||
|
|
||||
|
dateFormatter="string" |
||||
|
scroll={ |
||||
|
{ |
||||
|
scrollToFirstRowOnChange: true, |
||||
|
y: clientHeight - 260 |
||||
|
} |
||||
|
} |
||||
|
pagination={{ |
||||
|
size: 'large', |
||||
|
total: devices?.count, |
||||
|
showSizeChanger: true, |
||||
|
// showQuickJumper: true,
|
||||
|
current: currentPage, |
||||
|
pageSize: pageSize || 10, |
||||
|
pageSizeOptions: [10, 20, 50], |
||||
|
showTotal: (total) => { |
||||
|
return <span style={{ fontSize: 15 }}>{`共${Math.ceil(total / pageSize)}页,${total}项`}</span> |
||||
|
}, |
||||
|
onShowSizeChange: (currentPage, pageSize) => { |
||||
|
setCurrentPage(currentPage); |
||||
|
setPageSize(pageSize); |
||||
|
}, |
||||
|
onChange: (page, pageSize) => { |
||||
|
setCurrentPage(page); |
||||
|
setPageSize(pageSize); |
||||
|
} |
||||
|
}} |
||||
|
dataSource={devices?.rows || []} |
||||
|
rowSelection={{ |
||||
|
selectedRowKeys: rowSelected, |
||||
|
onChange: (selectedRowKeys) => { |
||||
|
setRowSelected(selectedRowKeys); |
||||
|
}, |
||||
|
getCheckboxProps: (record) => { |
||||
|
return { |
||||
|
disabled: record.username === 'SuperAdmin', |
||||
|
} |
||||
|
} |
||||
|
}} |
||||
|
options={false} |
||||
|
search={false} |
||||
|
/> |
||||
|
{showImportModal && <ImportDeviceModal |
||||
|
devices={devices?.rows || []} |
||||
|
onCancel={() => { |
||||
|
setShowImportModal(false) |
||||
|
}} |
||||
|
onOk={() => { |
||||
|
setShowImportModal(false) |
||||
|
queryData() |
||||
|
}} |
||||
|
/>} |
||||
|
</Spin> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
} |
||||
|
|
||||
|
function mapStateToProps(state) { |
||||
|
const { |
||||
|
auth, global, device |
||||
|
} = state; |
||||
|
return { |
||||
|
loading: device.isRequesting, |
||||
|
clientHeight: global.clientHeight, |
||||
|
actions: global.actions, |
||||
|
devices: device?.data || {} |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
export default connect(mapStateToProps)(DeviceManagement); |
||||
|
|
||||
|
|
@ -0,0 +1,5 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
import DeviceManage from './deviceManage' |
||||
|
|
||||
|
export { DeviceManage }; |
@ -0,0 +1,15 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
import reducers from './reducers'; |
||||
|
import routes from './routes'; |
||||
|
import actions from './actions'; |
||||
|
import { getNavItem } from './nav-item'; |
||||
|
|
||||
|
export default { |
||||
|
key: 'deviceManage', |
||||
|
name: '设备管理', |
||||
|
reducers: reducers, |
||||
|
routes: routes, |
||||
|
actions: actions, |
||||
|
getNavItem: getNavItem |
||||
|
}; |
@ -0,0 +1,13 @@ |
|||||
|
import React from 'react'; |
||||
|
import { Link } from 'react-router-dom'; |
||||
|
import { Menu } from 'antd'; |
||||
|
import { Func } from '$utils'; |
||||
|
export function getNavItem(user, dispatch) { |
||||
|
return ( |
||||
|
<Menu.Item icon={<img src='/assets/images/menu/device.png' style={{ width: 24, height: 24 }} />} |
||||
|
key="deviceManage"> |
||||
|
<Link to="/deviceManage">设备管理</Link> |
||||
|
</Menu.Item> |
||||
|
|
||||
|
); |
||||
|
} |
@ -0,0 +1,5 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
export default { |
||||
|
|
||||
|
} |
@ -0,0 +1,13 @@ |
|||||
|
'use strict'; |
||||
|
import { DeviceManage } from './containers'; |
||||
|
|
||||
|
export default [{ |
||||
|
type: 'inner', |
||||
|
route: { |
||||
|
path: '/deviceManage', |
||||
|
key: 'deviceManage', |
||||
|
breadcrumb: '设备管理', |
||||
|
component: DeviceManage, |
||||
|
|
||||
|
} |
||||
|
}]; |
Loading…
Reference in new issue