wenlele
10 months ago
150 changed files with 5 additions and 13136 deletions
@ -1,60 +0,0 @@ |
|||||
'use strict'; |
|
||||
import { basicAction } from '@peace/utils' |
|
||||
import { ApiTable } from '$utils' |
|
||||
|
|
||||
export function getAdvisoryNotices(query) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'get', |
|
||||
dispatch: dispatch, |
|
||||
query, |
|
||||
actionType: 'GET_ADVISORY_NOTICES', |
|
||||
url: `${ApiTable.getAdvisoryNotices}`, |
|
||||
msg: { error: '获取资讯公告失败' }, |
|
||||
reducer: { name: 'advisoryNotice'} |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
export function addOrUpdateAdvisoryNotice(data) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'post', |
|
||||
dispatch: dispatch, |
|
||||
data, |
|
||||
actionType: 'ADD_OR_UPDATE_ADVISORY_NOTICE', |
|
||||
url: `${ApiTable.addOrUpdateAdvisoryNotice}`, |
|
||||
msg: { option: data?.id?'编辑资讯公告':'新增资讯公告' }, |
|
||||
}) |
|
||||
} |
|
||||
export function delAdvisoryNotice(id) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'delete', |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'DEL_ADVISORY_NOTICE', |
|
||||
url: ApiTable.delAdvisoryNotice.replace('{id}', id), |
|
||||
msg: { option: '删除资讯公告' }, |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
|
|
||||
export function updateAdvisoryNoticeState(id,data) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'post', |
|
||||
dispatch: dispatch, |
|
||||
data, |
|
||||
actionType: 'UPDATE_ADVISORY_NOTICE_STATE', |
|
||||
url: ApiTable.updateAdvisoryNoticeState.replace('{id}', id), |
|
||||
msg: { option: data?.msg?.includes('发布')?'发布资讯公告':'下架资讯公告' }, |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
export default{ |
|
||||
getAdvisoryNotices, |
|
||||
addOrUpdateAdvisoryNotice, |
|
||||
delAdvisoryNotice, |
|
||||
updateAdvisoryNoticeState |
|
||||
} |
|
@ -1,6 +0,0 @@ |
|||||
|
|
||||
'use strict'; |
|
||||
import advisoryNotice from './advisoryNotice' |
|
||||
export default { |
|
||||
...advisoryNotice |
|
||||
} |
|
@ -1,108 +0,0 @@ |
|||||
import React, { useRef, useState, useEffect } from 'react' |
|
||||
import { Button, Form } from 'antd' |
|
||||
import { connect } from 'react-redux' |
|
||||
import { InfoCircleOutlined } from '@ant-design/icons' |
|
||||
import { ModalForm, ProFormSelect, ProFormText, ProFormDatePicker, ProFormTextArea,ProForm } from '@ant-design/pro-form' |
|
||||
import moment from 'moment' |
|
||||
import Uploads from '$components/Uploads' |
|
||||
|
|
||||
function AddAdvisoryNoticeModal(props) { |
|
||||
const { |
|
||||
title, |
|
||||
triggerRender, |
|
||||
editData = null, |
|
||||
onFinish, |
|
||||
devices, |
|
||||
actions, |
|
||||
dispatch, |
|
||||
disabled, |
|
||||
} = props |
|
||||
const formItemLayout = { labelCol: { span: 6 }, wrapperCol: { span: 16 } } |
|
||||
const initialValues = editData ? { ...editData } : {} |
|
||||
const [form] = Form.useForm() |
|
||||
const formRef = useRef() |
|
||||
|
|
||||
return ( |
|
||||
<ModalForm |
|
||||
width={500} |
|
||||
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 => { |
|
||||
let value = { |
|
||||
title: values?.title, |
|
||||
content: values?.content, |
|
||||
id: initialValues ? initialValues.id : null, |
|
||||
attachments:values?.attachments?.length? |
|
||||
values?.attachments[0]?.name ? values?.attachments.map(u => u.storageUrl) : editData?.attachments:[], |
|
||||
} |
|
||||
if(disabled){ |
|
||||
return true |
|
||||
} |
|
||||
return onFinish && (await onFinish(value)) |
|
||||
// return true;
|
|
||||
}}> |
|
||||
<ProFormText |
|
||||
rules={[{ required: true, message: '资讯标题' }]} |
|
||||
placeholder='请输入资讯标题' |
|
||||
name='title' |
|
||||
label='资讯标题' |
|
||||
disabled={disabled ? true : false} |
|
||||
/> |
|
||||
<ProFormTextArea |
|
||||
rules={[{ required: true, message: '咨讯内容' }]} |
|
||||
placeholder='请输入咨讯内容' |
|
||||
name='content' |
|
||||
label='咨讯内容' |
|
||||
disabled={disabled ? true : false} |
|
||||
/> |
|
||||
<div className='ant-col ant-col-xs-24'> |
|
||||
<Form.Item |
|
||||
label='文件:' |
|
||||
name='attachments' |
|
||||
// rules={[{ required: true, message: '请添加附件!' }]}
|
|
||||
disabled={disabled ? true : false}> |
|
||||
<Uploads |
|
||||
disabled={disabled ? true : false} |
|
||||
listType='picture-card' |
|
||||
uploadType='project' |
|
||||
maxFilesNum={10} |
|
||||
maxFileSize={10} |
|
||||
isQiniu={true} |
|
||||
// disabled={true}
|
|
||||
fileTypes={['png', 'jpg']} |
|
||||
defaultValue={(() => { |
|
||||
let nextV = [] |
|
||||
for (let s of editData?.attachments || []) { |
|
||||
if (s) { |
|
||||
nextV.push({ |
|
||||
storageUrl: s, |
|
||||
}) |
|
||||
} |
|
||||
} |
|
||||
return nextV |
|
||||
})()} |
|
||||
/> |
|
||||
</Form.Item> |
|
||||
</div> |
|
||||
</ModalForm> |
|
||||
) |
|
||||
} |
|
||||
function mapStateToProps(state) { |
|
||||
const { auth, global, device } = state |
|
||||
return { |
|
||||
loading: device.isRequesting, |
|
||||
clientHeight: global.clientHeight, |
|
||||
actions: global.actions, |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
export default connect(mapStateToProps)(AddAdvisoryNoticeModal) |
|
@ -1,216 +0,0 @@ |
|||||
import React, { useEffect, useState, useRef, useMemo } from 'react' |
|
||||
import { Spin, Popconfirm, message, Button, Input, Select } from 'antd' |
|
||||
import { connect } from 'react-redux' |
|
||||
import ProTable from '@ant-design/pro-table' |
|
||||
import moment from 'moment' |
|
||||
import AddAdvisoryNoticeModal from '../components/addAdvisoryNoticeModal' |
|
||||
function AdvisorNotice(props) { |
|
||||
const { loading, clientHeight, actions, dispatch } = props |
|
||||
const { advisorNotice } = actions |
|
||||
const tableRef = useRef() |
|
||||
const proTableFormRef = useRef() |
|
||||
const [tableParams, setTableParams] = useState({}) |
|
||||
const [dataSource, setDataSource] = useState([]) |
|
||||
|
|
||||
const queryData = () => { |
|
||||
dispatch(advisorNotice.getAdvisoryNotices()).then(res => { |
|
||||
if (res.success) { |
|
||||
const list = res?.payload?.data?.rows |
|
||||
setDataSource(list) |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
//初始化
|
|
||||
useEffect(() => { |
|
||||
queryData() |
|
||||
}, []) |
|
||||
|
|
||||
//新增或编辑
|
|
||||
const onFinish = async values => { |
|
||||
const dataToSave = { title: values?.title, content: values?.content,attachments:values?.attachments,id: values?.id } |
|
||||
return dispatch(advisorNotice.addOrUpdateAdvisoryNotice(dataToSave)).then(res => { |
|
||||
if (res.success) { |
|
||||
queryData() |
|
||||
// tableRef.current.reload()
|
|
||||
return true |
|
||||
} else { |
|
||||
return false |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
//删除
|
|
||||
const handleDelete = id => { |
|
||||
dispatch(advisorNotice.delAdvisoryNotice(id)).then(res => { |
|
||||
if (res.success) { |
|
||||
queryData() |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
//查询公告(搜索按钮)
|
|
||||
const tableDatas = useMemo(() => { |
|
||||
const { title } = tableParams |
|
||||
let rslt = dataSource |
|
||||
rslt = rslt.filter(s => (title ? (s.title ? s.title.includes(title) : false) : true)) |
|
||||
return rslt |
|
||||
}) |
|
||||
//上架下架处理
|
|
||||
const publishHandler=(record)=>{ |
|
||||
const msg=record.state===2?'下架':'发布' |
|
||||
const publishTime=record.state===2?moment(record.publishTime).format('YYYY-MM-DD HH:mm:ss'):null |
|
||||
dispatch(advisorNotice.updateAdvisoryNoticeState(record.id,{msg,publishTime})).then(res => { |
|
||||
if (res.success) { |
|
||||
queryData() |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
const columns = [ |
|
||||
{ |
|
||||
title: '序号', |
|
||||
dataIndex: 'id', |
|
||||
width: '12%', |
|
||||
render: (text, record, index) => { |
|
||||
return index + 1 |
|
||||
}, |
|
||||
search: false, |
|
||||
|
|
||||
}, |
|
||||
{ |
|
||||
title: '公告标题', |
|
||||
dataIndex: 'title', |
|
||||
ellipsis: true, |
|
||||
}, |
|
||||
{ |
|
||||
title: '发布时间', |
|
||||
dataIndex: 'publishTime', |
|
||||
ellipsis: true, |
|
||||
search: false, |
|
||||
render: (text, record, index) => { |
|
||||
return record?.publishTime?moment(record?.publishTime).format('YYYY-MM-DD HH:mm:ss'):'--' |
|
||||
}, |
|
||||
}, |
|
||||
{ |
|
||||
title: '当前状态', |
|
||||
dataIndex: 'state', |
|
||||
ellipsis: true, |
|
||||
search: false, |
|
||||
render: (text, record, index) => { |
|
||||
return record?.state===1?'草稿':record?.state===2?'已发布':'已下架' |
|
||||
}, |
|
||||
}, |
|
||||
{ |
|
||||
title: '操作', |
|
||||
width: 300, |
|
||||
key: 'option', |
|
||||
valueType: 'option', |
|
||||
render: (text, record) => { |
|
||||
const options = [] |
|
||||
options.push( |
|
||||
<AddAdvisoryNoticeModal |
|
||||
triggerRender={<a>查看详情</a>} |
|
||||
editData={record} |
|
||||
disabled={true} |
|
||||
title='查看详情' |
|
||||
onFinish={onFinish} |
|
||||
key='lookModel' |
|
||||
/> |
|
||||
) |
|
||||
options.push( |
|
||||
<Popconfirm |
|
||||
key='del' |
|
||||
placement='top' |
|
||||
title={record?.state===2?'确定下架吗?':'确定发布吗?'} |
|
||||
onConfirm={() => publishHandler(record)} |
|
||||
okText='是' |
|
||||
cancelText='否'> |
|
||||
<a>{record?.state===2?'下架':'发布'}</a> |
|
||||
</Popconfirm> |
|
||||
) |
|
||||
record.state ===1||record.state ===3? options.push( |
|
||||
<AddAdvisoryNoticeModal |
|
||||
triggerRender={<a>编辑</a>} |
|
||||
editData={record} |
|
||||
title='编辑资讯' |
|
||||
onFinish={onFinish} |
|
||||
key='editModel' |
|
||||
/> |
|
||||
):'' |
|
||||
|
|
||||
record.state ===1||record.state ===3?options.push( |
|
||||
<Popconfirm |
|
||||
key='del' |
|
||||
placement='top' |
|
||||
title='是否确认删除资讯?' |
|
||||
onConfirm={() => handleDelete(record.id)} |
|
||||
okText='是' |
|
||||
cancelText='否'> |
|
||||
<a style={{color:'red'}}>删除</a> |
|
||||
</Popconfirm> |
|
||||
):'' |
|
||||
|
|
||||
return options |
|
||||
}, |
|
||||
}, |
|
||||
] |
|
||||
|
|
||||
return ( |
|
||||
<Spin spinning={loading}> |
|
||||
<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'> ADVISORYNOTICE</span> |
|
||||
</div> |
|
||||
<div></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<AddAdvisoryNoticeModal |
|
||||
triggerRender={<Button type='primary'>新增</Button>} |
|
||||
title='新增资讯' |
|
||||
onFinish={onFinish} |
|
||||
key='addModel' |
|
||||
/> |
|
||||
<ProTable |
|
||||
formRef={proTableFormRef} |
|
||||
rowKey='id' |
|
||||
options={false} |
|
||||
request={async params => { |
|
||||
setTableParams(params) |
|
||||
return { |
|
||||
data: [], |
|
||||
success: true, |
|
||||
} |
|
||||
}} |
|
||||
actionRef={tableRef} |
|
||||
columns={columns} |
|
||||
pagination={{ pageSize: 10, size: 'default', className: 'global-pagination' }} |
|
||||
dataSource={tableDatas || []} |
|
||||
// search={{
|
|
||||
// labelWidth: 100,
|
|
||||
// }}
|
|
||||
// search={{
|
|
||||
// optionRender: ({searchText, resetText}, {form}, dom) => [
|
|
||||
// <Button type="primary" onClick={searchHandler}>查询</Button>,
|
|
||||
// ]
|
|
||||
// }}
|
|
||||
></ProTable> |
|
||||
{/* </Spin> */} |
|
||||
</div> |
|
||||
</Spin> |
|
||||
) |
|
||||
} |
|
||||
|
|
||||
function mapStateToProps(state) { |
|
||||
const { auth, global, advisoryNotice } = state |
|
||||
return { |
|
||||
loading: advisoryNotice.isRequesting, |
|
||||
clientHeight: global.clientHeight, |
|
||||
actions: global.actions, |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
export default connect(mapStateToProps)(AdvisorNotice) |
|
@ -1,5 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
import AdvisoryNotice from './advisoryNotice' |
|
||||
|
|
||||
export { AdvisoryNotice } |
|
@ -1,15 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
import reducers from './reducers'; |
|
||||
import routes from './routes'; |
|
||||
import actions from './actions'; |
|
||||
import { getNavItem } from './nav-item'; |
|
||||
|
|
||||
export default { |
|
||||
key: 'advisorNotice', |
|
||||
name: '资讯广告', |
|
||||
reducers: reducers, |
|
||||
routes: routes, |
|
||||
actions: actions, |
|
||||
getNavItem: getNavItem |
|
||||
}; |
|
@ -1,14 +0,0 @@ |
|||||
import React from 'react'; |
|
||||
import { Link } from 'react-router-dom'; |
|
||||
import { Menu } from 'antd'; |
|
||||
import { HomeOutlined } from '@ant-design/icons'; |
|
||||
import { Func } from '$utils'; |
|
||||
const SubMenu = Menu.SubMenu; |
|
||||
|
|
||||
export function getNavItem (user, dispatch) { |
|
||||
|
|
||||
return <Menu.Item key="advisoryNotice" icon={<img src='/assets/images/menu/home.svg' style={{ width: 24, height: 24 }} />}> |
|
||||
<Link to="/advisoryNotice">咨讯公告</Link> |
|
||||
</Menu.Item> |
|
||||
|
|
||||
} |
|
@ -1,5 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
export default { |
|
||||
|
|
||||
} |
|
@ -1,12 +0,0 @@ |
|||||
'use strict'; |
|
||||
import { AdvisoryNotice } from './containers'; |
|
||||
|
|
||||
export default [{ |
|
||||
type: 'inner', |
|
||||
route: { |
|
||||
path: '/advisoryNotice', |
|
||||
key: 'advisoryNotice', |
|
||||
breadcrumb: '咨询公告', |
|
||||
component: AdvisoryNotice, |
|
||||
} |
|
||||
}]; |
|
@ -1,8 +1,7 @@ |
|||||
'use strict'; |
'use strict'; |
||||
|
|
||||
import * as device from './device' |
import * as device from './device' |
||||
import * as network from './network' |
|
||||
|
|
||||
export default { |
export default { |
||||
...device,...network |
...device, |
||||
} |
} |
@ -1,50 +0,0 @@ |
|||||
'use strict'; |
|
||||
import { basicAction } from '@peace/utils' |
|
||||
import { ApiTable } from '$utils' |
|
||||
|
|
||||
export function getNetworks(query) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'get', |
|
||||
dispatch: dispatch, |
|
||||
query, |
|
||||
actionType: 'GET_NETWORKS', |
|
||||
url: `${ApiTable.getNetworks}`, |
|
||||
msg: { error: '获取宽带专网失败' }, |
|
||||
reducer: { name: 'networks'} |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
export function addOrUpdateNetwork(data) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'post', |
|
||||
dispatch: dispatch, |
|
||||
data, |
|
||||
actionType: 'ADD_OR_UPDATE_NETWORK', |
|
||||
url: `${ApiTable.addOrUpdateNetwork}`, |
|
||||
msg: { option: data?.id?'编辑宽带专网':'新增宽带专网' }, |
|
||||
}) |
|
||||
} |
|
||||
export function delNetwork(id) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'delete', |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'DEL_NETWORK', |
|
||||
url: ApiTable.delNetwork.replace('{id}', id), |
|
||||
msg: { option: '删除宽带专网' }, |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
export default{ |
|
||||
getNetworks, |
|
||||
addOrUpdateNetwork, |
|
||||
delNetwork, |
|
||||
} |
|
@ -1,103 +0,0 @@ |
|||||
import React, { useRef, useState, useEffect } from 'react' |
|
||||
import { Button, Form } from 'antd' |
|
||||
import { connect } from 'react-redux' |
|
||||
import { InfoCircleOutlined } from '@ant-design/icons' |
|
||||
import { ModalForm, ProFormSelect, ProFormText, ProFormDatePicker, ProFormTextArea,ProForm, ProFormTimePicker } from '@ant-design/pro-form' |
|
||||
import moment from 'moment' |
|
||||
|
|
||||
function addNetworkModal(props) { |
|
||||
const { |
|
||||
title, |
|
||||
structureListOpt, |
|
||||
triggerRender, |
|
||||
editData = null, |
|
||||
onFinish, |
|
||||
devices, |
|
||||
actions, |
|
||||
dispatch, |
|
||||
type |
|
||||
} = props |
|
||||
const formItemLayout = { labelCol: { span: 6 }, wrapperCol: { span: 16 } } |
|
||||
const initialValues = editData ? { ...editData } : {} |
|
||||
const [form] = Form.useForm() |
|
||||
const formRef = useRef() |
|
||||
|
|
||||
return ( |
|
||||
<ModalForm |
|
||||
width={500} |
|
||||
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 => { |
|
||||
console.log('x111',values) |
|
||||
let value = { |
|
||||
name: values?.name, |
|
||||
type:values?.type, |
|
||||
account:values?.account, |
|
||||
indate: values?.indate, |
|
||||
id: initialValues ? initialValues.id : null, |
|
||||
projectId:values?.projectId |
|
||||
} |
|
||||
|
|
||||
return onFinish && (await onFinish(value)) |
|
||||
// return true;
|
|
||||
}}> |
|
||||
<ProFormText |
|
||||
rules={[{ required: true, message: '请输入专网名称' }]} |
|
||||
placeholder='请输入专网名称' |
|
||||
name='name' |
|
||||
label='专网名称' |
|
||||
/> |
|
||||
<ProFormSelect |
|
||||
rules={[{ required: true, message: '请选择专网类型' }]} |
|
||||
placeholder='请选择专网类型' |
|
||||
options={type?.map(s => { |
|
||||
return { label: s.label, value: s.id } |
|
||||
})} |
|
||||
name='type' |
|
||||
label='专网类型' |
|
||||
/> |
|
||||
<ProFormText |
|
||||
rules={[{ required: true, message: '请输入账号' }]} |
|
||||
placeholder='请输入账号' |
|
||||
name='account' |
|
||||
label='账号' |
|
||||
/> |
|
||||
<ProFormDatePicker |
|
||||
rules={[{ required: true, message: '请输入有效期' }]} |
|
||||
placeholder='请输入有效期' |
|
||||
name='indate' |
|
||||
label='有效期' |
|
||||
/> |
|
||||
<ProFormSelect |
|
||||
showSearch |
|
||||
allowClear |
|
||||
rules={[{ required: true, message: '请选择结构物' }]} |
|
||||
placeholder='请选择结构物' |
|
||||
options={structureListOpt?.map(s => { |
|
||||
return { label: s.label, value: s.id } |
|
||||
})} |
|
||||
name='projectId' |
|
||||
label='关联结构物' |
|
||||
/> |
|
||||
</ModalForm> |
|
||||
) |
|
||||
} |
|
||||
function mapStateToProps(state) { |
|
||||
const { auth, global } = state |
|
||||
return { |
|
||||
clientHeight: global.clientHeight, |
|
||||
actions: global.actions, |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
export default connect(mapStateToProps)(addNetworkModal) |
|
@ -1,5 +1,4 @@ |
|||||
'use strict'; |
'use strict'; |
||||
|
|
||||
import DeviceManage from './deviceManage' |
import DeviceManage from './deviceManage' |
||||
import Network from './network' |
export { DeviceManage}; |
||||
export { DeviceManage,Network}; |
|
||||
|
@ -1,213 +0,0 @@ |
|||||
import React, { useEffect, useState, useRef, useMemo } from 'react' |
|
||||
import { Spin, Popconfirm, message, Button, Input, Select } from 'antd' |
|
||||
import { connect } from 'react-redux' |
|
||||
import ProTable from '@ant-design/pro-table' |
|
||||
import moment from 'moment' |
|
||||
import AddNetworkModal from '../components/addNetworkModal'; |
|
||||
|
|
||||
|
|
||||
|
|
||||
const type=[{id:1,label:'外网'},{id:2,label:'内网'}] |
|
||||
function Network(props) { |
|
||||
const { loading, clientHeight, actions, dispatch, } = props |
|
||||
const { deviceManage,projectRegime} = actions |
|
||||
const tableRef = useRef() |
|
||||
const proTableFormRef = useRef() |
|
||||
const [tableParams, setTableParams] = useState({}) |
|
||||
const [dataSource, setDataSource] = useState([]) |
|
||||
const [structureListOpt, setStructureListOpt] = useState([])//巡检结构物
|
|
||||
const queryData = () => { |
|
||||
dispatch(deviceManage.getNetworks()).then(res => { |
|
||||
if (res.success) { |
|
||||
const list = res?.payload?.data?.rows |
|
||||
setDataSource(list) |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
//初始化
|
|
||||
useEffect(() => { |
|
||||
dispatch(projectRegime.getProjectList()).then(res => { |
|
||||
if (res.success) { |
|
||||
const dp = res.payload.data?.rows?.filter(i=>i.type==='管廊')?.map(item => { |
|
||||
return { |
|
||||
label: item?.name, |
|
||||
id: item?.id, |
|
||||
} |
|
||||
}) |
|
||||
setStructureListOpt(dp) |
|
||||
} |
|
||||
}) |
|
||||
queryData() |
|
||||
}, []) |
|
||||
|
|
||||
//新增或编辑
|
|
||||
const onFinish = async values => { |
|
||||
const dataToSave = { |
|
||||
name: values?.name, |
|
||||
type:values?.type, |
|
||||
account:values?.account, |
|
||||
indate: values?.indate, |
|
||||
id: values.id , |
|
||||
projectId:values?.projectId |
|
||||
} |
|
||||
return dispatch(deviceManage.addOrUpdateNetwork(dataToSave)).then(res => { |
|
||||
if (res.success) { |
|
||||
queryData() |
|
||||
// tableRef.current.reload()
|
|
||||
return true |
|
||||
} else { |
|
||||
return false |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
//删除
|
|
||||
const handleDelete = id => { |
|
||||
dispatch(deviceManage.delNetwork(id)).then(res => { |
|
||||
if (res.success) { |
|
||||
queryData() |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
//查询宽带名字(搜索按钮)
|
|
||||
const tableDatas = useMemo(() => { |
|
||||
const { name } = tableParams |
|
||||
let rslt = dataSource |
|
||||
rslt = rslt.filter(s => (name ? (s.name ? s.name.includes(name) : false) : true)) |
|
||||
return rslt |
|
||||
}) |
|
||||
|
|
||||
|
|
||||
const columns = [ |
|
||||
{ |
|
||||
title: '专网名称', |
|
||||
dataIndex: 'name', |
|
||||
ellipsis: true, |
|
||||
}, |
|
||||
{ |
|
||||
title: '专网类型', |
|
||||
dataIndex: 'type', |
|
||||
ellipsis: true, |
|
||||
search: false, |
|
||||
valueEnum: type.reduce((enumObj, { id, label }) => { |
|
||||
enumObj[id] = { text: label }; |
|
||||
return enumObj; |
|
||||
}, {}), |
|
||||
|
|
||||
}, |
|
||||
{ |
|
||||
title: '账号', |
|
||||
dataIndex: 'account', |
|
||||
ellipsis: true, |
|
||||
search: false, |
|
||||
}, |
|
||||
{ |
|
||||
title: '有效期', |
|
||||
dataIndex: 'indate', |
|
||||
ellipsis: true, |
|
||||
search: false, |
|
||||
render: (text, record, index) => { |
|
||||
return record?.indate?moment(record?.indate).format('YYYY-MM-DD'):'--' |
|
||||
}, |
|
||||
}, |
|
||||
{ |
|
||||
title: '关联结构物', |
|
||||
dataIndex: 'projectId', |
|
||||
ellipsis: true, |
|
||||
search: false, |
|
||||
valueEnum: structureListOpt.reduce((enumObj, { id, label }) => { |
|
||||
enumObj[id] = { text: label }; |
|
||||
return enumObj; |
|
||||
}, {}), |
|
||||
}, |
|
||||
{ |
|
||||
title: '操作', |
|
||||
width: 300, |
|
||||
key: 'option', |
|
||||
valueType: 'option', |
|
||||
render: (text, record) => { |
|
||||
const options = [] |
|
||||
options |
|
||||
.push( <AddNetworkModal |
|
||||
type={type} |
|
||||
structureListOpt={structureListOpt} |
|
||||
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 style={{ color: 'red' }}>删除</a> |
|
||||
</Popconfirm> |
|
||||
) |
|
||||
|
|
||||
return options |
|
||||
}, |
|
||||
}, |
|
||||
] |
|
||||
|
|
||||
return ( |
|
||||
<Spin spinning={loading}> |
|
||||
<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'> NETWORK</span> |
|
||||
</div> |
|
||||
<div></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<AddNetworkModal |
|
||||
type={type} |
|
||||
structureListOpt={structureListOpt} |
|
||||
triggerRender={<Button type='primary'>新增</Button>} |
|
||||
title='新增宽带宽带' |
|
||||
onFinish={onFinish} |
|
||||
key='addModel' |
|
||||
/> |
|
||||
<ProTable |
|
||||
formRef={proTableFormRef} |
|
||||
rowKey='id' |
|
||||
options={false} |
|
||||
request={async params => { |
|
||||
setTableParams(params) |
|
||||
return { |
|
||||
data: [], |
|
||||
success: true, |
|
||||
} |
|
||||
}} |
|
||||
actionRef={tableRef} |
|
||||
columns={columns} |
|
||||
pagination={{ pageSize: 10, size: 'default', className: 'global-pagination' }} |
|
||||
dataSource={tableDatas || []} |
|
||||
></ProTable> |
|
||||
{/* </Spin> */} |
|
||||
</div> |
|
||||
</Spin> |
|
||||
) |
|
||||
} |
|
||||
|
|
||||
function mapStateToProps(state) { |
|
||||
const { auth, global, networks } = state |
|
||||
return { |
|
||||
loading: networks.isRequesting, |
|
||||
clientHeight: global.clientHeight, |
|
||||
actions: global.actions, |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
export default connect(mapStateToProps)(Network) |
|
@ -1,11 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
|
|
||||
import * as record from './record' |
|
||||
|
|
||||
|
|
||||
export default { |
|
||||
|
|
||||
...record, |
|
||||
|
|
||||
} |
|
@ -1,32 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
import { basicAction } from '@peace/utils' |
|
||||
import { ApiTable } from '$utils' |
|
||||
|
|
||||
|
|
||||
export function addPatrolRecordIssueHandle(params) { |
|
||||
return (dispatch) => basicAction({ |
|
||||
type: 'post', |
|
||||
data: params, |
|
||||
dispatch, |
|
||||
actionType: 'ADD_PatrolRecordIssueHandle_REPORT', |
|
||||
url: ApiTable.addPatrolRecordIssueHandle, |
|
||||
msg: { |
|
||||
option: '维修计划新增', |
|
||||
}, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function modifyPatrolRecordIssueHandle(id, params, msg) { |
|
||||
return (dispatch) => basicAction({ |
|
||||
type: 'put', |
|
||||
data: params, |
|
||||
dispatch, |
|
||||
actionType: 'MODIFY_PatrolRecordIssueHandle_REPORT', |
|
||||
url: ApiTable.modifyPatrolRecordIssueHandle.replace('{id}', id), |
|
||||
msg: { |
|
||||
option: msg || '维修计划审批', |
|
||||
}, |
|
||||
}); |
|
||||
} |
|
||||
|
|
@ -1,429 +0,0 @@ |
|||||
import React, { useState, useRef } from 'react'; |
|
||||
import { Button, Form, Row, Col, Table, Popconfirm, Input, message } from 'antd'; |
|
||||
import { |
|
||||
ModalForm, |
|
||||
ProFormText, |
|
||||
ProFormSelect, |
|
||||
ProFormTextArea, |
|
||||
ProFormDatePicker, |
|
||||
ProFormDateRangePicker, |
|
||||
ProFormDependency |
|
||||
} from '@ant-design/pro-form'; |
|
||||
import Uploads from '$components/Uploads'; |
|
||||
import moment from 'moment'; |
|
||||
const FormItem = Form.Item; |
|
||||
//state: 1下发未上报 2已上报待审批 3整改完成 上报结果result: status 0 已上报未审批 1 审批通过 2 审批驳回
|
|
||||
export default (props) => { |
|
||||
const { title, triggerRender, editData = null, onFinish, readOnly, structsUsers, user } = props; |
|
||||
const users = structsUsers?.find(s => s.id == editData?.points?.project?.id)?.users?.map(v => { return { value: v.id, label: v.name, ...v } }) |
|
||||
const formItemLayout = { labelCol: { span: 7 }, wrapperCol: { span: 16 } }; |
|
||||
const formRef = useRef(); |
|
||||
|
|
||||
const initialValues = editData ? { |
|
||||
...editData, |
|
||||
...editData?.patrolRecordIssueHandles[0], |
|
||||
approvePerson: editData?.patrolRecordIssueHandles[0]?.approvePerson?.name || '', |
|
||||
approveDate: editData?.patrolRecordIssueHandles[0]?.approveDate ? moment(editData?.patrolRecordIssueHandles[0]?.approveDate).format('YYYY-MM-DD HH:mm:ss') : "", |
|
||||
repairPerson: users?.find(s => s.value == editData?.patrolRecordIssueHandles[0]?.repairPerson?.id) ? editData?.patrolRecordIssueHandles[0]?.repairPerson?.id : null, |
|
||||
checkPerson: users?.find(s => s.value == editData?.patrolRecordIssueHandles[0]?.checkPerson?.id) ? editData?.patrolRecordIssueHandles[0]?.checkPerson?.id : null, |
|
||||
} : {}; |
|
||||
if (editData?.patrolRecordIssueHandles?.length > 0) { |
|
||||
initialValues.dateRange = [editData?.patrolRecordIssueHandles[0]?.startTime, editData?.patrolRecordIssueHandles[0]?.endTime] |
|
||||
} |
|
||||
const [approve, setApprove] = useState('') |
|
||||
|
|
||||
const approveHandle = async (values) => { |
|
||||
onFinish && await onFinish({ |
|
||||
msg: approve ? '计划同意' : '计划驳回', |
|
||||
state: approve ? 4 : 3, |
|
||||
approveOpinion: values?.approveOpinion, |
|
||||
approvePerson: user, |
|
||||
approveDate: moment() |
|
||||
}, editData) |
|
||||
} |
|
||||
|
|
||||
const renderPlanInfo = () => { |
|
||||
return <> |
|
||||
{/* <Card title={'巡检信息'}> */} |
|
||||
<div className="item-title">{"巡检信息"}</div> |
|
||||
<Form> |
|
||||
<Row> |
|
||||
<Col span={12}> |
|
||||
<Form.Item label="结构物名称:" {...formItemLayout}> |
|
||||
<Input value={editData?.points?.project?.name} readOnly /> |
|
||||
</Form.Item> |
|
||||
<Form.Item label="巡检人:" {...formItemLayout}> |
|
||||
<Input value={editData?.points?.user?.name} readOnly /> |
|
||||
</Form.Item> |
|
||||
</Col> |
|
||||
<Col span={12}> |
|
||||
<Form.Item label="巡检单位:" {...formItemLayout}> |
|
||||
<Input value={editData?.points?.user?.department?.name} readOnly title={222} /> |
|
||||
</Form.Item> |
|
||||
|
|
||||
<Form.Item label="巡检时间:" {...formItemLayout}> |
|
||||
<Input value={editData?.inspectionTime && moment(editData?.inspectionTime).format('YYYY-MM-DD HH:mm:ss')} readOnly /> |
|
||||
</Form.Item> |
|
||||
</Col> |
|
||||
</Row> |
|
||||
</Form> |
|
||||
|
|
||||
<div className="item-title">{"问题详情"}</div> |
|
||||
<Row> |
|
||||
<Col span={12}> |
|
||||
<Form.Item label="点位名称:" {...formItemLayout}> |
|
||||
<Input value={editData?.points?.itemData?.name} readOnly /> |
|
||||
</Form.Item> |
|
||||
</Col> |
|
||||
</Row> |
|
||||
<Row> |
|
||||
<Col span={24}> |
|
||||
{ |
|
||||
editData?.points?.inspectContent && Array.isArray(editData?.points?.inspectContent) && |
|
||||
editData?.points?.inspectContent?.map(s => { |
|
||||
if (s?.alarm == true) { |
|
||||
return <> |
|
||||
{s?.deviceName && <Col span={12}> |
|
||||
<Form.Item label="设备名称:" {...formItemLayout}> |
|
||||
<Input value={s?.deviceName} readOnly /> |
|
||||
</Form.Item> |
|
||||
</Col>} |
|
||||
{ |
|
||||
s?.checkItems?.map(k => { |
|
||||
return <Row style={{ marginBottom: 15 }}> |
|
||||
<Col span={12}> |
|
||||
<Form.Item label="检查项:" {...formItemLayout}> |
|
||||
<Input value={k.name} readOnly /> |
|
||||
</Form.Item> |
|
||||
<Form.Item label="异常等级:" {...formItemLayout}> |
|
||||
<Input value={k?.level} readOnly /> |
|
||||
</Form.Item> |
|
||||
</Col> |
|
||||
<Col span={12}> |
|
||||
<Form.Item label="问题描述:" {...formItemLayout}> |
|
||||
<Input value={k?.msgInp} readOnly title={222} /> |
|
||||
</Form.Item> |
|
||||
|
|
||||
<Form.Item label="现场图片:" {...formItemLayout}> |
|
||||
<Uploads |
|
||||
listType='picture-card' |
|
||||
uploadType='project' |
|
||||
maxFilesNum={1} |
|
||||
maxFileSize={10} |
|
||||
isQiniu={true} |
|
||||
disabled={true} |
|
||||
fileTypes={["png", "jpg"]} |
|
||||
defaultValue={ |
|
||||
(() => { |
|
||||
let nextV = [] |
|
||||
for (let s of (k.imgs || [])) { |
|
||||
if (s) { |
|
||||
nextV.push({ |
|
||||
storageUrl: s |
|
||||
}) |
|
||||
} |
|
||||
} |
|
||||
return nextV |
|
||||
})() |
|
||||
} |
|
||||
/> |
|
||||
|
|
||||
</Form.Item> |
|
||||
</Col> |
|
||||
</Row> |
|
||||
}) |
|
||||
} |
|
||||
</> |
|
||||
|
|
||||
|
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
</Col> |
|
||||
</Row></> |
|
||||
} |
|
||||
|
|
||||
const renderRepairInfo = () => { |
|
||||
return <> |
|
||||
<div className="item-title">{"维修处理"}</div> |
|
||||
|
|
||||
<ProFormTextArea |
|
||||
name="repairDesc" |
|
||||
label="维修情况描述:" |
|
||||
disabled={true} |
|
||||
/> |
|
||||
|
|
||||
<Form.Item label="完工图片:"> |
|
||||
<Uploads |
|
||||
listType='picture-card' |
|
||||
uploadType='project' |
|
||||
maxFilesNum={1} |
|
||||
maxFileSize={10} |
|
||||
isQiniu={true} |
|
||||
disabled={true} |
|
||||
fileTypes={["png", "jpg"]} |
|
||||
defaultValue={ |
|
||||
(() => { |
|
||||
let nextV = [] |
|
||||
for (let s of (editData?.patrolRecordIssueHandles[0]?.repairImage || [])) { |
|
||||
if (s) { |
|
||||
nextV.push({ |
|
||||
storageUrl: s |
|
||||
}) |
|
||||
} |
|
||||
} |
|
||||
return nextV |
|
||||
})() |
|
||||
} |
|
||||
/> |
|
||||
|
|
||||
</Form.Item> |
|
||||
|
|
||||
</> |
|
||||
} |
|
||||
|
|
||||
const renderCheckInfo = () => { |
|
||||
return <> |
|
||||
<div className="item-title">{"质检验收"}</div> |
|
||||
|
|
||||
<ProFormTextArea |
|
||||
name="checkPerson1" |
|
||||
label="验收人:" |
|
||||
disabled={true} |
|
||||
value={editData?.patrolRecordIssueHandles[0]?.checkPerson?.name} |
|
||||
/> |
|
||||
|
|
||||
<ProFormText |
|
||||
name="checkPerson1" |
|
||||
label="成本(元):" |
|
||||
disabled={true} |
|
||||
value={editData?.patrolRecordIssueHandles[0]?.cost} |
|
||||
/> |
|
||||
|
|
||||
<Form.Item label="完工图片:"> |
|
||||
<Uploads |
|
||||
listType='picture-card' |
|
||||
uploadType='project' |
|
||||
maxFilesNum={1} |
|
||||
maxFileSize={10} |
|
||||
isQiniu={true} |
|
||||
disabled={true} |
|
||||
fileTypes={["png", "jpg"]} |
|
||||
defaultValue={ |
|
||||
(() => { |
|
||||
let nextV = [] |
|
||||
for (let s of (editData?.patrolRecordIssueHandles[0]?.checkImage || [])) { |
|
||||
if (s) { |
|
||||
nextV.push({ |
|
||||
storageUrl: s |
|
||||
}) |
|
||||
} |
|
||||
} |
|
||||
return nextV |
|
||||
})() |
|
||||
} |
|
||||
/> |
|
||||
</Form.Item> |
|
||||
|
|
||||
<ProFormTextArea |
|
||||
name="checkOpinion" |
|
||||
label="验收意见:" |
|
||||
disabled={true} |
|
||||
/> |
|
||||
|
|
||||
<ProFormTextArea |
|
||||
name="checkState" |
|
||||
label="验收结果:" |
|
||||
disabled={true} |
|
||||
value={editData?.patrolRecordIssueHandles[0]?.state == 6 ? '验收通过' : '验收不通过'} |
|
||||
/> |
|
||||
</> |
|
||||
} |
|
||||
return ( |
|
||||
<ModalForm |
|
||||
formRef={formRef} |
|
||||
title={title || ''} |
|
||||
initialValues={initialValues} |
|
||||
trigger={ |
|
||||
triggerRender ? triggerRender : <Button type="primary" > |
|
||||
{title || ''} |
|
||||
</Button> |
|
||||
} |
|
||||
width={1300} |
|
||||
layout="horizontal" |
|
||||
// grid={true}
|
|
||||
{...formItemLayout} |
|
||||
modalProps={{ |
|
||||
destroyOnClose: true, |
|
||||
// onCancel: () => { },
|
|
||||
bodyStyle: { height: 620, overflowY: 'auto' } |
|
||||
}} |
|
||||
onFinish={async (values) => { |
|
||||
if (editData?.patrolRecordIssueHandles[0]?.state === 2 && title == '审核') { |
|
||||
approveHandle(values) |
|
||||
return true; |
|
||||
} else { |
|
||||
values.repairUnit = values?.repairUnits; |
|
||||
values.startTime = values?.dateRange[0]; |
|
||||
values.endTime = values?.dateRange[1]; |
|
||||
values.repairPerson = { id: users?.find(s => s.value == values.repairPerson)?.value, name: users?.find(s => s.id == values.repairPerson)?.label } |
|
||||
values.checkPerson = { id: users?.find(s => s.value == values.checkPerson)?.value, name: users?.find(s => s.id == values.checkPerson)?.label } |
|
||||
onFinish && await onFinish(values, editData) |
|
||||
//message.success('提交成功');
|
|
||||
return true; |
|
||||
} |
|
||||
}} |
|
||||
|
|
||||
submitter={editData?.patrolRecordIssueHandles[0]?.state === 2 && title != '修改计划' && title != '查看详情' ? { |
|
||||
render: (props, defaultDoms) => { |
|
||||
return [ |
|
||||
<Button onClick={() => { |
|
||||
setApprove(1) |
|
||||
props.submit(); |
|
||||
}} type='primary'>确定</Button>, |
|
||||
<Button onClick={() => { |
|
||||
setApprove(0) |
|
||||
props.submit(); |
|
||||
}}>驳回</Button> |
|
||||
]; |
|
||||
} |
|
||||
} : (!readOnly)} |
|
||||
> |
|
||||
<div> |
|
||||
{/*问题记录信息*/} |
|
||||
{renderPlanInfo()} |
|
||||
|
|
||||
{/*问题处理计划表单*/} |
|
||||
{ |
|
||||
((editData?.patrolRecordIssueHandles[0]?.state == 1 && title != '查看详情') || editData?.patrolRecordIssueHandles[0]?.state > 1) && |
|
||||
<> |
|
||||
<div className="item-title">{"维修计划信息"}</div> |
|
||||
<Row> |
|
||||
<Col span={12}> |
|
||||
{!readOnly ? <ProFormSelect |
|
||||
rules={[{ required: true, message: '请选择维修人' }]} |
|
||||
options={users || []} |
|
||||
disabled={readOnly} |
|
||||
name="repairPerson" |
|
||||
label="维修人" |
|
||||
fieldProps={{ |
|
||||
showSearch: true |
|
||||
}} |
|
||||
/> : |
|
||||
<ProFormText |
|
||||
name="repairPerson1" |
|
||||
label="维修人:" |
|
||||
disabled={true} |
|
||||
value={editData?.patrolRecordIssueHandles[0]?.repairPerson?.name} |
|
||||
/> |
|
||||
} |
|
||||
</Col> |
|
||||
<Col span={12}> |
|
||||
<ProFormDependency name={['repairPerson']}> |
|
||||
{({ repairPerson }) => { |
|
||||
const department = users?.find(s => s.id == repairPerson)?.department?.name |
|
||||
|
|
||||
return ( |
|
||||
<ProFormText |
|
||||
disabled={true} |
|
||||
name="repairUnits" |
|
||||
label="维修单位" |
|
||||
placeholder="" |
|
||||
fieldProps={{ |
|
||||
showSearch: true |
|
||||
}} |
|
||||
colProps={{ |
|
||||
span: 12, |
|
||||
}} |
|
||||
value={department} |
|
||||
/> |
|
||||
); |
|
||||
}} |
|
||||
</ProFormDependency> |
|
||||
|
|
||||
</Col> |
|
||||
|
|
||||
<Col span={12}> |
|
||||
<ProFormDateRangePicker |
|
||||
disabled={readOnly} |
|
||||
name="dateRange" |
|
||||
label="计划开始时间~结束时间:" |
|
||||
rules={[{ required: true, message: '请选择计划时间范围' }]} |
|
||||
/> |
|
||||
</Col> |
|
||||
<Col span={12}> |
|
||||
{!readOnly ? <ProFormSelect |
|
||||
rules={[{ required: true, message: '请选择质检人' }]} |
|
||||
options={users || []} |
|
||||
disabled={readOnly} |
|
||||
name="checkPerson" |
|
||||
label="质检人" |
|
||||
fieldProps={{ |
|
||||
showSearch: true |
|
||||
}} |
|
||||
/> : <ProFormText |
|
||||
name="checkPerson1" |
|
||||
label="质检人:" |
|
||||
disabled={true} |
|
||||
value={editData?.patrolRecordIssueHandles[0]?.checkPerson?.name} |
|
||||
/>} |
|
||||
</Col> |
|
||||
<Col span={12}> |
|
||||
<ProFormTextArea |
|
||||
name="repairAsk" |
|
||||
label="维修要求:" |
|
||||
disabled={readOnly} |
|
||||
rules={[ |
|
||||
{ |
|
||||
max: 200, message: '维修要求长度不能大于200个字符' |
|
||||
}, |
|
||||
{ |
|
||||
whitespace: true, message: '请勿输入空格' |
|
||||
}]} |
|
||||
placeholder="" |
|
||||
/></Col> |
|
||||
{editData?.patrolRecordIssueHandles[0]?.state && editData?.patrolRecordIssueHandles[0]?.state > 3 && <Col span={12}> |
|
||||
<ProFormText |
|
||||
name="approvePerson" |
|
||||
label="制定人:" |
|
||||
disabled={true} |
|
||||
/> |
|
||||
<ProFormText |
|
||||
name="approveDate" |
|
||||
label="制定时间:" |
|
||||
disabled={true} |
|
||||
/> |
|
||||
</Col>} |
|
||||
</Row> |
|
||||
</> |
|
||||
} |
|
||||
|
|
||||
{ |
|
||||
((editData?.patrolRecordIssueHandles[0]?.state > 2) || title == '审核') && |
|
||||
<> |
|
||||
<div className="item-title">{"维修计划审批"}</div> |
|
||||
<div> |
|
||||
<ProFormTextArea |
|
||||
name="approveOpinion" |
|
||||
label="审批意见:" |
|
||||
disabled={title != '审核'} |
|
||||
rules={[ |
|
||||
{ required: true, message: '请输入审批意见' }, |
|
||||
{ |
|
||||
max: 200, message: '审批意见长度不能大于200个字符' |
|
||||
}, |
|
||||
{ |
|
||||
whitespace: true, message: '请勿输入空格' |
|
||||
}]} |
|
||||
placeholder="请输入审批意见" |
|
||||
/> |
|
||||
</div> |
|
||||
</> |
|
||||
} |
|
||||
|
|
||||
{(editData?.patrolRecordIssueHandles[0]?.state && editData?.patrolRecordIssueHandles[0]?.state > 4) && renderRepairInfo()} |
|
||||
{(editData?.patrolRecordIssueHandles[0]?.state && editData?.patrolRecordIssueHandles[0]?.state > 5) && renderCheckInfo()} |
|
||||
</div> |
|
||||
</ ModalForm> |
|
||||
); |
|
||||
}; |
|
@ -1,5 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
import PatrolReocrd from './patrolRecord'; |
|
||||
|
|
||||
export { PatrolReocrd }; |
|
@ -1,268 +0,0 @@ |
|||||
|
|
||||
'use strict' |
|
||||
|
|
||||
import React, { useEffect, useState } from 'react'; |
|
||||
import { connect } from 'react-redux'; |
|
||||
import { Form, Input, Select, Button, Table, Modal, DatePicker, Checkbox, Row, Col, Collapse } from 'antd'; |
|
||||
import moment from "moment"; |
|
||||
import Uploads from '$components/Uploads'; |
|
||||
import IssueHandleModal from '../components/isuue-handle-mdal' |
|
||||
import '../style.less' |
|
||||
import { useFsRequest, ApiTable, Func } from '$utils'; |
|
||||
|
|
||||
const { Panel } = Collapse; |
|
||||
const ISSUEHANDLE_STATE = [1, 2, 3, 4, 5, 6, 7] |
|
||||
const STATE_TEXT = { 1: '待制定计划', 2: '待审核', 3: '计划驳回', 4: '待维修', 5: '待验收', 6: '验收通过', 7: '验收不通过', } |
|
||||
|
|
||||
const PatrolRecord = (props) => { |
|
||||
const { dispatch, actions, user } = props |
|
||||
const { patrolManage, issueHandle } = actions |
|
||||
const [tableList, settableList] = useState([]) |
|
||||
const [name, setName] = useState(''); |
|
||||
const [curState, setCurState] = useState('全部'); |
|
||||
const format = 'YYYY-MM-DD HH:mm:ss' |
|
||||
const times = [moment().subtract(70, 'years').format(format), moment().format(format)] |
|
||||
const [search, setSearch] = useState({ name: null, time: [times[0], times[1]], state: 'null' }) |
|
||||
|
|
||||
const { data: structsUsers = [] } = useFsRequest({ url: 'structures/users' }); |
|
||||
useEffect(() => { |
|
||||
queryData() |
|
||||
}, []) |
|
||||
|
|
||||
const queryData = () => { |
|
||||
dispatch(patrolManage.records(`patrolRecord/all/${times[0]}/${times[1]}/true/null`)).then(res => { |
|
||||
if (res.success) { |
|
||||
settableList(name != null ? res.payload.data |
|
||||
?.filter(v => (v.points.itemData.name.indexOf(name) != -1 || v.points.project.name.indexOf(name) != -1)) |
|
||||
.filter(x => curState == '全部' || curState == renderOptionText(x?.patrolRecordIssueHandles[0]?.state)) |
|
||||
.map(v => ({ ...v, key: v.id })) : res.payload.data?.map(v => ({ ...v, key: v.id }))) |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
const onFinish = async (values, editData) => { |
|
||||
const dataToSave = { ...values }; |
|
||||
if (editData?.patrolRecordIssueHandles?.length > 0) { |
|
||||
let msg = ''; |
|
||||
if (editData?.patrolRecordIssueHandles[0]?.state == 3) { |
|
||||
dataToSave.state = 2; |
|
||||
msg = '维修计划修改'; |
|
||||
} |
|
||||
|
|
||||
if (editData?.patrolRecordIssueHandles[0]?.state == 1) { |
|
||||
dataToSave.state = 2; |
|
||||
dataToSave.creator = user; |
|
||||
dataToSave.createTime = moment(); |
|
||||
msg = '计划制定'; |
|
||||
} |
|
||||
return dispatch( |
|
||||
issueHandle.modifyPatrolRecordIssueHandle(editData?.patrolRecordIssueHandles[0]?.id, dataToSave, |
|
||||
values?.msg || msg), |
|
||||
).then(() => { |
|
||||
queryData(); |
|
||||
}); |
|
||||
} |
|
||||
let state = ISSUEHANDLE_STATE[1]; |
|
||||
|
|
||||
return dispatch(issueHandle.addPatrolRecordIssueHandle({ |
|
||||
...dataToSave, |
|
||||
state, |
|
||||
patrolRecordId: editData?.id, |
|
||||
creator: user, |
|
||||
createTime: moment() |
|
||||
})).then(() => { |
|
||||
queryData(); |
|
||||
}); |
|
||||
}; |
|
||||
|
|
||||
const renderOptionText = (currentState) => { |
|
||||
let text = '待制定计划' |
|
||||
|
|
||||
return STATE_TEXT[currentState] || text |
|
||||
} |
|
||||
|
|
||||
const columns = [ |
|
||||
{ |
|
||||
title: '结构物名称', |
|
||||
dataIndex: 'name', |
|
||||
key: 'name', |
|
||||
width: '10%', |
|
||||
showInDetail: true, |
|
||||
render: (text, record, index) => { |
|
||||
return !record.points?.project ? '' : <div>{record.points.project.name}</div> |
|
||||
} |
|
||||
}, |
|
||||
{ |
|
||||
title: '上报人', |
|
||||
dataIndex: 'type', |
|
||||
key: 'type', |
|
||||
showInDetail: true, |
|
||||
width: '10%', |
|
||||
render: (text, record, index) => { |
|
||||
return !record.points?.user ? '' : <div>{record.points.user.name}</div> |
|
||||
} |
|
||||
}, |
|
||||
{ |
|
||||
title: '上报时间', |
|
||||
dataIndex: 'time', |
|
||||
key: 'time', |
|
||||
showInDetail: true, |
|
||||
render: (text, record, index) => moment(record.inspectionTime).format('YYYY-MM-DD HH:mm:ss') || '--' |
|
||||
}, { |
|
||||
title: '点位名称', |
|
||||
dataIndex: 'station', |
|
||||
key: 'station', |
|
||||
showInDetail: true, |
|
||||
render: (text, record, index) => record?.points?.itemData?.name |
|
||||
}, |
|
||||
{ |
|
||||
title: '问题来源', |
|
||||
dataIndex: 'source', |
|
||||
key: 'source', |
|
||||
showInDetail: true, |
|
||||
render: (text, record, index) => record?.patrolPlanId == -1 ? '主动上报' : '巡检上报' //暂定巡检上报 后续会增加平台录入
|
|
||||
}, |
|
||||
{ |
|
||||
title: '严重等级', |
|
||||
dataIndex: 'level', |
|
||||
key: 'level', |
|
||||
showInDetail: true, |
|
||||
render: (text, record, index) => { |
|
||||
const LEVELS_ = ['严重', '中度', '轻微']; |
|
||||
const recordLevels = [] |
|
||||
record?.points?.inspectContent ? Object.keys(record?.points?.inspectContent).map(key => { |
|
||||
recordLevels.push(record?.points?.inspectContent[key]?.level) |
|
||||
}) : '' |
|
||||
|
|
||||
|
|
||||
if (Array.isArray(record?.points?.inspectContent)) { |
|
||||
record?.points?.inspectContent?.map(x => { |
|
||||
x.checkItems?.map(v => { |
|
||||
recordLevels.push(v?.level) |
|
||||
}) |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
const level = LEVELS_.find(s => recordLevels.find(x => x == s)) |
|
||||
return level || '-'; |
|
||||
} |
|
||||
}, |
|
||||
{ |
|
||||
title: '当前状态', |
|
||||
dataIndex: 'state', |
|
||||
key: 'name', |
|
||||
width: '10%', |
|
||||
showInDetail: true, |
|
||||
render: (text, record, index) => { |
|
||||
return !record?.patrolRecordIssueHandles || record?.patrolRecordIssueHandles?.length == 0 ? '待制定计划' : |
|
||||
renderOptionText(record?.patrolRecordIssueHandles[0]?.state) |
|
||||
} |
|
||||
}, |
|
||||
{ |
|
||||
title: '操作', |
|
||||
dataIndex: 'operation', |
|
||||
key: 'operation', |
|
||||
render: (text, record, index) => { |
|
||||
const options = []; |
|
||||
if (Func.isAuthorized('ZHIDINGJIHUA') && (!record?.patrolRecordIssueHandles || record?.patrolRecordIssueHandles?.length == 0 || record?.patrolRecordIssueHandles[0]?.state == 1)) { |
|
||||
options.push(<IssueHandleModal |
|
||||
structsUsers={structsUsers} |
|
||||
editData={record} |
|
||||
readOnly={false} |
|
||||
key="edit" |
|
||||
title="制定计划" |
|
||||
triggerRender={<a style={{ marginRight: 8 }}>制定计划</a>} |
|
||||
user={user} |
|
||||
onFinish={onFinish} />) |
|
||||
} |
|
||||
|
|
||||
if (Func.isAuthorized('ZHIDINGJIHUA') && (record?.patrolRecordIssueHandles[0]?.state == 3 || record?.patrolRecordIssueHandles[0]?.state == 2)) { |
|
||||
options.push(<IssueHandleModal |
|
||||
structsUsers={structsUsers} |
|
||||
editData={record} |
|
||||
readOnly={false} |
|
||||
key="edit" |
|
||||
title="修改计划" |
|
||||
triggerRender={<a style={{ marginRight: 8 }}>修改计划</a>} |
|
||||
user={user} |
|
||||
onFinish={onFinish} />) |
|
||||
} |
|
||||
|
|
||||
if (Func.isAuthorized('SHENHE') && record?.patrolRecordIssueHandles[0]?.state == 2) { |
|
||||
options.push(<IssueHandleModal |
|
||||
structsUsers={structsUsers} |
|
||||
editData={record} |
|
||||
readOnly={true} |
|
||||
key="edit" |
|
||||
title="审核" |
|
||||
triggerRender={<a style={{ marginRight: 8 }}>审核</a>} |
|
||||
user={user} |
|
||||
onFinish={onFinish} />) |
|
||||
} |
|
||||
|
|
||||
|
|
||||
Func.isAuthorized('CHAKANXIANGQING') && options.push(<IssueHandleModal |
|
||||
structsUsers={structsUsers} |
|
||||
editData={record} |
|
||||
readOnly={true} |
|
||||
key="edit" |
|
||||
title="查看详情" |
|
||||
triggerRender={<a>查看详情</a>} |
|
||||
user={user} |
|
||||
onFinish={onFinish} />) |
|
||||
|
|
||||
return options; |
|
||||
} |
|
||||
} |
|
||||
] |
|
||||
|
|
||||
return ( |
|
||||
<div id='patrol-record' className='global-main'> |
|
||||
<div style={{ marginBottom: 20, display: 'flex', justifyContent: 'space-between' }}> |
|
||||
<div className='title'> |
|
||||
<span className='line'></span> |
|
||||
<span className='cn'>问题处理</span> |
|
||||
<span className='en'> PROBLEM HANDLING</span> |
|
||||
</div> |
|
||||
<div> |
|
||||
<Input style={{ width: 240, marginRight: 20 }} |
|
||||
value={name} onChange={e => { setName(e.target.value) }} |
|
||||
placeholder="请输入结构物名称或点位名称" allowClear /> |
|
||||
<Select |
|
||||
value={curState} |
|
||||
onChange={e => { setCurState(e) }} |
|
||||
style={{ width: 140, marginRight: 20 }} |
|
||||
options={[ |
|
||||
{ value: '全部', label: '全部' }, |
|
||||
].concat(ISSUEHANDLE_STATE.map(s => { |
|
||||
return { value: renderOptionText(s), label: renderOptionText(s) } |
|
||||
}))} /> |
|
||||
<Button type='primary' onClick={() => { queryData() }}>搜索</Button> |
|
||||
</div> |
|
||||
</div> |
|
||||
<Table |
|
||||
columns={columns} |
|
||||
dataSource={tableList} |
|
||||
pagination={{ |
|
||||
showSizeChanger: true, |
|
||||
pageSizeOptions: [10, 20, 50], |
|
||||
className: 'global-pagination', |
|
||||
}} |
|
||||
rowClassName={(record, index) => { |
|
||||
let className = 'global-light-row'; |
|
||||
if (index % 2 === 1) className = 'global-dark-row'; |
|
||||
return className; |
|
||||
}} |
|
||||
/> |
|
||||
</div> |
|
||||
) |
|
||||
} |
|
||||
|
|
||||
function mapStateToProps(state) { |
|
||||
const { auth, global } = state; |
|
||||
return { |
|
||||
user: auth.user, |
|
||||
actions: global.actions, |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
export default connect(mapStateToProps)(PatrolRecord); |
|
@ -1,15 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
import reducers from './reducers'; |
|
||||
import routes from './routes'; |
|
||||
import actions from './actions'; |
|
||||
import { getNavItem } from './nav-item'; |
|
||||
|
|
||||
export default { |
|
||||
key: 'issueHandle', |
|
||||
name: '', |
|
||||
reducers: reducers, |
|
||||
routes: routes, |
|
||||
actions: actions, |
|
||||
getNavItem: getNavItem |
|
||||
}; |
|
@ -1,21 +0,0 @@ |
|||||
import React from 'react'; |
|
||||
import { Link } from 'react-router-dom'; |
|
||||
import { Menu } from 'antd'; |
|
||||
import { CompressOutlined } from '@ant-design/icons'; |
|
||||
import { Func } from '$utils'; |
|
||||
const SubMenu = Menu.SubMenu; |
|
||||
|
|
||||
export function getNavItem(user, dispatch) { |
|
||||
// if (!Func.isAuthorized("ORG_MANAGE")) {
|
|
||||
// return null
|
|
||||
// }
|
|
||||
return ( |
|
||||
(Func.isAuthorized("SHENHE") |
|
||||
|| Func.isAuthorized("ZHIDINGJIHUA") |
|
||||
|| Func.isAuthorized("CHAKANXIANGQING")) && |
|
||||
<Menu.Item icon={<img src='/assets/images/menu/issue.svg' style={{ width: 24, height: 24 }} />} key="issueHandle"> |
|
||||
<Link to="/issueHandle">问题处理</Link> |
|
||||
</Menu.Item> |
|
||||
|
|
||||
); |
|
||||
} |
|
@ -1,5 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
export default { |
|
||||
|
|
||||
}; |
|
@ -1,32 +0,0 @@ |
|||||
'use strict'; |
|
||||
import * as actionTypes from '../actions/record'; |
|
||||
import Immutable from 'immutable'; |
|
||||
|
|
||||
const initState = { |
|
||||
data: {}, |
|
||||
isRequesting: false, |
|
||||
error: null |
|
||||
}; |
|
||||
|
|
||||
function record(state = initState, action) { |
|
||||
const payload = action.payload; |
|
||||
switch (action.type){ |
|
||||
case actionTypes.GET_PATROL_RECORD_LIST: |
|
||||
return Immutable.fromJS(state).set('data', |
|
||||
payload.data).toJS(); |
|
||||
case actionTypes.GET_PATROL_RECORD_LIST_SUCCESS: |
|
||||
return Immutable.fromJS(state).merge({ |
|
||||
isRequesting: false, |
|
||||
data: payload.data |
|
||||
}).toJS(); |
|
||||
case actionTypes.GET_PATROL_RECORD_LIST_ERROR: |
|
||||
return Immutable.fromJS(state).merge({ |
|
||||
isRequesting: false, |
|
||||
error: payload.error |
|
||||
}).toJS(); |
|
||||
default: |
|
||||
return state; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
export default record; |
|
@ -1,13 +0,0 @@ |
|||||
'use strict'; |
|
||||
import { PatrolReocrd } from './containers'; |
|
||||
|
|
||||
export default [{ |
|
||||
type: 'inner', |
|
||||
route: { |
|
||||
path: '/issueHandle', |
|
||||
key: 'issueHandle', |
|
||||
breadcrumb: '问题处理', |
|
||||
component: PatrolReocrd, |
|
||||
|
|
||||
} |
|
||||
}]; |
|
@ -1,13 +0,0 @@ |
|||||
.patrol-record-detail-modal { |
|
||||
.ant-collapse>.ant-collapse-item>.ant-collapse-header { |
|
||||
padding: 0 |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.item-title { |
|
||||
background-color: #4A93DF; |
|
||||
padding: 10px; |
|
||||
color: #fff; |
|
||||
margin-bottom: 20px; |
|
||||
padding-left: 20px; |
|
||||
} |
|
@ -1,51 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
import { basicAction } from '@peace/utils' |
|
||||
import { ApiTable } from '$utils' |
|
||||
|
|
||||
export function getAuthority(orgId) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'get', |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'GET_MEMBERS', |
|
||||
url: `${ApiTable.getEnterprisesMembers.replace('{enterpriseId}', orgId)}`, |
|
||||
msg: { error: '获取用户列表失败' }, |
|
||||
reducer: { name: 'members' } |
|
||||
}); |
|
||||
} |
|
||||
export function getResource(userId) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'get', |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'GET_RESOURCE', |
|
||||
url: `${ApiTable.getResource}`, |
|
||||
msg: { error: '获取权限失败' }, |
|
||||
reducer: { name: 'resource' } |
|
||||
}); |
|
||||
} |
|
||||
export function getUserResource(userId) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'get', |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'GET_USER_RESOURCE', |
|
||||
url: `${ApiTable.getUserResource}?userId=${userId}`, |
|
||||
msg: { error: '获取用户权限失败' }, |
|
||||
reducer: { name: 'userResource' } |
|
||||
}); |
|
||||
} |
|
||||
export function postUserRes(body) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'post', |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'UPDATE_USER_RESOURCE', |
|
||||
url: `${ApiTable.postUserRes}`, |
|
||||
data: body, |
|
||||
msg: { success: '更新用户权限' } |
|
||||
}); |
|
||||
} |
|
||||
export default { |
|
||||
getAuthority, |
|
||||
getResource, |
|
||||
getUserResource, |
|
||||
postUserRes |
|
||||
} |
|
@ -1,11 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
import * as authority from './authority' |
|
||||
import { getDepMessage, getDepUser, createUser } from './user' |
|
||||
|
|
||||
export default { |
|
||||
...authority, |
|
||||
getDepMessage, |
|
||||
getDepUser, |
|
||||
createUser, |
|
||||
} |
|
@ -1,113 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
import { basicAction } from '@peace/utils' |
|
||||
import { ApiTable } from '$utils' |
|
||||
|
|
||||
export function getDepMessage() { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'get', |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'GET_DEPARTMENT_MESSAGE', |
|
||||
url: ApiTable.getDepMessage, |
|
||||
msg: { error: '获取部门信息失败' }, |
|
||||
reducer: { name: 'depMessage' } |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
//新建部门
|
|
||||
export function createDept(data) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'post', |
|
||||
data, |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'CREATE_DEPT', |
|
||||
url: ApiTable.createDept, |
|
||||
msg: { option: '新建部门' }, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
//修改部门
|
|
||||
export function updateDept(id, data) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'put', |
|
||||
data, |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'UPDATE_DEPT', |
|
||||
url: ApiTable.updateDept.replace('{id}', id), |
|
||||
msg: { option: '修改部门' }, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
//删除部门
|
|
||||
export function delDept(id) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'del', |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'DEL_DEPT', |
|
||||
url: ApiTable.delDept.replace('{id}', id), |
|
||||
msg: { option: '删除部门' }, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function getDepUser(depId) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'get', |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'GET_DEPARTMENT_USER', |
|
||||
url: ApiTable.getDepUser.replace('{depId}', depId), |
|
||||
msg: { error: '获取部门下用户信息失败' }, |
|
||||
reducer: { name: 'depUser' } |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function createUser(data) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'post', |
|
||||
data, |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'CREATE_DEPARTMENT_USER', |
|
||||
url: ApiTable.createUser, |
|
||||
msg: { option: '新建用户' }, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function updateUser(id, data) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'put', |
|
||||
data, |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'UPDATE_DEPARTMENT_USER', |
|
||||
url: ApiTable.updateUser.replace('{id}', id), |
|
||||
msg: { option: '修改用户' }, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function delUser(ids) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'del', |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'DEL_DEPARTMENT_USER', |
|
||||
url: ApiTable.delUser.replace('{ids}', ids), |
|
||||
msg: { option: '删除用户' }, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function resetPwd(id, data) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'put', |
|
||||
data, |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'CREATE_DEPARTMENT_USER', |
|
||||
url: ApiTable.resetPwd.replace('{id}', id), |
|
||||
msg: { option: '重置用户密码' }, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export default { |
|
||||
getDepMessage, |
|
||||
getDepUser, |
|
||||
createUser, |
|
||||
updateUser, |
|
||||
delUser, |
|
||||
resetPwd |
|
||||
} |
|
@ -1,88 +0,0 @@ |
|||||
import React from 'react'; |
|
||||
import { connect } from 'react-redux'; |
|
||||
import { ProFormText, ModalForm, ProFormSelect } from '@ant-design/pro-form'; |
|
||||
|
|
||||
const DeptModal = (props) => { |
|
||||
const { visible, modalType, onVisibleChange, onConfirm, editData, depts } = props |
|
||||
let deptOptions = [], sonArr = []; |
|
||||
depts.map(d => { |
|
||||
deptOptions.push({ |
|
||||
value: d.id, |
|
||||
label: d.name |
|
||||
}); |
|
||||
|
|
||||
d.subordinate.map(ds => { |
|
||||
sonArr.push({ |
|
||||
value: ds.id, |
|
||||
label: ds.name |
|
||||
}) |
|
||||
}) |
|
||||
}) |
|
||||
const onFinish = (values) => { |
|
||||
if (onConfirm) { |
|
||||
if (modalType === 'edit') { |
|
||||
values.contract.parentDeptId = values.contract.parentDeptId || null |
|
||||
onConfirm(values) |
|
||||
} else { |
|
||||
onConfirm(values); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
const checkName = (rule, value, callback) => { |
|
||||
const list = modalType == 'edit' ? deptOptions.concat(sonArr).filter(g => g.value != editData.id) : deptOptions.concat(sonArr) |
|
||||
if (list.filter(s => s.label == value).length) { |
|
||||
callback('该名称已存在'); |
|
||||
} else { |
|
||||
callback(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return ( |
|
||||
<ModalForm |
|
||||
width={400} |
|
||||
title={modalType == 'edit' ? '编辑部门' : '新建部门'} |
|
||||
visible={visible} |
|
||||
onVisibleChange={onVisibleChange} |
|
||||
onFinish={onFinish} |
|
||||
destroyOnClose |
|
||||
initialValues={ |
|
||||
modalType == 'edit' ? |
|
||||
{ |
|
||||
contract: editData |
|
||||
} : |
|
||||
{ |
|
||||
contract: { |
|
||||
enable: true |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
> |
|
||||
<ProFormText |
|
||||
name={['contract', 'name']} |
|
||||
maxLength={24} |
|
||||
width="md" |
|
||||
label="部门名称" |
|
||||
required |
|
||||
placeholder="请输入部门名称" |
|
||||
rules={[{ required: true, message: '请输入部门名称' }, { validator: checkName }]} |
|
||||
/> |
|
||||
<ProFormSelect |
|
||||
name={['contract', 'dependence']} |
|
||||
label="上级部门" |
|
||||
request={async () => { |
|
||||
let t = modalType === 'edit' ? deptOptions.filter(i => i.value !== editData.id) : deptOptions |
|
||||
return t |
|
||||
}} |
|
||||
disabled={modalType === 'edit' ? editData.subordinate?.length === 0 ? false : true : false} |
|
||||
/> |
|
||||
</ModalForm> |
|
||||
) |
|
||||
} |
|
||||
|
|
||||
function mapStateToProps(state) { |
|
||||
return { |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
export default connect(mapStateToProps)(DeptModal); |
|
@ -1,74 +0,0 @@ |
|||||
import React, { useRef, useState } from 'react'; |
|
||||
import { connect } from 'react-redux'; |
|
||||
import { Spin, Card, Modal, TreeSelect } from 'antd'; |
|
||||
import ProForm, { ProFormText, ModalForm, ProFormSwitch, ProFormTreeSelect } from '@ant-design/pro-form'; |
|
||||
|
|
||||
const ResetPwd = (props) => { |
|
||||
const { visible, onVisibleChange, onConfirm } = props; |
|
||||
const formRef = useRef(); |
|
||||
|
|
||||
const onFinish = (values) => { |
|
||||
if (onConfirm) { |
|
||||
onConfirm(values); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return ( |
|
||||
<Spin spinning={false}> |
|
||||
<ModalForm |
|
||||
title={'重置密码'} |
|
||||
visible={visible} |
|
||||
onVisibleChange={onVisibleChange} |
|
||||
onFinish={onFinish} |
|
||||
formRef={formRef} |
|
||||
destroyOnClose |
|
||||
> |
|
||||
<ProFormText.Password |
|
||||
name={['password']} |
|
||||
width="md" |
|
||||
label="新密码" |
|
||||
required |
|
||||
placeholder="请输入密码" |
|
||||
fieldProps={{ |
|
||||
autocomplete: 'new-password' |
|
||||
}} |
|
||||
rules={[ |
|
||||
{ required: true, message: '请填写密码' }, |
|
||||
{ min: 6, message: '请填写至少6位密码' }, |
|
||||
]} |
|
||||
/> |
|
||||
<ProFormText.Password |
|
||||
name={['checkPassword']} |
|
||||
width="md" |
|
||||
label="确认密码" |
|
||||
required |
|
||||
autocomplete='off' |
|
||||
placeholder="请输入密码" |
|
||||
rules={[ |
|
||||
{ required: true, message: '请再次填写密码' }, |
|
||||
{ min: 6, message: '请填写至少6位密码' }, |
|
||||
{ |
|
||||
validator: (rule, value, callback) => { |
|
||||
const pwd = formRef.current.getFieldValue('password'); |
|
||||
if (!value) { |
|
||||
callback(); |
|
||||
} |
|
||||
if (pwd == value) { |
|
||||
callback(); |
|
||||
} else { |
|
||||
callback('两次输入的密码不一致'); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
]} |
|
||||
/> |
|
||||
</ModalForm> |
|
||||
</Spin> |
|
||||
) |
|
||||
} |
|
||||
|
|
||||
function mapStateToProps(state) { |
|
||||
return {}; |
|
||||
} |
|
||||
|
|
||||
export default connect(mapStateToProps)(ResetPwd); |
|
@ -1,126 +0,0 @@ |
|||||
import React, { useEffect } from 'react'; |
|
||||
import { Checkbox, Table } from 'antd'; |
|
||||
import { useState } from 'react'; |
|
||||
|
|
||||
const CheckboxGroup = Checkbox.Group; |
|
||||
|
|
||||
const Resource = props => { |
|
||||
const { roleData, userRole, userSelected, setResCode, userType } = props; |
|
||||
const [indeterminate, setIndeterminate] = useState({}); |
|
||||
const [roleCheck, setRoleCheck] = useState({});//一级权限码
|
|
||||
const [parentRoleCheck, setParentRoleCheck] = useState({}); //二级权限码
|
|
||||
|
|
||||
const roleDatas = roleData.slice(0) |
|
||||
useEffect(() => { |
|
||||
const check = {} |
|
||||
const parentCheck = {} |
|
||||
const initInd = {} |
|
||||
roleData && roleData.map && roleData.map(r => { |
|
||||
let currentInd = false; |
|
||||
let sum = 0; |
|
||||
if (r.resources) { |
|
||||
check[r.code] = [] |
|
||||
r.resources.map(child => { |
|
||||
if (userRole.find(code => code.resourceId == child.code)) { |
|
||||
currentInd = true; |
|
||||
sum++; |
|
||||
check[r.code].push(child.code); |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
parentCheck[r.code] = r.resources.length === sum |
|
||||
initInd[r.code] = parentCheck[r.code] ? false : currentInd |
|
||||
}); |
|
||||
setParentRoleCheck(parentCheck) |
|
||||
setRoleCheck(check); |
|
||||
setIndeterminate(initInd); |
|
||||
}, [userRole]); |
|
||||
|
|
||||
const setResData = (role) => { |
|
||||
let codes = []; |
|
||||
// Object.keys(partRole).map(r => {
|
|
||||
// if (partRole[r]) codes.push(r)
|
|
||||
// })
|
|
||||
Object.keys(role).map(r => { |
|
||||
if (role[r].length) { |
|
||||
codes.push(r); |
|
||||
} |
|
||||
codes = codes.concat(role[r]) |
|
||||
}) |
|
||||
setResCode(codes) |
|
||||
} |
|
||||
return ( |
|
||||
<Table |
|
||||
bordered |
|
||||
pagination={false} |
|
||||
dataSource={roleDatas} |
|
||||
rowClassName={(record, index) => { |
|
||||
let className = 'global-light-row'; |
|
||||
if (index % 2 === 1) className = 'global-dark-row'; |
|
||||
return className; |
|
||||
}} |
|
||||
columns={[{ |
|
||||
title: '功能', |
|
||||
key: 'name', |
|
||||
dataIndex: 'name', |
|
||||
render: (text, record) => { |
|
||||
const parentCode = record.code |
|
||||
return <Checkbox |
|
||||
|
|
||||
indeterminate={indeterminate[parentCode]} |
|
||||
onChange={(e) => { |
|
||||
const currentParCheck = JSON.parse(JSON.stringify(parentRoleCheck)); |
|
||||
currentParCheck[parentCode] = e.target.checked; |
|
||||
const currentCode = JSON.parse(JSON.stringify(roleCheck)); |
|
||||
currentCode[parentCode] = e.target.checked ? roleData.find(r => r.code == parentCode).resources.map(r => r.code) : [] |
|
||||
const currentInd = JSON.parse(JSON.stringify(indeterminate)); |
|
||||
currentInd[parentCode] = false; |
|
||||
|
|
||||
setParentRoleCheck(currentParCheck); |
|
||||
setRoleCheck(currentCode); |
|
||||
setIndeterminate(currentInd); |
|
||||
setResData(currentCode) |
|
||||
}} |
|
||||
checked={parentRoleCheck[parentCode] || false} |
|
||||
disabled={userSelected === "SuperAdmin" || userType === 4} |
|
||||
options={''} |
|
||||
> |
|
||||
{text} |
|
||||
</Checkbox> |
|
||||
} |
|
||||
}, { |
|
||||
title: '列表', |
|
||||
key: 'resources', |
|
||||
dataIndex: 'resources', |
|
||||
render: (text, record) => { |
|
||||
let data = []; |
|
||||
console.log() |
|
||||
text.map(s => { s.name !== "整治汇总编辑" ? data.push({ label: s.name, value: s.code }) : '' }) |
|
||||
let parentCode = record.code; |
|
||||
|
|
||||
return <CheckboxGroup |
|
||||
disabled={userSelected === "SuperAdmin" || userType === 4} |
|
||||
options={data} |
|
||||
value={roleCheck[parentCode] || []} |
|
||||
onChange={value => { |
|
||||
const checkArr = JSON.parse(JSON.stringify(roleCheck)); |
|
||||
const parentCheck = JSON.parse(JSON.stringify(parentRoleCheck)); |
|
||||
const ind = JSON.parse(JSON.stringify(indeterminate)); |
|
||||
const currentCode = roleData.find(r => r.code == parentCode) || {} |
|
||||
|
|
||||
checkArr[parentCode] = value; |
|
||||
ind[parentCode] = !!value.length && value.length < currentCode.resources.length |
|
||||
parentCheck[parentCode] = value.length === currentCode.resources.length |
|
||||
|
|
||||
setRoleCheck(checkArr); |
|
||||
setIndeterminate(ind); |
|
||||
setParentRoleCheck(parentCheck); |
|
||||
setResData(checkArr) |
|
||||
}} |
|
||||
/> |
|
||||
} |
|
||||
}]} |
|
||||
></Table > |
|
||||
) |
|
||||
} |
|
||||
export default Resource |
|
@ -1,237 +0,0 @@ |
|||||
import React from 'react'; |
|
||||
import { connect } from 'react-redux'; |
|
||||
import { Spin, Card, Modal, TreeSelect, message } from 'antd'; |
|
||||
import ProForm, { ProFormText, ModalForm, ProFormSwitch, ProFormTreeSelect, ProFormSelect } from '@ant-design/pro-form'; |
|
||||
|
|
||||
const UserModal = (props) => { |
|
||||
const { visible, modalType, depData, onVisibleChange, onConfirm, editData, tableList } = props |
|
||||
const reg_tel = /^1([358][0-9]|4[579]|66|7[0135678]|9[89])[0-9]{8}$/; |
|
||||
const onFinish = (values) => { |
|
||||
if (onConfirm) { |
|
||||
onConfirm(values); |
|
||||
} |
|
||||
} |
|
||||
const mobile = (value) => { |
|
||||
if (reg_tel.test(value)) { |
|
||||
return |
|
||||
} |
|
||||
return message('请输入姓名') |
|
||||
} |
|
||||
return ( |
|
||||
<Spin spinning={false}> |
|
||||
<ModalForm |
|
||||
modalProps={{ |
|
||||
className: "global-modal-form", |
|
||||
}} |
|
||||
layout="horizontal" |
|
||||
grid={true} |
|
||||
width={800} |
|
||||
title={modalType == 'edit' ? '编辑用户' : '新建用户'} |
|
||||
visible={visible} |
|
||||
onVisibleChange={onVisibleChange} |
|
||||
onFinish={onFinish} |
|
||||
destroyOnClose |
|
||||
initialValues={ |
|
||||
modalType == 'edit' ? |
|
||||
{ |
|
||||
contract: editData |
|
||||
} : |
|
||||
{ |
|
||||
contract: { |
|
||||
enable: true, |
|
||||
role: '巡检人员' |
|
||||
}, |
|
||||
} |
|
||||
} |
|
||||
> |
|
||||
<ProForm.Group> |
|
||||
<ProFormText |
|
||||
name={['contract', 'name']} |
|
||||
colProps={{ md: 12, xl: 12 }} |
|
||||
maxLength={24} |
|
||||
label="姓名" |
|
||||
required |
|
||||
placeholder="请输入姓名" |
|
||||
rules={[{ required: true, message: '请输入姓名' }]} |
|
||||
bordered={false} |
|
||||
/> |
|
||||
<ProFormText |
|
||||
name={['contract', 'phone']} |
|
||||
colProps={{ md: 12, xl: 12 }} |
|
||||
label="用户名(手机号)" |
|
||||
required |
|
||||
fieldProps={{ |
|
||||
maxLength: 11, |
|
||||
}} |
|
||||
getValueFromEvent={(event) => { |
|
||||
return event.target.value.replace(/\D/g, '') |
|
||||
}} |
|
||||
placeholder="请输入用户名(手机号)" |
|
||||
rules={[ |
|
||||
{ required: true, valueType: Number, max: 11 }, { pattern: /^1(3|4|5|6|7|8|9)\d{9}$/, message: "请输入正确的手机号" } |
|
||||
]} |
|
||||
/> |
|
||||
</ProForm.Group> |
|
||||
<ProForm.Group> |
|
||||
<ProFormTreeSelect |
|
||||
name={['contract', 'departmentId']} |
|
||||
placeholder="请选择所属部门" |
|
||||
colProps={{ md: 12, xl: 12 }} |
|
||||
label="所属部门" |
|
||||
required |
|
||||
fieldNames={{ |
|
||||
title: 'name', |
|
||||
key: 'id', |
|
||||
children: 'subordinate' |
|
||||
}} |
|
||||
onSelect={(selectedKeys, { selected, selectedNodes }) => { |
|
||||
if (selected) { |
|
||||
setDepSelectedKeys(selectedKeys) |
|
||||
setDepSelected(selectedNodes[0].name || "") |
|
||||
dispatch(getDepUser(selectedKeys[0])) |
|
||||
} |
|
||||
}} |
|
||||
fieldProps={{ |
|
||||
fieldNames: { |
|
||||
label: 'title', |
|
||||
}, |
|
||||
treeDefaultExpandAll: false, |
|
||||
}} |
|
||||
rules={[{ required: true, message: '请选择所属部门' }]} |
|
||||
request={async () => { |
|
||||
console.log(depData); |
|
||||
return depData |
|
||||
}} |
|
||||
expandedKeys={["title"]} |
|
||||
/> |
|
||||
< ProFormText |
|
||||
name={['contract', 'post']} |
|
||||
colProps={{ md: 12, xl: 12 }} |
|
||||
label="职位" |
|
||||
// required
|
|
||||
placeholder="请输入职位" |
|
||||
/> |
|
||||
</ProForm.Group> |
|
||||
<ProForm.Group> |
|
||||
{/* <ProFormTreeSelect |
|
||||
name={['contract', 'structure']} |
|
||||
placeholder="请选择结构物" |
|
||||
width="md" |
|
||||
mode="multiple" |
|
||||
label="关注结构物" |
|
||||
required |
|
||||
// fieldNames={{
|
|
||||
// title: 'name',
|
|
||||
// key: 'id',
|
|
||||
// children: 'subordinate'
|
|
||||
// }}
|
|
||||
onSelect={(selectedKeys, { selected, selectedNodes }) => { |
|
||||
|
|
||||
}} |
|
||||
fieldProps={{ |
|
||||
mode: 'multiple', |
|
||||
fieldNames: { |
|
||||
label: 'title', |
|
||||
}, |
|
||||
treeDefaultExpandAll: false, |
|
||||
}} |
|
||||
rules={[{ required: true, message: '请选择结构物' }]} |
|
||||
request={async () => { |
|
||||
console.log(tableList); |
|
||||
const opts = tableList?.map(i=>({title:i.name,value:i.id})) |
|
||||
return opts |
|
||||
}} |
|
||||
expandedKeys={["title"]} |
|
||||
/> */} |
|
||||
<ProFormSelect |
|
||||
colProps={{ md: 12, xl: 12 }} |
|
||||
label="关注结构物" |
|
||||
name={['contract', 'structure']} |
|
||||
mode="multiple" |
|
||||
// fieldProps={{//这里使用了select的onChange方法,必须使用这样的写法来进行调用onChange方法
|
|
||||
// onChange:(val) => handleChange(val),
|
|
||||
// }}
|
|
||||
request={async () => { |
|
||||
console.log(tableList); |
|
||||
const opts = tableList?.map(i => ({ label: i.name, value: i.id })) |
|
||||
return opts |
|
||||
}} |
|
||||
placeholder="请选择结构物" |
|
||||
rules={[{ required: true, message: '结构物不能为空' }]} |
|
||||
/> |
|
||||
|
|
||||
<ProFormText |
|
||||
name={['contract', 'email']} |
|
||||
colProps={{ md: 12, xl: 12 }} |
|
||||
label="邮箱" |
|
||||
// required
|
|
||||
placeholder="请输入邮箱" |
|
||||
rules={[ |
|
||||
// { required: true, message: '请输入邮箱' },
|
|
||||
{ type: 'email', message: '请输入正确格式的邮箱' }, |
|
||||
]} |
|
||||
/> |
|
||||
</ProForm.Group> |
|
||||
<ProForm.Group> |
|
||||
{modalType == 'edit' ? null : <ProFormText.Password |
|
||||
name={['contract', 'password']} |
|
||||
colProps={{ md: 12, xl: 12 }} |
|
||||
label="密码" |
|
||||
required |
|
||||
placeholder="请输入密码" |
|
||||
fieldProps={{ |
|
||||
autocomplete: 'new-password' |
|
||||
}} |
|
||||
rules={[ |
|
||||
{ required: true, message: '请填写密码' }, |
|
||||
{ min: 6, message: '请填写至少6位密码' }, |
|
||||
]} |
|
||||
/>} |
|
||||
<ProFormSwitch |
|
||||
name={['contract', 'enable']} |
|
||||
colProps={{ md: 12, xl: 12 }} |
|
||||
label="是否启用" |
|
||||
placeholder="请选择" |
|
||||
// defaultChecked
|
|
||||
valuePropName="checked" |
|
||||
/> |
|
||||
</ProForm.Group> |
|
||||
|
|
||||
<ProFormSelect |
|
||||
name={['contract', 'role']} |
|
||||
colProps={{ md: 12, xl: 12 }} |
|
||||
label="角色" |
|
||||
placeholder="请选择角色" |
|
||||
options={[{ label: '巡检人员', value: '巡检人员' }, { label: '管理人员', value: '管理人员' }]} |
|
||||
rules={[ |
|
||||
{ required: true, message: '请选择角色' }, |
|
||||
]} |
|
||||
/> |
|
||||
</ModalForm> |
|
||||
</Spin> |
|
||||
) |
|
||||
} |
|
||||
|
|
||||
function mapStateToProps(state) { |
|
||||
const { depMessage } = state; |
|
||||
|
|
||||
const pakData = (dep) => { |
|
||||
// console.log(dep);
|
|
||||
return dep.map((d) => { |
|
||||
return { |
|
||||
title: d.name, |
|
||||
value: d.id, |
|
||||
// key: d.id,
|
|
||||
children: pakData(d.subordinate) |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
let depData = pakData(depMessage.data || []) |
|
||||
|
|
||||
return { |
|
||||
loading: depMessage.isRequesting, |
|
||||
depData, |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
export default connect(mapStateToProps)(UserModal); |
|
@ -1,158 +0,0 @@ |
|||||
import React, { useEffect, useState } from 'react'; |
|
||||
import { connect } from 'react-redux'; |
|
||||
import { Spin, Row, Col, Card, Button, Tree, Empty, Divider } from 'antd'; |
|
||||
import { getDepMessage, getDepUser } from '../actions/user'; |
|
||||
import { getResource, getUserResource, postUserRes } from '../actions/authority'; |
|
||||
import Resource from '../components/resource'; |
|
||||
import './authority.less'; |
|
||||
|
|
||||
const Authority = (props) => { |
|
||||
const { dispatch, loading, depMessage, depUser, resource, userResource, clientHeight } = props |
|
||||
const [depSelectedKeys, setDepSelectedKeys] = useState([]) |
|
||||
const [userSelectedKeys, setUserSelectedKeys] = useState([]) |
|
||||
const [depSelected, setDepSelected] = useState() |
|
||||
const [userSelected, setUserSelected] = useState() |
|
||||
const [resCode, setResCode] = useState({}) |
|
||||
const [useName, setUseName] = useState()// 选中名字
|
|
||||
const [userType, setUserType] = useState() |
|
||||
useEffect(() => { |
|
||||
dispatch(getResource()) |
|
||||
if (!(depMessage && depMessage.length)) { |
|
||||
dispatch(getDepMessage()) |
|
||||
} |
|
||||
|
|
||||
}, []) |
|
||||
useEffect(() => { |
|
||||
if (depMessage.length) { |
|
||||
setDepSelectedKeys([depMessage[0].id]) |
|
||||
setDepSelected([depMessage[0].name]) |
|
||||
dispatch(getDepUser(depMessage[0].id)) |
|
||||
} |
|
||||
|
|
||||
}, [depMessage]) |
|
||||
useEffect(() => { |
|
||||
if (depUser.length) { |
|
||||
setUserSelectedKeys([depUser[0].id]) |
|
||||
setUserSelected(depUser[0].username) |
|
||||
dispatch(getUserResource(depUser[0].id)) |
|
||||
setUseName(depUser[0].name) |
|
||||
} else { |
|
||||
setUseName('') |
|
||||
} |
|
||||
}, [depUser]) |
|
||||
|
|
||||
const handleSave = () => { |
|
||||
dispatch(postUserRes({ userId: userSelectedKeys[0], resCode: resCode })).then(res => { |
|
||||
if (res.success) { |
|
||||
dispatch(getUserResource(userSelectedKeys[0])) |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
return ( |
|
||||
<div className='main'> |
|
||||
<Spin spinning={loading}> |
|
||||
<div> |
|
||||
<div className='title'> |
|
||||
<span className='line'></span> |
|
||||
<span className='cn'>权限功能</span> |
|
||||
<span className='en'> PERMISSION FUNCTION</span> |
|
||||
</div> |
|
||||
<div className='tree-box'> |
|
||||
{ |
|
||||
depMessage.length ? |
|
||||
<Tree |
|
||||
style={{ width: 272 }} |
|
||||
height={195} |
|
||||
defaultExpandedKeys={[depMessage[0].id]} |
|
||||
selectedKeys={depSelectedKeys} |
|
||||
onSelect={(selectedKeys, { selected, selectedNodes, node }) => { |
|
||||
setUserType(selectedNodes[0].type) |
|
||||
if (selected) { |
|
||||
setDepSelectedKeys(selectedKeys) |
|
||||
setDepSelected(selectedNodes[0].name || "") |
|
||||
dispatch(getDepUser(selectedKeys[0])) |
|
||||
} |
|
||||
|
|
||||
}} |
|
||||
treeData={depMessage} |
|
||||
fieldNames={{ |
|
||||
title: 'name', |
|
||||
key: 'id', |
|
||||
children: 'subordinate' |
|
||||
}} |
|
||||
/> : '' |
|
||||
} |
|
||||
<div className='user-list'> |
|
||||
<div className='list-title'> |
|
||||
{(depSelected ? `【${depSelected}】` : "") + '用户列表'} |
|
||||
</div> |
|
||||
{ |
|
||||
depUser.length ? |
|
||||
<Tree |
|
||||
// style={{ width: 272 }}
|
|
||||
height={168} |
|
||||
defaultSelectedKeys={[depUser[0].id]} |
|
||||
selectedKeys={userSelectedKeys} |
|
||||
onSelect={(selectedKeys, { selected, selectedNodes, node, event }) => { |
|
||||
const name = node.name |
|
||||
setUseName(name) |
|
||||
|
|
||||
if (selected) { |
|
||||
setUserSelectedKeys(selectedKeys) |
|
||||
setUserSelected(selectedNodes[0].username || '') |
|
||||
dispatch(getUserResource(selectedKeys[0])) |
|
||||
} |
|
||||
|
|
||||
}} |
|
||||
treeData={depUser} |
|
||||
fieldNames={{ |
|
||||
title: 'name', |
|
||||
key: 'id' |
|
||||
}} |
|
||||
/> : <Empty /> |
|
||||
} |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<Divider /> |
|
||||
<div className='list-title'> |
|
||||
{`【${useName || ''}】 功能范围`} |
|
||||
</div> |
|
||||
{depUser.length ? |
|
||||
<Card bordered={false} bodyStyle={{ padding: 8, paddingTop: 24 }}> |
|
||||
<Resource |
|
||||
userSelected={userSelected} |
|
||||
roleData={resource} |
|
||||
userRole={userResource} |
|
||||
setResCode={setResCode} |
|
||||
userType={userType} |
|
||||
/> |
|
||||
<Row type="flex" justify="center" style={{ marginBottom: 16, marginTop: 16, textAlign: 'center' }}> |
|
||||
<Col span="24"> |
|
||||
<Button |
|
||||
disabled={userSelected === "SuperAdmin" || userType === 4} |
|
||||
onClick={handleSave} |
|
||||
style={{ width: '60%' }} |
|
||||
type='primary'>保存修改</Button> |
|
||||
</Col></Row> |
|
||||
</Card> |
|
||||
: <Empty /> |
|
||||
} |
|
||||
</Spin> |
|
||||
</div> |
|
||||
) |
|
||||
} |
|
||||
|
|
||||
function mapStateToProps(state) { |
|
||||
const { userResource, resource, depMessage, depUser, global } = state; |
|
||||
return { |
|
||||
clientHeight: global.clientHeight, |
|
||||
loading: depMessage.isRequesting || depUser.isRequesting || resource.isRequesting, |
|
||||
userResource: userResource.data || [], |
|
||||
resource: resource.data || [], |
|
||||
depMessage: depMessage.data || [], |
|
||||
depUser: depUser.data || [] |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
export default connect(mapStateToProps)(Authority); |
|
@ -1,49 +0,0 @@ |
|||||
.main { |
|
||||
width: 100%; |
|
||||
background: #fff; |
|
||||
padding: 10px 16px; |
|
||||
|
|
||||
.title { |
|
||||
display: inline-block; |
|
||||
|
|
||||
.line { |
|
||||
display: inline-block; |
|
||||
width: 3px; |
|
||||
height: 20px; |
|
||||
background: #006BE3; |
|
||||
} |
|
||||
|
|
||||
.cn { |
|
||||
font-family: YouSheBiaoTiHei; |
|
||||
font-size: 24px; |
|
||||
color: #101531; |
|
||||
margin-left: 11px; |
|
||||
} |
|
||||
|
|
||||
.en { |
|
||||
font-family: D-DINExp-Italic; |
|
||||
font-weight: Italic; |
|
||||
font-size: 12px; |
|
||||
color: #969799; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.tree-box { |
|
||||
display: flex; |
|
||||
width: 100%; |
|
||||
|
|
||||
.user-list { |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
margin-left: 100px; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.list-title { |
|
||||
font-family: PingFangSC-Medium; |
|
||||
font-weight: 600; |
|
||||
font-size: 16px; |
|
||||
color: #000000d9; |
|
||||
margin-left: 15px; |
|
||||
} |
|
||||
} |
|
@ -1,6 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
import Authority from './authority'; |
|
||||
import UserManage from './user'; |
|
||||
|
|
||||
export { Authority, UserManage }; |
|
@ -1,355 +0,0 @@ |
|||||
import React, { useEffect, useState } from 'react'; |
|
||||
import { connect } from 'react-redux'; |
|
||||
import { FormOutlined, DeleteOutlined } from '@ant-design/icons'; |
|
||||
import { Spin, Tooltip, Button, Popconfirm, Row, Col, Tree, Card, Switch } from 'antd'; |
|
||||
import ProTable from '@ant-design/pro-table'; |
|
||||
import { getDepMessage, getDepUser, createUser, updateUser, delUser, resetPwd, createDept, updateDept, delDept } from '../actions/user'; |
|
||||
import UserModal from '../components/userModal'; |
|
||||
import ResetPwd from '../components/resetPwd'; |
|
||||
import DeptModal from '../components/deptModal'; |
|
||||
import './user.less'; |
|
||||
|
|
||||
const TreeNode = Tree.TreeNode; |
|
||||
|
|
||||
const UserManage = (props) => { |
|
||||
const user = JSON.parse(sessionStorage.getItem('user')); |
|
||||
const [tableList, settableList] = useState([]) |
|
||||
const { dispatch, loading, depMessage, depUser, clientHeight, actions } = props; |
|
||||
// 部门
|
|
||||
const [deptModalVisible, setDeptModalVisible] = useState(false); |
|
||||
const [deptModalType, setDeptModalType] = useState(); |
|
||||
const [deptModalRecord, setDeptModalRecord] = useState(); |
|
||||
const { projectRegime } = actions |
|
||||
// 成员
|
|
||||
const [modalVisible, setModalVisible] = useState(false); |
|
||||
const [modalType, setModalType] = useState(); |
|
||||
const [modalRecord, setModalRecord] = useState(); |
|
||||
const [pwdModalVisible, setPwdModalVisible] = useState(false); |
|
||||
const [depSelectedKeys, setDepSelectedKeys] = useState([]) |
|
||||
const [rowSelected, setRowSelected] = useState([]) |
|
||||
|
|
||||
useEffect(() => { |
|
||||
dispatch(getDepMessage()) |
|
||||
projectList() |
|
||||
}, []) |
|
||||
|
|
||||
const projectList = (obj) => { |
|
||||
|
|
||||
dispatch(projectRegime.getProjectList()).then(res => { |
|
||||
// console.log(res)
|
|
||||
if (res.success) { |
|
||||
settableList(res.payload.data?.rows) |
|
||||
// setLimits(res.payload.data?.count)
|
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
useEffect(() => { |
|
||||
if (depMessage.length) { |
|
||||
setDepSelectedKeys([depMessage[0].id]) |
|
||||
dispatch(getDepUser(depMessage[0].id)) |
|
||||
} |
|
||||
}, [depMessage]) |
|
||||
|
|
||||
const columns = [ |
|
||||
{ |
|
||||
title: '姓名', |
|
||||
dataIndex: 'name', |
|
||||
}, { |
|
||||
title: '用户名(手机号)', |
|
||||
dataIndex: 'username', |
|
||||
}, |
|
||||
{ |
|
||||
title: '职位', |
|
||||
dataIndex: 'post', |
|
||||
}, { |
|
||||
title: '邮箱', |
|
||||
dataIndex: 'email', |
|
||||
}, { |
|
||||
title: '启用状态', |
|
||||
dataIndex: 'enable', |
|
||||
render: (_, r) => { |
|
||||
return <Switch checkedChildren="启用" unCheckedChildren="禁用" disabled defaultChecked={r.enable} /> |
|
||||
} |
|
||||
}, { |
|
||||
title: '操作', |
|
||||
dataIndex: 'action', |
|
||||
render: (dom, record) => { |
|
||||
|
|
||||
return record.username == 'SuperAdmin' ? '' : [ |
|
||||
<Button type="link" onClick={() => { openModal('edit', record) }}>编辑</Button>, |
|
||||
<Popconfirm |
|
||||
title="确认删除?" |
|
||||
onConfirm={() => { |
|
||||
delUsers([record.id]) |
|
||||
}} |
|
||||
> |
|
||||
<Button type="link">删除</Button> |
|
||||
</Popconfirm>, |
|
||||
<Button |
|
||||
type="link" |
|
||||
onClick={() => { |
|
||||
setModalRecord(record); |
|
||||
setPwdModalVisible(true); |
|
||||
}} |
|
||||
>重置密码</Button> |
|
||||
] |
|
||||
}, |
|
||||
}, |
|
||||
]; |
|
||||
|
|
||||
//弹窗确认
|
|
||||
const onConfirm = (values) => { |
|
||||
if (modalType == 'edit') { |
|
||||
dispatch(updateUser(modalRecord.id, values.contract)).then(res => { |
|
||||
if (res.success) { |
|
||||
setModalVisible(false); |
|
||||
dispatch(getDepUser(depSelectedKeys[0])); |
|
||||
} |
|
||||
}); |
|
||||
} else { |
|
||||
dispatch(createUser(values.contract)).then(res => { |
|
||||
if (res.success) { |
|
||||
setModalVisible(false); |
|
||||
dispatch(getDepUser(depSelectedKeys[0])); |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
//打开弹窗
|
|
||||
const openModal = (type, record) => { |
|
||||
setModalVisible(true); |
|
||||
setModalType(type); |
|
||||
if (type == 'edit') { |
|
||||
setModalRecord(record); |
|
||||
} else { |
|
||||
setModalRecord(null); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
//删除用户
|
|
||||
const delUsers = (ids, type) => { |
|
||||
dispatch(delUser(ids)).then(res => { |
|
||||
dispatch(getDepUser(depSelectedKeys[0])); |
|
||||
if (type == 'batch') { |
|
||||
setRowSelected([]); |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
//重置密码
|
|
||||
const onPwdConfirm = (values) => { |
|
||||
dispatch(resetPwd(modalRecord.id, { password: values.password })).then(res => { |
|
||||
if (res.success) { |
|
||||
setPwdModalVisible(false); |
|
||||
dispatch(getDepUser(depSelectedKeys[0])); |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
const openDeptModal = (type, record) => { |
|
||||
console.log(type, record, 'type, record') |
|
||||
|
|
||||
setDeptModalVisible(true); |
|
||||
setDeptModalType(type); |
|
||||
if (type === 'edit') { |
|
||||
setDeptModalRecord(record); |
|
||||
} else { |
|
||||
setDeptModalRecord(null); |
|
||||
} |
|
||||
} |
|
||||
const onDeptConfirm = (values) => { |
|
||||
if (deptModalType === 'edit') { |
|
||||
dispatch(updateDept(deptModalRecord.id, values.contract)).then(res => { |
|
||||
if (res.success) { |
|
||||
setDeptModalVisible(false); |
|
||||
dispatch(getDepMessage()) |
|
||||
} |
|
||||
}); |
|
||||
} else { |
|
||||
dispatch(createDept(values.contract)).then(res => { |
|
||||
if (res.success) { |
|
||||
setDeptModalVisible(false); |
|
||||
dispatch(getDepMessage()) |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
const delDepartment = (id) => { |
|
||||
dispatch(delDept(id)).then(res => { |
|
||||
if (res.success) { |
|
||||
dispatch(getDepMessage()) |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
const renderTree = (item, id) => { |
|
||||
// let cannotDel = item.users.length || item.subordinate?.filter(is => is.users.length).length;//自己下面有成员 或者下级部门下有成员 不能删除
|
|
||||
return <div style={{ display: 'flex', width: '10vw', justifyContent: 'space-between' }}> |
|
||||
<Tooltip title={item.name}> |
|
||||
<div style={{ width: '80%', textOverflow: 'ellipsis', whiteSpace: 'nowrap', overflow: 'hidden' }}>{item.name}</div> |
|
||||
</Tooltip> |
|
||||
<div style={{ width: '20%' }} > |
|
||||
{ |
|
||||
depSelectedKeys == id && user.username === "SuperAdmin" ? |
|
||||
<> |
|
||||
<FormOutlined onClick={() => { |
|
||||
setDeptModalRecord(item) |
|
||||
setDeptModalVisible(true) |
|
||||
setDeptModalType('edit') |
|
||||
}} /> |
|
||||
{ |
|
||||
<Popconfirm title='是否确认删除?' onConfirm={() => { delDepartment(id) }}> |
|
||||
<DeleteOutlined style={{ marginLeft: 5 }} /> |
|
||||
</Popconfirm> |
|
||||
} |
|
||||
</> : null |
|
||||
} |
|
||||
</div> |
|
||||
</div> |
|
||||
} |
|
||||
|
|
||||
return (<> |
|
||||
<Spin spinning={loading} style={{ height: clientHeight }}> |
|
||||
<div className='dep-box'> |
|
||||
<div className='top'> |
|
||||
<div className='title'> |
|
||||
<span className='line'></span> |
|
||||
<span className='cn'>部门</span> |
|
||||
<span className='en'> DEPARTMENT</span> |
|
||||
</div> |
|
||||
{ |
|
||||
user.username === "SuperAdmin" && <Button |
|
||||
type="primary" |
|
||||
key="primary" |
|
||||
onClick={() => openDeptModal('create')} |
|
||||
>新建部门</Button> |
|
||||
} |
|
||||
</div> |
|
||||
{ |
|
||||
depMessage.length ? |
|
||||
<Tree |
|
||||
style={{ width: 272 }} |
|
||||
height={150} |
|
||||
defaultExpandedKeys={[depMessage[0].id]} |
|
||||
selectedKeys={depSelectedKeys} |
|
||||
onSelect={(selectedKeys, e) => { |
|
||||
if (e.selected) { |
|
||||
setDepSelectedKeys(selectedKeys) |
|
||||
dispatch(getDepUser(selectedKeys[0])) |
|
||||
} |
|
||||
}} |
|
||||
// treeData={depMessage}
|
|
||||
// fieldNames={{
|
|
||||
// title: 'name',
|
|
||||
// key: 'id',
|
|
||||
// children: 'subordinate'
|
|
||||
// }}
|
|
||||
> |
|
||||
{ |
|
||||
depMessage.map((s, index) => { |
|
||||
return <TreeNode title={renderTree(s, s.id)} key={s.id} > |
|
||||
{ |
|
||||
s.subordinate.map(k => { |
|
||||
return <TreeNode title={renderTree(k, k.id)} key={k.id} onMouseOver={() => { setIShowIcon(k.id) }} onMouseOut={() => { setIShowIcon(null) }}> |
|
||||
</TreeNode> |
|
||||
}) |
|
||||
} |
|
||||
</TreeNode> |
|
||||
}) |
|
||||
} |
|
||||
</Tree> : '' |
|
||||
} |
|
||||
</div> |
|
||||
<div className='user-box'> |
|
||||
<div className='top' style={{ marginBottom: 19 }}> |
|
||||
<div className='title'> |
|
||||
<span className='line'></span> |
|
||||
<span className='cn'>用户</span> |
|
||||
<span className='en'> USER</span> |
|
||||
</div> |
|
||||
<div> |
|
||||
<Button |
|
||||
type="primary" |
|
||||
key="primary" |
|
||||
style={{ marginRight: 10 }} |
|
||||
onClick={() => openModal('create')} |
|
||||
>新建用户</Button> |
|
||||
<Button style={{ marginRight: 10 }} onClick={() => { dispatch(getDepUser(depSelectedKeys[0])); }}>刷新</Button> |
|
||||
<Popconfirm title="确认删除?" onConfirm={() => { delUsers(rowSelected, 'batch') }}> |
|
||||
<Button>批量删除</Button> |
|
||||
</Popconfirm> |
|
||||
</div> |
|
||||
</div> |
|
||||
<ProTable |
|
||||
columns={columns} |
|
||||
dataSource={depUser} |
|
||||
style={{ width: "100% ", height: clientHeight - 371, overflow: "auto" }} |
|
||||
rowSelection={{ |
|
||||
selectedRowKeys: rowSelected, |
|
||||
onChange: (selectedRowKeys) => { |
|
||||
setRowSelected(selectedRowKeys); |
|
||||
|
|
||||
}, |
|
||||
getCheckboxProps: (record) => { |
|
||||
return { |
|
||||
disabled: record.username === 'SuperAdmin', |
|
||||
} |
|
||||
}, |
|
||||
}} |
|
||||
options={false} |
|
||||
search={false} |
|
||||
rowKey="id" |
|
||||
rowClassName={(record, index) => { |
|
||||
let className = 'global-light-row'; |
|
||||
if (index % 2 === 1) className = 'global-dark-row'; |
|
||||
return className; |
|
||||
}} |
|
||||
pagination={{ size: 'default', className: 'global-pagination' }} |
|
||||
/> |
|
||||
</div> |
|
||||
{ |
|
||||
deptModalVisible ? |
|
||||
<DeptModal |
|
||||
visible={deptModalVisible} |
|
||||
onVisibleChange={setDeptModalVisible} |
|
||||
modalType={deptModalType} |
|
||||
onConfirm={onDeptConfirm} |
|
||||
editData={deptModalRecord} |
|
||||
depts={depMessage} |
|
||||
/> |
|
||||
: '' |
|
||||
} |
|
||||
{ |
|
||||
depMessage.length && modalVisible ? |
|
||||
<UserModal |
|
||||
visible={modalVisible} |
|
||||
onVisibleChange={setModalVisible} |
|
||||
modalType={modalType} |
|
||||
onConfirm={onConfirm} |
|
||||
editData={{ ...modalRecord, structure: modalRecord?.structure || [] }} |
|
||||
tableList={tableList} |
|
||||
/> |
|
||||
: '' |
|
||||
} |
|
||||
{pwdModalVisible ? <ResetPwd visible={pwdModalVisible} |
|
||||
onVisibleChange={setPwdModalVisible} |
|
||||
onConfirm={onPwdConfirm} /> : ''} |
|
||||
</Spin> |
|
||||
</>) |
|
||||
} |
|
||||
|
|
||||
function mapStateToProps(state) { |
|
||||
const { depMessage, depUser, global } = state; |
|
||||
return { |
|
||||
clientHeight: global.clientHeight, |
|
||||
loading: depMessage.isRequesting, |
|
||||
depMessage: depMessage.data || [], |
|
||||
depUser: depUser.data || [], |
|
||||
actions: global.actions |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
export default connect(mapStateToProps)(UserManage); |
|
@ -1,42 +0,0 @@ |
|||||
.dep-box { |
|
||||
height: 213px; |
|
||||
background: #fff; |
|
||||
padding: 10px 16px; |
|
||||
margin-bottom: 20px; |
|
||||
} |
|
||||
|
|
||||
.user-box { |
|
||||
background: #fff; |
|
||||
padding: 10px 16px; |
|
||||
} |
|
||||
|
|
||||
.top { |
|
||||
display: flex; |
|
||||
justify-content: space-between; |
|
||||
|
|
||||
.title { |
|
||||
background-color: #fff; |
|
||||
display: inline-block; |
|
||||
|
|
||||
.line { |
|
||||
display: inline-block; |
|
||||
width: 3px; |
|
||||
height: 20px; |
|
||||
background: #006BE3; |
|
||||
} |
|
||||
|
|
||||
.cn { |
|
||||
font-family: YouSheBiaoTiHei; |
|
||||
font-size: 24px; |
|
||||
color: #101531; |
|
||||
margin-left: 11px; |
|
||||
} |
|
||||
|
|
||||
.en { |
|
||||
font-family: D-DINExp-Italic; |
|
||||
font-weight: Italic; |
|
||||
font-size: 12px; |
|
||||
color: #969799; |
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -1,15 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
import reducers from './reducers'; |
|
||||
import routes from './routes'; |
|
||||
import actions from './actions'; |
|
||||
import { getNavItem } from './nav-item'; |
|
||||
|
|
||||
export default { |
|
||||
key: 'organization', |
|
||||
name: '', |
|
||||
reducers: reducers, |
|
||||
routes: routes, |
|
||||
actions: actions, |
|
||||
getNavItem: getNavItem |
|
||||
}; |
|
@ -1,22 +0,0 @@ |
|||||
import React from 'react'; |
|
||||
import { Link } from 'react-router-dom'; |
|
||||
import { Menu } from 'antd'; |
|
||||
import { FormatPainterOutlined } from '@ant-design/icons'; |
|
||||
import { Func } from '$utils'; |
|
||||
const SubMenu = Menu.SubMenu; |
|
||||
|
|
||||
export function getNavItem(user, dispatch) { |
|
||||
// if (!Func.isAuthorized("ORG_MANAGE")) {
|
|
||||
// return null
|
|
||||
// }
|
|
||||
return ( |
|
||||
Func.isAuthorized('ORG_MANAGE') && <SubMenu key="organization" icon={<img src='/assets/images/menu/org.svg' style={{ width: 24, height: 24 }} />} title={'组织管理'}> |
|
||||
{Func.isAuthorized('USER_CONFIG') && <Menu.Item key="userManage"> |
|
||||
<Link to="/organization/user">部门成员</Link> |
|
||||
</Menu.Item>} |
|
||||
{Func.isAuthorized('AUTH_CONFIG') && <Menu.Item key="authority"> |
|
||||
<Link to="/organization/authority">权限配置</Link> |
|
||||
</Menu.Item>} |
|
||||
</SubMenu> |
|
||||
); |
|
||||
} |
|
@ -1,5 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
export default { |
|
||||
|
|
||||
}; |
|
@ -1,26 +0,0 @@ |
|||||
'use strict'; |
|
||||
import { UserManage, Authority } from './containers'; |
|
||||
|
|
||||
export default [{ |
|
||||
type: 'inner', |
|
||||
route: { |
|
||||
path: '/organization', |
|
||||
key: 'organization', |
|
||||
breadcrumb: '组织管理', |
|
||||
menuSelectKeys: ['userManage'], |
|
||||
menuOpenKeys: ['organization'], |
|
||||
childRoutes: [{ |
|
||||
path: '/user', |
|
||||
key: 'userManage', |
|
||||
menuSelectKeys: ['userManage'], |
|
||||
component: UserManage, |
|
||||
breadcrumb: '部门成员', |
|
||||
}, { |
|
||||
path: '/authority', |
|
||||
key: 'authority', |
|
||||
component: Authority, |
|
||||
menuSelectKeys: ['authority'], |
|
||||
breadcrumb: '权限配置', |
|
||||
}] |
|
||||
} |
|
||||
}]; |
|
@ -1,88 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
import { basicAction } from '@peace/utils' |
|
||||
import { ApiTable } from '$utils' |
|
||||
|
|
||||
export function getCheckItemsGroup() { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'get', |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'GET_CHECK_ITEMS_GROUP', |
|
||||
url: ApiTable.checkItemsGroup, |
|
||||
msg: { error: '获取检查项分组失败' }, |
|
||||
reducer:{name:'checkItemsGroup'} |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function createCheckItemsGroup(data) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'post', |
|
||||
data, |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'CREATE_CHECK_ITEMS_GROUP', |
|
||||
url: ApiTable.checkItemsGroup, |
|
||||
msg: { option: '创建检查项分组' }, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function delCheckItemsGroup(id) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'del', |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'DEL_CHECK_ITEMS_GROUP', |
|
||||
url: ApiTable.delCheckItemsGroup.replace('{id}', id), |
|
||||
msg: { option: '删除检查项分组' }, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function getCheckItems(query) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'get', |
|
||||
dispatch: dispatch, |
|
||||
query: query, |
|
||||
actionType: 'GET_CHECK_ITEMS', |
|
||||
url: ApiTable.checkItems, |
|
||||
msg: { error: '获取检查项失败' } |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function createCheckItems(data) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'post', |
|
||||
data, |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'CREATE_CHECK_ITEMS', |
|
||||
url: ApiTable.checkItems, |
|
||||
msg: { option: '新建检查项' }, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function updateCheckItems(id, data) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'put', |
|
||||
data, |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'UPDATE_CHECK_ITEMS', |
|
||||
url: ApiTable.updateCheckItems.replace('{id}', id), |
|
||||
msg: { option: '修改检查项' }, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function delCheckItems(ids) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'del', |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'DEL_CHECK_ITEMS', |
|
||||
url: ApiTable.delCheckItems.replace('{ids}', ids), |
|
||||
msg: { option: '删除检查项' }, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export default { |
|
||||
getCheckItemsGroup, |
|
||||
createCheckItemsGroup, |
|
||||
getCheckItems, |
|
||||
createCheckItems, |
|
||||
updateCheckItems, |
|
||||
delCheckItems, |
|
||||
} |
|
@ -1,18 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
import * as plan from './plan' |
|
||||
import * as record from './record' |
|
||||
import * as report from './report' |
|
||||
import * as template from './template' |
|
||||
import * as checkItems from './checkItems' |
|
||||
import * as yujingguanli from './yujingguanli' |
|
||||
import * as reportConf from './reportConf' |
|
||||
export default { |
|
||||
...plan, |
|
||||
...record, |
|
||||
...report, |
|
||||
...template, |
|
||||
...checkItems, |
|
||||
...yujingguanli, |
|
||||
...reportConf |
|
||||
} |
|
@ -1,81 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
import { basicAction } from '@peace/utils' |
|
||||
import { ApiTable } from '$utils' |
|
||||
|
|
||||
export function getPatrolPlan(query) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'get', |
|
||||
query, |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'GET_PATROL_PLAN', |
|
||||
url: ApiTable.patrolPlan, |
|
||||
msg: { error: '获取巡检计划失败' }, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function createPatrolPlan(data) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'post', |
|
||||
data, |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'CREATE_PATROL_PLAN', |
|
||||
url: ApiTable.patrolPlan, |
|
||||
msg: { error: '新增巡检计划失败' }, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function delPatrolPlan(id) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'del', |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'DEL_PATROL_PLAN', |
|
||||
url: ApiTable.delPatrolPlan.replace('{id}', id), |
|
||||
msg: { error: '删除巡检计划失败' }, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function updatePatrolPlan(data) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'put', |
|
||||
data, |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'UPDATE_PATROL_PLAN', |
|
||||
url: ApiTable.patrolPlan, |
|
||||
msg: { error: '修改巡检计划失败' }, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function getUserList() { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'get', |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'GET_USER_LIST', |
|
||||
url: ApiTable.getDepUser.replace('{depId}', null), |
|
||||
msg: { error: '获取人员列表失败' }, |
|
||||
reducer: { name: 'userList' } |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function getProjectList(query) { |
|
||||
return (dispatch) => basicAction({ |
|
||||
type: 'get', |
|
||||
query, |
|
||||
dispatch, |
|
||||
actionType: 'GET_PROJEECT_LIST', |
|
||||
url: ApiTable.getProjectList, |
|
||||
msg: { error: '获取结构物列表失败', }, |
|
||||
reducer: { name: 'structureList' } |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function positionList(query) { |
|
||||
return (dispatch) => basicAction({ |
|
||||
type: 'get', |
|
||||
query, |
|
||||
dispatch, |
|
||||
actionType: 'POSITION_LIST', |
|
||||
url: ApiTable.position, |
|
||||
msg: { error: '获取点位列表失败', }, |
|
||||
}); |
|
||||
} |
|
@ -1,17 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
import { basicAction } from '@peace/utils' |
|
||||
|
|
||||
export const GET_PATROL_RECORD_LIST = 'GET_PATROL_RECORD_LIST'; |
|
||||
export const GET_PATROL_RECORD_LIST_SUCCESS = 'GET_PATROL_RECORD_LIST_SUCCESS'; |
|
||||
export const GET_PATROL_RECORD_LIST_ERROR = 'GET_PATROL_RECORD_LIST_ERROR'; |
|
||||
export function records(url) { |
|
||||
return (dispatch) => basicAction({ |
|
||||
type: 'get', |
|
||||
dispatch, |
|
||||
actionType: GET_PATROL_RECORD_LIST, |
|
||||
url: url, |
|
||||
msg: { error: '获取巡检记录失败', }, |
|
||||
reducer: { name: 'record' } |
|
||||
}); |
|
||||
} |
|
@ -1,26 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
import { basicAction } from '@peace/utils' |
|
||||
import { ApiTable } from '$utils' |
|
||||
|
|
||||
export function getPatrolReport (query) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'get', |
|
||||
query, |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'GET_PATROL_REPORT', |
|
||||
url: ApiTable.patrolReport, |
|
||||
msg: { error: '获取巡检报告失败' }, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
export function delpatrolRecord (id) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'delete', |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'DEL_PATROL_RECORD', |
|
||||
url: ApiTable.delpatrolRecord.replace('{id}', id), |
|
||||
msg: { error: '删除巡检报告失败' }, |
|
||||
}) |
|
||||
} |
|
@ -1,55 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
import { basicAction } from '@peace/utils' |
|
||||
import { ApiTable } from '$utils' |
|
||||
|
|
||||
export function getReportList (query) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'get', |
|
||||
query, |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'GET_REPORT_LIST', |
|
||||
url: ApiTable.getReportList, |
|
||||
msg: { error: '获取报表配置列表失败' }, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
export function postReport (data = {}) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'post', |
|
||||
data, |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'POST_REPORT', |
|
||||
url: `${ApiTable.postReport}`, |
|
||||
msg: { option: data?.id ? '编辑报表生成规则' : "新增报表生成规则" }, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
export function delReport (id) {//删除报表文件
|
|
||||
return dispatch => basicAction({ |
|
||||
type: 'del', |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'DEL_REPORT', |
|
||||
url: `${ApiTable.delReport.replace('{id}', id)}`, |
|
||||
msg: { option: '删除报表规则' }, |
|
||||
|
|
||||
|
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function postGenerateReport (data = {}) { //生成报表
|
|
||||
return dispatch => basicAction({ |
|
||||
type: 'post', |
|
||||
data, |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'POST_GENERATE_REPORT', |
|
||||
url: `${ApiTable.generateReport}`, |
|
||||
msg: { option: "生成报表" }, |
|
||||
reducer: { |
|
||||
name: "generateReport", |
|
||||
params: { noClear: true } |
|
||||
} |
|
||||
}); |
|
||||
} |
|
@ -1,48 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
import { basicAction } from '@peace/utils' |
|
||||
import { ApiTable } from '$utils' |
|
||||
|
|
||||
export function getPatrolTemplate (query) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'get', |
|
||||
query, |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'GET_PATROL_TEMPLATE', |
|
||||
url: ApiTable.patrolTemplate, |
|
||||
msg: { error: '获取巡检模板失败' }, |
|
||||
reducer: { name: 'patrolTemplate' } |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function createPatrolTemplate (data) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'post', |
|
||||
data, |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'CREATE_PATROL_TEMPLATE', |
|
||||
url: ApiTable.patrolTemplate, |
|
||||
msg: { option: '新增巡检模板' }, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function delPatrolTemplate (id) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'del', |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'DEL_PATROL_TEMPLATE', |
|
||||
url: ApiTable.delPatrolTemplate.replace('{id}', id), |
|
||||
msg: { option: '删除巡检模板' }, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function updatePatrolTemplate (data) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'put', |
|
||||
data, |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'UPDATE_PATROL_TEMPLATE', |
|
||||
url: ApiTable.patrolTemplate, |
|
||||
msg: { option: '修改巡检模板' }, |
|
||||
}); |
|
||||
} |
|
@ -1,24 +0,0 @@ |
|||||
import { basicAction } from '@peace/utils' |
|
||||
import { ApiTable } from '$utils' |
|
||||
|
|
||||
export function putxinxi (data) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'post', |
|
||||
data, |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'PUT_XINXI', |
|
||||
url: ApiTable.yujingguanli, |
|
||||
msg: { option: '发送信息' }, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function modifyPatrolRecordIssueHandle(id, params, msg) { |
|
||||
return (dispatch) => basicAction({ |
|
||||
type: 'put', |
|
||||
data: params, |
|
||||
dispatch, |
|
||||
actionType: 'MODIFY_PatrolRecordIssueHandle_REPORT', |
|
||||
url: ApiTable.modifyPatrolRecordIssueHandle.replace('{id}', id), |
|
||||
msg: '', |
|
||||
}); |
|
||||
} |
|
@ -1,281 +0,0 @@ |
|||||
import { Button, Form, Input, Modal, Select, DatePicker,message } from 'antd' |
|
||||
import React, { useState, useEffect } from 'react' |
|
||||
import { connect } from 'react-redux' |
|
||||
import Uploads from '$components/Uploads' |
|
||||
const { RangePicker } = DatePicker |
|
||||
import moment from 'moment' |
|
||||
|
|
||||
const AddReportRulesModal = props => { |
|
||||
const [form] = Form.useForm() |
|
||||
const { user, visible, cancelHandle, actions, dispatch, onOk, modalData,typeList,structAll} = props |
|
||||
const [systemList, setSystemList] = useState([{ value: 1, label: '动力系统' },{ value: 2, label: '网络系统' }]) |
|
||||
const { patrolManage } = actions |
|
||||
const [type, setType] = useState(0) |
|
||||
const [system,setSystem]=useState(0)//system
|
|
||||
const [isShow, setIsShow] = useState(false) |
|
||||
const [structlist, setStructlist] = useState([])//结构物列表(只包括id和name)
|
|
||||
// const [startTime,setStartTime]=useState('')
|
|
||||
// const [endTime,setEndTime]=useState('')
|
|
||||
useEffect(()=>{ |
|
||||
if(modalData){ |
|
||||
setType(modalData.type) |
|
||||
} |
|
||||
},[modalData]) |
|
||||
const typeChange = e => { |
|
||||
setType(e) |
|
||||
form.setFieldValue('system', '') |
|
||||
form.setFieldValue('structure', undefined) |
|
||||
} |
|
||||
useEffect(()=>{ |
|
||||
if(type){ |
|
||||
if(type==1){ |
|
||||
const list = structAll.filter(v => v.type === '管廊')?.map(k => { |
|
||||
return { |
|
||||
value: k.id, |
|
||||
label: k.name |
|
||||
} |
|
||||
}) |
|
||||
setStructlist(list) |
|
||||
} |
|
||||
} |
|
||||
},[type]) |
|
||||
useEffect(()=>{ |
|
||||
//过滤管廊类型的数据
|
|
||||
const list = structAll.filter(v => v.type === '管廊')?.map(k => { |
|
||||
return { |
|
||||
value: k.id, |
|
||||
label: k.name |
|
||||
} |
|
||||
}) |
|
||||
setStructlist(list) |
|
||||
},[]) |
|
||||
|
|
||||
useEffect(() => { |
|
||||
// setPic(modalData?.reportpic)
|
|
||||
form.setFieldsValue({ |
|
||||
structure: null, |
|
||||
pic: null, |
|
||||
name: null, |
|
||||
type: null, |
|
||||
timeRange: null, |
|
||||
}) |
|
||||
form.setFieldsValue({ |
|
||||
structure: modalData?.structure, |
|
||||
name: modalData?.name, |
|
||||
type: modalData?.type, |
|
||||
system:modalData?.system, |
|
||||
pic: modalData?.reportpic?.map(item=>{return {storageUrl:item}}), |
|
||||
timeRange: modalData?.startTime ? [moment(modalData?.startTime), moment(modalData?.endTime)] : [], |
|
||||
}) |
|
||||
}, [visible]) |
|
||||
const timeChane = e => {} |
|
||||
const okHandler = () => { |
|
||||
form |
|
||||
.validateFields() |
|
||||
.then(values => { |
|
||||
if(values.pic?.length<4){ |
|
||||
message.warning(`最少选择4张图片`) |
|
||||
return |
|
||||
} |
|
||||
const params = { |
|
||||
id: modalData?.id, |
|
||||
name: values.name, |
|
||||
type: values.type, |
|
||||
system:values.system, |
|
||||
structure: Array.isArray(values.structure) ? [...values.structure] : [values.structure], |
|
||||
endTime: moment(values.timeRange[1]).endOf('day').format('YYYY-MM-DD HH:mm:ss'), |
|
||||
startTime: moment(values.timeRange[0]).startOf('day').format('YYYY-MM-DD HH:mm:ss'), |
|
||||
reportpic: values?.pic[0]?.name ? values?.pic.map(u => u.storageUrl) : modalData?.reportpic, |
|
||||
} |
|
||||
dispatch(patrolManage.postReport(params)).then(res => { |
|
||||
if (res.success) { |
|
||||
// form.resetFields()
|
|
||||
cancelHandle() |
|
||||
onOk() |
|
||||
setType(null) |
|
||||
} |
|
||||
}) |
|
||||
}) |
|
||||
.catch(info => { |
|
||||
console.log('Validate Failed:', info) |
|
||||
}) |
|
||||
} |
|
||||
//use
|
|
||||
// const structChange=(e)=>{
|
|
||||
// setStructObj(structAll.find(item=>item.id==e))
|
|
||||
// }
|
|
||||
// useEffect(()=>{
|
|
||||
// if(strcutObj){
|
|
||||
// if(strcutObj.subType.includes('供配电系统')||strcutObj.subType.includes('防雷')){
|
|
||||
// setSystemList([{ value: 1, label: '动力系统' }])
|
|
||||
// setIsShow(true)
|
|
||||
// }else if(strcutObj.subType.includes('指挥中心')||strcutObj.subType.includes('安防'))
|
|
||||
// setSystemList([{ value: 2, label: '网络系统' }])
|
|
||||
// setIsShow(true)
|
|
||||
// }
|
|
||||
|
|
||||
// },[strcutObj])
|
|
||||
|
|
||||
const systemChange=(e)=>{ |
|
||||
setSystem(e) |
|
||||
// setType(null)
|
|
||||
form.setFieldValue('structure', undefined) |
|
||||
if(e==1){ |
|
||||
const list=structAll.filter(v => v.type === '管廊')?.filter(item=>item.subType.includes('供配电系统')||item.subType.includes('防雷')) |
|
||||
if(list&&list.length){ |
|
||||
setStructlist( list?.map(item=>{ |
|
||||
return {value: item.id, |
|
||||
label: item.name} |
|
||||
})) |
|
||||
|
|
||||
}else{ |
|
||||
setStructlist([]) |
|
||||
} |
|
||||
}else if(e==2){ |
|
||||
const list=structAll.filter(v => v.type === '管廊')?.filter(item=>item.subType.includes('指挥中心')||item.subType.includes('安防')) |
|
||||
if(list&&list.length){ |
|
||||
setStructlist( list?.map(item=>{ |
|
||||
return {value: item.id, |
|
||||
label: item.name} |
|
||||
})) |
|
||||
|
|
||||
}else{ |
|
||||
setStructlist([]) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
} |
|
||||
console.log('reportpic',modalData?.reportpic) |
|
||||
return ( |
|
||||
<> |
|
||||
<Modal |
|
||||
destroyOnClose |
|
||||
title={modalData ? '编辑报表规则' : '新建报表规则'} |
|
||||
visible={visible} |
|
||||
onCancel={() => { |
|
||||
cancelHandle() |
|
||||
setIsShow(false) |
|
||||
setType(0) |
|
||||
form.setFieldsValue({ |
|
||||
structure: null, |
|
||||
pic: null, |
|
||||
name: null, |
|
||||
type: null, |
|
||||
timeRange: null, |
|
||||
}) |
|
||||
// form.resetFields()
|
|
||||
}} |
|
||||
onOk={okHandler}> |
|
||||
<Form |
|
||||
form={form} |
|
||||
labelCol={{ |
|
||||
span: 5, |
|
||||
}} |
|
||||
initialValues={ |
|
||||
{ |
|
||||
// structure:modalData?.structure,
|
|
||||
// pic:modalData?.reportpic,
|
|
||||
// name:modalData?.name,
|
|
||||
// type:modalData?.type,
|
|
||||
// timeRange:[moment(modalData?.startTime),moment(modalData?.endTime)]
|
|
||||
} |
|
||||
}> |
|
||||
<Form.Item label='报表名称' name='name' rules={[{ required: true, message: '请输入报表名称' }]}> |
|
||||
<Input /> |
|
||||
</Form.Item> |
|
||||
<Form.Item label='报表类型' name='type' rules={[{ required: true, message: '请选择报表类型' }]}> |
|
||||
<Select onChange={typeChange}> |
|
||||
{typeList?.map(g => { |
|
||||
return ( |
|
||||
<Option key={g.value} value={g.value} label={g.label}> |
|
||||
<div |
|
||||
style={{ |
|
||||
display: 'flex', |
|
||||
justifyContent: 'space-between', |
|
||||
}}> |
|
||||
{g.label} |
|
||||
</div> |
|
||||
</Option> |
|
||||
) |
|
||||
})} |
|
||||
</Select> |
|
||||
</Form.Item> |
|
||||
{type===2? |
|
||||
<Form.Item label='系统' name='system' rules={[{ required: true, message: '请选择系统' }]}> |
|
||||
<Select onChange={systemChange} > |
|
||||
{systemList?.map(g => { |
|
||||
return ( |
|
||||
<Option key={g.value} value={g.value} label={g.label}> |
|
||||
<div |
|
||||
style={{ |
|
||||
display: 'flex', |
|
||||
justifyContent: 'space-between', |
|
||||
}}> |
|
||||
{g.label} |
|
||||
</div> |
|
||||
</Option> |
|
||||
) |
|
||||
})} |
|
||||
</Select> |
|
||||
</Form.Item>:''} |
|
||||
<Form.Item label='关联结构物' name='structure' rules={[{ required: true, message: '请选择结构物' }]}> |
|
||||
<Select mode={type === 2 ? 'multiple' : undefined}> |
|
||||
{structlist?.map(g => { |
|
||||
return ( |
|
||||
<Option key={g.value} value={g.value} label={g.label}> |
|
||||
<div |
|
||||
style={{ |
|
||||
display: 'flex', |
|
||||
justifyContent: 'space-between', |
|
||||
}}> |
|
||||
{g.label} |
|
||||
</div> |
|
||||
</Option> |
|
||||
) |
|
||||
})} |
|
||||
</Select> |
|
||||
</Form.Item> |
|
||||
|
|
||||
<Form.Item label='生成时间' name='timeRange' rules={[{ required: true, message: '请选择时间' }]}> |
|
||||
<RangePicker onChange={timeChane} /> |
|
||||
</Form.Item> |
|
||||
<Form.Item label='发现问题上传:' name='pic' rules={[{ required: true, message: '请选择图片' }]}> |
|
||||
<Uploads |
|
||||
listType='picture-card' |
|
||||
uploadType='project' |
|
||||
maxFilesNum={15} |
|
||||
maxFileSize={10} |
|
||||
isQiniu={true} |
|
||||
// disabled={true}
|
|
||||
fileTypes={['png', 'jpg']} |
|
||||
fileList={modalData?.reportpic} |
|
||||
defaultValue={(() => { |
|
||||
let nextV = [] |
|
||||
for (let s of modalData?.reportpic || []) { |
|
||||
if (s) { |
|
||||
nextV.push({ |
|
||||
url: s, |
|
||||
storageUrl: s, |
|
||||
}) |
|
||||
} |
|
||||
} |
|
||||
return nextV |
|
||||
})()} |
|
||||
/> |
|
||||
</Form.Item> |
|
||||
</Form> |
|
||||
</Modal> |
|
||||
</> |
|
||||
) |
|
||||
} |
|
||||
|
|
||||
function mapStateToProps(state) { |
|
||||
const { auth, global } = state |
|
||||
return { |
|
||||
user: auth.user, |
|
||||
actions: global.actions, |
|
||||
} |
|
||||
} |
|
||||
export default connect(mapStateToProps)(AddReportRulesModal) |
|
@ -1,122 +0,0 @@ |
|||||
import { Button, Form, Input, Modal, Select } from 'antd'; |
|
||||
import { DeleteOutlined } from '@ant-design/icons'; |
|
||||
import React, { useState, useEffect } from 'react'; |
|
||||
import { connect } from 'react-redux'; |
|
||||
import { getCheckItemsGroup, delCheckItemsGroup } from '../actions/checkItems'; |
|
||||
const { Option } = Select; |
|
||||
|
|
||||
const CheckItemsModal = ({ visible, onOk, onCancel, curRecord, dispatch }) => { |
|
||||
const [group, setGroup] = useState([]); |
|
||||
const [isNewGroup, setIsNewGroup] = useState(false); |
|
||||
const [form] = Form.useForm(); |
|
||||
|
|
||||
useEffect(() => { |
|
||||
getGroup(); |
|
||||
}, []) |
|
||||
|
|
||||
function getGroup() { |
|
||||
dispatch(getCheckItemsGroup()).then(res => { |
|
||||
if (res.success) { |
|
||||
const opt = res.payload.data?.map(g => ({ value: g.id, label: g.name })); |
|
||||
setGroup(opt); |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
function delGroup(id, lastGroup) { |
|
||||
dispatch(delCheckItemsGroup(id)).then(res => { |
|
||||
if (res.success) { |
|
||||
form.setFieldValue('group', lastGroup === id ? null : lastGroup) |
|
||||
getGroup(); |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
return ( |
|
||||
<Modal |
|
||||
visible={visible} |
|
||||
title={curRecord ? "检查项修改" : "检查项添加"} |
|
||||
okText="确定" |
|
||||
cancelText="取消" |
|
||||
onCancel={() => { |
|
||||
form.resetFields(); |
|
||||
onCancel(); |
|
||||
}} |
|
||||
onOk={() => { |
|
||||
form |
|
||||
.validateFields() |
|
||||
.then((values) => { |
|
||||
form.resetFields(); |
|
||||
const params = { |
|
||||
...values, |
|
||||
isNewGroup |
|
||||
} |
|
||||
onOk(params); |
|
||||
}) |
|
||||
.catch((info) => { |
|
||||
console.log('Validate Failed:', info); |
|
||||
}); |
|
||||
}} |
|
||||
> |
|
||||
<Form |
|
||||
form={form} |
|
||||
layout="vertical" |
|
||||
name="form_in_modal" |
|
||||
initialValues={{ |
|
||||
...curRecord, |
|
||||
group: curRecord?.checkItemsGroup?.id |
|
||||
}} |
|
||||
> |
|
||||
<Form.Item |
|
||||
name="name" |
|
||||
label="检查项名称" |
|
||||
rules={[ |
|
||||
{ required: true, message: '请输入检查项名称' }, |
|
||||
]} |
|
||||
> |
|
||||
<Input /> |
|
||||
</Form.Item> |
|
||||
<Form.Item |
|
||||
name="group" |
|
||||
label="分组名称" |
|
||||
rules={[ |
|
||||
{ required: true, message: '请选择分组' }, |
|
||||
]} |
|
||||
> |
|
||||
{ |
|
||||
isNewGroup |
|
||||
? <Input /> |
|
||||
: <Select loading={!group?.length} optionLabelProp="label"> |
|
||||
{ |
|
||||
group?.map((g) => { |
|
||||
return <Option key={g.value} value={g.value} label={g.label}> |
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}> |
|
||||
{g.label} |
|
||||
<DeleteOutlined onClick={() => { delGroup(g.value, form.getFieldValue('group')) }} /> |
|
||||
</div> |
|
||||
</Option> |
|
||||
}) |
|
||||
} |
|
||||
</Select> |
|
||||
} |
|
||||
</Form.Item> |
|
||||
</Form> |
|
||||
<Button type='link' onClick={() => { |
|
||||
if (!isNewGroup) { |
|
||||
form.setFieldsValue({ group: null }) |
|
||||
} else { |
|
||||
form.setFieldsValue({ group: curRecord?.checkItemsGroup?.id }) |
|
||||
} |
|
||||
setIsNewGroup(!isNewGroup); |
|
||||
}}>{isNewGroup ? '选择已有' : '创建分组'}</Button> |
|
||||
</Modal > |
|
||||
); |
|
||||
}; |
|
||||
|
|
||||
function mapStateToProps(state) { |
|
||||
const { auth } = state |
|
||||
return { |
|
||||
user: auth.user, |
|
||||
} |
|
||||
} |
|
||||
export default connect(mapStateToProps)(CheckItemsModal); |
|
@ -1,263 +0,0 @@ |
|||||
import { Form, Input, Modal, Select, DatePicker } from 'antd'; |
|
||||
import { DownOutlined } from '@ant-design/icons'; |
|
||||
import React, { useState, useEffect } from 'react'; |
|
||||
import { connect } from 'react-redux'; |
|
||||
import { getUserList, getProjectList, positionList } from '../actions/plan'; |
|
||||
import moment from 'moment'; |
|
||||
|
|
||||
const { RangePicker } = DatePicker; |
|
||||
|
|
||||
const PlanModal = ({ visible, onCreate, onCancel, dispatch, userLoading, userList, structureList, struLoading, type, curRecord, templateLoading, patrolTemplate }) => { |
|
||||
const [userOpt, setUserOpt] = useState(); |
|
||||
const [struOpt, setStruOpt] = useState(); |
|
||||
const [pointOpt, setPointOpt] = useState(); |
|
||||
const [points, setPoints] = useState(); |
|
||||
const [unit, setUnit] = useState(curRecord?.frequency ? curRecord.frequency.substring(curRecord.frequency.length - 3, curRecord.frequency.length) : "次/天"); |
|
||||
const [form] = Form.useForm(); |
|
||||
|
|
||||
useEffect(() => { |
|
||||
if (type === 'view') { |
|
||||
|
|
||||
} else { |
|
||||
dispatch(getUserList()) |
|
||||
dispatch(getProjectList()) |
|
||||
} |
|
||||
if (type === 'edit' || type === 'view') { |
|
||||
dispatch(positionList({ projectId: curRecord?.project?.id })).then(res => { |
|
||||
if (res.success) { |
|
||||
setPoints(res.payload.data?.rows) |
|
||||
setPointOpt(res.payload.data?.rows[0]?.points?.map(p => ({ label: p.name, value: p.id }))) |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
}, []) |
|
||||
|
|
||||
useEffect(() => { |
|
||||
if (userList.length) { |
|
||||
setUserOpt(userList?.filter(f => f.structure?.includes(curRecord?.project?.id))?.map(u => ({ label: u.name, value: u.id }))) |
|
||||
// 如果巡检人员用户被删除,筛掉被删除的用户
|
|
||||
const userListIds = userList?.map(u => u.id); |
|
||||
const filterUsers = curRecord?.users?.filter(u => userListIds.includes(u.id)); |
|
||||
const nextUserIds = filterUsers?.map(u => u.id); |
|
||||
form.setFieldsValue({ |
|
||||
userIds: nextUserIds, |
|
||||
userDept: [...new Set(filterUsers?.map(u => u.department?.name))].join() |
|
||||
}); |
|
||||
} |
|
||||
}, [userList]) |
|
||||
|
|
||||
useEffect(() => { |
|
||||
if (structureList?.rows?.length) { |
|
||||
setStruOpt(structureList?.rows?.map(s => ({ label: s.name, value: s.id }))) |
|
||||
} |
|
||||
}, [structureList]) |
|
||||
|
|
||||
const selectAfter = ( |
|
||||
<Select |
|
||||
defaultValue={curRecord?.frequency ? curRecord.frequency.substring(curRecord.frequency.length - 3, curRecord.frequency.length) : "次/天"} |
|
||||
onChange={value => setUnit(value)} |
|
||||
suffixIcon={<DownOutlined style={{ color: '#fff' }} />} |
|
||||
> |
|
||||
<Option value="次/天">次/天</Option> |
|
||||
<Option value="次/周">次/周</Option> |
|
||||
<Option value="次/月">次/月</Option> |
|
||||
</Select> |
|
||||
); |
|
||||
return ( |
|
||||
<Modal |
|
||||
className="global-modal" |
|
||||
width={717} |
|
||||
visible={visible} |
|
||||
title={(type === 'view' ? '查看' : type === 'edit' ? '编辑' : '新增') + "巡检计划"} |
|
||||
okText="确定" |
|
||||
cancelText="取消" |
|
||||
onCancel={() => { |
|
||||
form.resetFields(); |
|
||||
onCancel(); |
|
||||
}} |
|
||||
onOk={() => { |
|
||||
if (type === 'view') { |
|
||||
form.resetFields(); |
|
||||
onCancel(); |
|
||||
return; |
|
||||
} |
|
||||
form |
|
||||
.validateFields() |
|
||||
.then((values) => { |
|
||||
form.resetFields(); |
|
||||
const params = { |
|
||||
...values, |
|
||||
frequency: values.frequency + unit, |
|
||||
startTime: values.time[0], |
|
||||
endTime: values.time[1], |
|
||||
points: points[0]?.points?.filter(p => values?.points?.includes(p.id)) |
|
||||
} |
|
||||
onCreate(params); |
|
||||
}) |
|
||||
.catch((info) => { |
|
||||
console.log('Validate Failed:', info); |
|
||||
}); |
|
||||
}} |
|
||||
> |
|
||||
<Form |
|
||||
form={form} |
|
||||
name="form_in_modal" |
|
||||
labelAlign='right' |
|
||||
labelCol={{ span: 4 }} wrapperCol={{ span: 18 }} |
|
||||
initialValues={{ |
|
||||
...curRecord, |
|
||||
time: [moment(curRecord?.startTime), moment(curRecord?.endTime)], |
|
||||
points: curRecord?.points?.map(p => p.id), |
|
||||
userIds: curRecord?.users?.map(u => u.id), |
|
||||
userDept: [...new Set(curRecord?.users?.map(u => u.department?.name))].join(), |
|
||||
frequency: curRecord?.frequency?.split('次')[0] |
|
||||
}} |
|
||||
disabled={type === 'view'} |
|
||||
> |
|
||||
<div style={{ position: 'relative', display: 'flex', justifyContent: 'space-between' }}> |
|
||||
<Form.Item |
|
||||
name="structureId" |
|
||||
label="结构物名称" |
|
||||
labelCol={{ span: 9 }} |
|
||||
style={{ width: 330 }} |
|
||||
rules={[ |
|
||||
{ required: true, message: '请选择结构物' }, |
|
||||
]} |
|
||||
> |
|
||||
<Select disabled={type === 'view'} bordered={false} options={struOpt} loading={struLoading} onChange={(projectId) => { |
|
||||
dispatch(positionList({ projectId })).then(res => { |
|
||||
if (res.success) { |
|
||||
setPoints(res.payload.data?.rows) |
|
||||
setPointOpt(res.payload.data?.rows[0]?.points?.map(p => ({ label: p.name, value: p.id }))) |
|
||||
} |
|
||||
}) |
|
||||
form.setFieldsValue({ userIds: [], userDept: [] }); |
|
||||
setUserOpt(userList?.filter(f => f.structure?.includes(projectId))?.map(u => ({ label: u.name, value: u.id }))) |
|
||||
}} /> |
|
||||
</Form.Item> |
|
||||
<Form.Item |
|
||||
name="name" |
|
||||
label="巡检任务名称" |
|
||||
labelCol={{ span: 9 }} |
|
||||
style={{ width: 330 }} |
|
||||
rules={[ |
|
||||
{ required: true, message: '请输入巡检任务名称' }, |
|
||||
]} |
|
||||
> |
|
||||
<Input disabled={type === 'view'} bordered={false} /> |
|
||||
</Form.Item> |
|
||||
</div> |
|
||||
<div style={{ position: 'relative', display: 'flex', justifyContent: 'space-between' }}> |
|
||||
<Form.Item |
|
||||
name="way" |
|
||||
label="巡检方式" |
|
||||
labelCol={{ span: 8 }} |
|
||||
style={{ width: 330 }} |
|
||||
rules={[ |
|
||||
{ required: true, message: '请选择巡检方式' }, |
|
||||
]} |
|
||||
initialValue='周期巡检' |
|
||||
> |
|
||||
<Select bordered={false} options={[{ |
|
||||
label: '周期巡检', |
|
||||
value: '周期巡检' |
|
||||
}]} disabled /> |
|
||||
</Form.Item> |
|
||||
<Form.Item |
|
||||
name="frequency" |
|
||||
label="巡检频次" |
|
||||
labelCol={{ span: 8 }} |
|
||||
style={{ width: 330 }} |
|
||||
rules={[ |
|
||||
{ required: true, message: '请选择巡检频次' }, |
|
||||
]} |
|
||||
> |
|
||||
<Input addonAfter={selectAfter} disabled={type === 'view'} bordered={false} /> |
|
||||
</Form.Item> |
|
||||
</div> |
|
||||
<div style={{ position: 'relative', display: 'flex', justifyContent: 'space-between' }}> |
|
||||
<Form.Item |
|
||||
name="templateId" |
|
||||
label="巡检模板" |
|
||||
labelCol={{ span: 8 }} |
|
||||
style={{ width: 330 }} |
|
||||
rules={[ |
|
||||
{ required: true, message: '请选择巡检模板' }, |
|
||||
]} |
|
||||
> |
|
||||
<Select |
|
||||
bordered={false} |
|
||||
disabled={type === 'view'} |
|
||||
options={patrolTemplate.map(t => { |
|
||||
return { label: t.name, value: t.id } |
|
||||
})} |
|
||||
loading={templateLoading} |
|
||||
/> |
|
||||
</Form.Item> |
|
||||
<Form.Item |
|
||||
name="time" |
|
||||
label="任务周期" |
|
||||
labelCol={{ span: 8 }} |
|
||||
style={{ width: 330 }} |
|
||||
rules={[ |
|
||||
{ required: true, message: '请选择任务周期' }, |
|
||||
]} |
|
||||
> |
|
||||
<RangePicker disabled={type === 'view'} bordered={false} /> |
|
||||
</Form.Item> |
|
||||
</div> |
|
||||
<div style={{ position: 'relative', display: 'flex', justifyContent: 'space-between' }}> |
|
||||
<Form.Item |
|
||||
name="points" |
|
||||
label="巡检点" |
|
||||
labelCol={{ span: 8 }} |
|
||||
style={{ width: 330 }} |
|
||||
rules={[ |
|
||||
{ required: true, message: '请选择巡检点' }, |
|
||||
]} |
|
||||
> |
|
||||
<Select mode="multiple" options={pointOpt} disabled={!pointOpt || type === 'view'} bordered={false} showSearch |
|
||||
filterOption={(input, option) => (option?.label ?? '').toLowerCase().includes(input.toLowerCase())} |
|
||||
/> |
|
||||
</Form.Item> |
|
||||
<Form.Item |
|
||||
name="userIds" |
|
||||
label="巡检人员" |
|
||||
labelCol={{ span: 8 }} |
|
||||
style={{ width: 330 }} |
|
||||
rules={[ |
|
||||
{ required: true, message: '请选择巡检人员' }, |
|
||||
]} |
|
||||
> |
|
||||
<Select mode="multiple" disabled={type === 'view'} bordered={false} options={userOpt} loading={userLoading} onChange={(values) => { |
|
||||
const selectUser = userList?.filter(u => values?.includes(u.id)) |
|
||||
form.setFieldsValue({ |
|
||||
userDept: [...new Set(selectUser?.map(u => u.department.name))].join() |
|
||||
}); |
|
||||
}} /> |
|
||||
</Form.Item> |
|
||||
</div> |
|
||||
<Form.Item |
|
||||
name="userDept" |
|
||||
label="巡检单位" |
|
||||
> |
|
||||
<Input disabled bordered={false} /> |
|
||||
</Form.Item> |
|
||||
</Form> |
|
||||
</Modal > |
|
||||
); |
|
||||
}; |
|
||||
|
|
||||
function mapStateToProps(state) { |
|
||||
const { auth, userList, structureList, patrolTemplate } = state |
|
||||
return { |
|
||||
user: auth.user, |
|
||||
userList: userList.data || [], |
|
||||
structureList: structureList.data || [], |
|
||||
patrolTemplate: (patrolTemplate.data || { rows: [] }).rows, |
|
||||
userLoading: userList.isRequesting, |
|
||||
struLoading: structureList.isRequesting, |
|
||||
templateLoading: patrolTemplate.isRequesting, |
|
||||
} |
|
||||
} |
|
||||
export default connect(mapStateToProps)(PlanModal); |
|
@ -1,122 +0,0 @@ |
|||||
import { Button, Form, Input, Modal, Select, DatePicker } from 'antd'; |
|
||||
import React, { useState, useEffect } from 'react'; |
|
||||
import { connect } from 'react-redux'; |
|
||||
import { createPatrolTemplate, delPatrolTemplate, updatePatrolTemplate, getPatrolTemplate } from '../actions/template'; |
|
||||
import moment from 'moment'; |
|
||||
|
|
||||
const { RangePicker } = DatePicker; |
|
||||
const { TextArea } = Input; |
|
||||
|
|
||||
const PlanModal = ({ visible, onCancel, dispatch, type, curRecord, tableRef, checkItemsGroup }) => { |
|
||||
const [form] = Form.useForm(); |
|
||||
|
|
||||
return ( |
|
||||
<Modal |
|
||||
visible={visible} |
|
||||
title="新增巡检模板" |
|
||||
okText="确定" |
|
||||
cancelText="取消" |
|
||||
onCancel={() => { |
|
||||
form.resetFields(); |
|
||||
onCancel(); |
|
||||
}} |
|
||||
onOk={() => { |
|
||||
form |
|
||||
.validateFields() |
|
||||
.then((values) => { |
|
||||
|
|
||||
const params = { |
|
||||
...values, |
|
||||
} |
|
||||
|
|
||||
if (type === 'create') { |
|
||||
dispatch(createPatrolTemplate(params)).then(res => { |
|
||||
if (res.success) { |
|
||||
tableRef.current.reload(); |
|
||||
form.resetFields(); |
|
||||
onCancel(); |
|
||||
} |
|
||||
}) |
|
||||
} else { |
|
||||
dispatch(updatePatrolTemplate({ |
|
||||
...params, |
|
||||
id: curRecord.id |
|
||||
})).then(res => { |
|
||||
if (res.success) { |
|
||||
tableRef.current.reload(); |
|
||||
form.resetFields(); |
|
||||
onCancel(); |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
}) |
|
||||
.catch((info) => { |
|
||||
console.log('Validate Failed:', info); |
|
||||
}); |
|
||||
}} |
|
||||
> |
|
||||
<Form |
|
||||
form={form} |
|
||||
layout="vertical" |
|
||||
name="form_in_modal" |
|
||||
initialValues={{ |
|
||||
...curRecord, |
|
||||
checkItems: curRecord?.checkItems?.map(c => c.id) |
|
||||
}} |
|
||||
> |
|
||||
<Form.Item |
|
||||
name="name" |
|
||||
label="模板名称" |
|
||||
rules={[ |
|
||||
{ required: true, message: '请输入巡检模板名称' }, |
|
||||
]} |
|
||||
> |
|
||||
<Input /> |
|
||||
</Form.Item> |
|
||||
<Form.Item |
|
||||
name="describe" |
|
||||
label="描述" |
|
||||
rules={[]} |
|
||||
> |
|
||||
<TextArea rows={4} /> |
|
||||
</Form.Item> |
|
||||
<Form.Item |
|
||||
name="checkItems" |
|
||||
label="检查项" |
|
||||
rules={[ |
|
||||
{ required: true, message: '请选择检查项' }, |
|
||||
]} |
|
||||
> |
|
||||
<Select |
|
||||
style={{ |
|
||||
// width: 200,
|
|
||||
}} |
|
||||
mode="multiple" |
|
||||
options={ |
|
||||
checkItemsGroup.map(g => { |
|
||||
return { |
|
||||
label: g.name, |
|
||||
options: g.checkItems.map(c => { |
|
||||
return { |
|
||||
label: c.name, |
|
||||
value: c.id, |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
/> |
|
||||
</Form.Item> |
|
||||
</Form> |
|
||||
</Modal > |
|
||||
); |
|
||||
}; |
|
||||
|
|
||||
function mapStateToProps (state) { |
|
||||
const { auth, checkItemsGroup } = state |
|
||||
return { |
|
||||
user: auth.user, |
|
||||
checkItemsGroup: checkItemsGroup.data || [] |
|
||||
} |
|
||||
} |
|
||||
export default connect(mapStateToProps)(PlanModal); |
|
@ -1,89 +0,0 @@ |
|||||
import { Button, Form, Input, Modal, Select, DatePicker,Checkbox, message } from 'antd'; |
|
||||
import React, { useState, useEffect } from 'react'; |
|
||||
import { connect } from 'react-redux'; |
|
||||
import {modifyPatrolRecordIssueHandle} from '../actions/yujingguanli' |
|
||||
import {putxinxi} from '../actions/yujingguanli' |
|
||||
import moment from 'moment'; |
|
||||
|
|
||||
const { RangePicker } = DatePicker; |
|
||||
const { TextArea } = Input; |
|
||||
|
|
||||
const PlanModal = ({ visible, onCancel, dispatch, type, curRecord, tableRef, checkItemsGroup,userlist ,actions,onHandle}) => { |
|
||||
const [form] = Form.useForm(); |
|
||||
const { issueHandle } = actions |
|
||||
const shigutypes = [{value:1,label: '短信告警'}, |
|
||||
{value:2,label:'邮件告警'}] |
|
||||
console.log(userlist,'userlist') |
|
||||
return ( |
|
||||
<Modal |
|
||||
visible={visible} |
|
||||
title="下发告警" |
|
||||
okText="确定" |
|
||||
cancelText="取消" |
|
||||
onCancel={() => { |
|
||||
form.resetFields(); |
|
||||
onCancel(); |
|
||||
}} |
|
||||
onOk={() => { |
|
||||
form |
|
||||
.validateFields() |
|
||||
.then((values) => { |
|
||||
const params = { |
|
||||
...values, |
|
||||
} |
|
||||
console.log('user,',userlist) |
|
||||
let usedata = userlist.filter(i=>i?.username===values.name) |
|
||||
console.log(usedata,'usedata') |
|
||||
dispatch(putxinxi({phone:[params.name],email:[usedata[0]?.email],type:params.type,struction:curRecord?.points?.project?.name |
|
||||
,point:curRecord?.points?.itemData?.name,number:curRecord?.patrolRecordIssueHandles[0]?.yanshoucishu})).then(res=>{ |
|
||||
console.log(res,'res') |
|
||||
}).then(()=>{ |
|
||||
dispatch(modifyPatrolRecordIssueHandle(curRecord?.patrolRecordIssueHandles[0]?.id,{ |
|
||||
isgaojing:true, |
|
||||
yujingshijian:moment().format('YYYY-MM-DD HH:mm:ss') |
|
||||
})).then(()=>message.success('下发告警成功')), |
|
||||
onCancel(); |
|
||||
onHandle() |
|
||||
}) |
|
||||
console.log(curRecord,'curRecord') |
|
||||
console.log(params,'params') |
|
||||
}) |
|
||||
.catch((info) => { |
|
||||
console.log('Validate Failed:', info); |
|
||||
}); |
|
||||
}} |
|
||||
> |
|
||||
<Form |
|
||||
form={form} |
|
||||
// layout="vertical"
|
|
||||
name="form_in_modal" |
|
||||
|
|
||||
labelCol={{ span: 5 }} wrapperCol={{ span: 19 }} |
|
||||
> |
|
||||
<Form.Item |
|
||||
name="name" |
|
||||
label="告警接收人" |
|
||||
rules={[ |
|
||||
{ required: true, message: '请输入用户账号' }, |
|
||||
]} |
|
||||
> |
|
||||
<Select options={userlist?.map(i=>({value:i?.username,label:i?.name}))}></Select> |
|
||||
</Form.Item> |
|
||||
<Form.Item label="告警方式" |
|
||||
name="type"> |
|
||||
<Checkbox.Group options={shigutypes}/> |
|
||||
</Form.Item> |
|
||||
</Form> |
|
||||
</Modal > |
|
||||
); |
|
||||
}; |
|
||||
|
|
||||
function mapStateToProps (state) { |
|
||||
const { auth, checkItemsGroup,global } = state |
|
||||
return { |
|
||||
user: auth.user, |
|
||||
checkItemsGroup: checkItemsGroup.data || [], |
|
||||
actions: global.actions, |
|
||||
} |
|
||||
} |
|
||||
export default connect(mapStateToProps)(PlanModal); |
|
@ -1,176 +0,0 @@ |
|||||
import React, { useState, useRef } from 'react'; |
|
||||
import { connect } from 'react-redux'; |
|
||||
import { Button, Popconfirm } from 'antd'; |
|
||||
import ProTable from '@ant-design/pro-table'; |
|
||||
import CheckItemsModal from '../components/checkItemsModal'; |
|
||||
import { getCheckItems, createCheckItems, updateCheckItems, delCheckItems, createCheckItemsGroup } from '../actions/checkItems'; |
|
||||
|
|
||||
function CheckItems(props) { |
|
||||
const { dispatch } = props; |
|
||||
const tableRef = useRef(); |
|
||||
const [dataSource, setDataSource] = useState([{}]); |
|
||||
const [visible, setVisible] = useState(false); |
|
||||
const [curRecord, setCurRecord] = useState(null); // 新增 or 修改
|
|
||||
const [select, setSelect] = useState([]); |
|
||||
|
|
||||
const onOk = async (values) => { |
|
||||
let groupId = null; |
|
||||
if (values.isNewGroup) { |
|
||||
await dispatch(createCheckItemsGroup({ name: values.group })).then(res => { |
|
||||
if (res.success) { |
|
||||
groupId = res.payload.data?.groupId |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
if (!curRecord) { |
|
||||
dispatch(createCheckItems({ |
|
||||
name: values.name, |
|
||||
groupId: groupId ? groupId : values.group |
|
||||
})).then(res => { |
|
||||
if (res.success) { |
|
||||
tableRef.current.reload(); |
|
||||
} |
|
||||
}) |
|
||||
} else { |
|
||||
dispatch(updateCheckItems(curRecord.id, { |
|
||||
name: values.name, |
|
||||
groupId: groupId ? groupId : values.group |
|
||||
})).then(res => { |
|
||||
if (res.success) { |
|
||||
tableRef.current.reload(); |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
setVisible(false); |
|
||||
}; |
|
||||
|
|
||||
function delItems(ids) { |
|
||||
dispatch(delCheckItems(ids)).then(res => { |
|
||||
if (res.success) { |
|
||||
tableRef.current.reload(); |
|
||||
setSelect([]); |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
const columns = [{ |
|
||||
title: '检查项', |
|
||||
dataIndex: 'name', |
|
||||
key: 'name', |
|
||||
ellipsis: true, |
|
||||
width: 150, |
|
||||
}, { |
|
||||
title: '分组名称', |
|
||||
dataIndex: 'groupName', |
|
||||
key: 'groupName', |
|
||||
ellipsis: true, |
|
||||
search: false, |
|
||||
width: 150, |
|
||||
render: (_, record) => { |
|
||||
return <div>{record?.checkItemsGroup?.name}</div> |
|
||||
} |
|
||||
}, { |
|
||||
title: '操作', |
|
||||
dataIndex: 'action', |
|
||||
key: 'action', |
|
||||
search: false, |
|
||||
width: 200, |
|
||||
render: (_, record) => { |
|
||||
return <> |
|
||||
<Button type="link" onClick={() => { |
|
||||
setCurRecord(record) |
|
||||
setVisible(true) |
|
||||
}}>修改</Button> |
|
||||
<Popconfirm |
|
||||
title="确认删除?" |
|
||||
onConfirm={() => { delItems(record.id) }} |
|
||||
disabled={record && record.patrolTemplates && record.patrolTemplates.length} |
|
||||
> |
|
||||
<Button type="link" danger disabled={record && record.patrolTemplates && record.patrolTemplates.length}>删除</Button> |
|
||||
</Popconfirm> |
|
||||
</> |
|
||||
}, |
|
||||
}]; |
|
||||
|
|
||||
return ( |
|
||||
<> |
|
||||
<ProTable |
|
||||
columns={columns} |
|
||||
actionRef={tableRef} |
|
||||
options={false} |
|
||||
dataSource={dataSource || []} |
|
||||
rowKey='id' |
|
||||
pagination={{ pageSize: 10, size: 'default', className: 'global-pagination' }} |
|
||||
request={async (params = {}) => { |
|
||||
const res = await dispatch(getCheckItems({ |
|
||||
limit: params.pageSize, |
|
||||
page: params.current - 1, |
|
||||
name: params?.name |
|
||||
})); |
|
||||
setDataSource(res?.payload.data?.rows); |
|
||||
return { |
|
||||
...res, |
|
||||
total: res.payload.data.count ? res.payload.data.count : 0, |
|
||||
}; |
|
||||
}} |
|
||||
onReset={() => { }} |
|
||||
search={{ |
|
||||
defaultCollapsed: false, |
|
||||
optionRender: (searchConfig, formProps, dom) => [ |
|
||||
...dom.reverse(), |
|
||||
<Button |
|
||||
key="add" |
|
||||
type='primary' |
|
||||
onClick={() => { |
|
||||
setCurRecord(null) |
|
||||
setVisible(true) |
|
||||
}} |
|
||||
>新增</Button>, |
|
||||
<Button |
|
||||
key="del" |
|
||||
type='primary' |
|
||||
disabled={!select?.length} |
|
||||
onClick={() => { |
|
||||
const ids = select?.map(s => s.id).join(); |
|
||||
delItems(ids); |
|
||||
}} |
|
||||
>批量删除</Button>, |
|
||||
], |
|
||||
}} |
|
||||
rowSelection={{ |
|
||||
selectedRowKeys: select?.map(v => v.id) || [], |
|
||||
onChange: (_, selectedRows) => { |
|
||||
setSelect(selectedRows) |
|
||||
}, |
|
||||
getCheckboxProps: (record) => ({ |
|
||||
disabled: record && record.patrolTemplates && record.patrolTemplates.length, |
|
||||
}), |
|
||||
}} |
|
||||
rowClassName={(record, index) => { |
|
||||
let className = 'global-light-row'; |
|
||||
if (index % 2 === 1) className = 'global-dark-row'; |
|
||||
return className; |
|
||||
}} |
|
||||
/> |
|
||||
{ |
|
||||
visible ? |
|
||||
<CheckItemsModal |
|
||||
visible={visible} |
|
||||
onOk={onOk} |
|
||||
curRecord={curRecord} |
|
||||
onCancel={() => { |
|
||||
setVisible(false); |
|
||||
}} |
|
||||
/> : null |
|
||||
} |
|
||||
</> |
|
||||
) |
|
||||
} |
|
||||
|
|
||||
function mapStateToProps(state) { |
|
||||
const { auth } = state |
|
||||
return { |
|
||||
user: auth.user |
|
||||
} |
|
||||
} |
|
||||
export default connect(mapStateToProps)(CheckItems); |
|
@ -1,10 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
import PatrolPlan from './patrolPlan'; |
|
||||
import PatrolReocrd from './patrolRecord'; |
|
||||
import PatrolReport from './patrolReport'; |
|
||||
import CheckItems from './checkItems'; |
|
||||
import PlanTemplate from './patrolTemplate'; |
|
||||
import YujingGuanli from './yujingguanli'; |
|
||||
|
|
||||
export { PatrolPlan, PatrolReocrd, PatrolReport, CheckItems, PlanTemplate,YujingGuanli }; |
|
@ -1,192 +0,0 @@ |
|||||
import React, { useState, useRef, useEffect } from 'react'; |
|
||||
import { connect } from 'react-redux'; |
|
||||
import { Button, Popconfirm } from 'antd'; |
|
||||
import ProTable from '@ant-design/pro-table'; |
|
||||
import PlanModal from '../components/planModal'; |
|
||||
import { createPatrolPlan, delPatrolPlan, updatePatrolPlan, getPatrolPlan } from '../actions/plan'; |
|
||||
import { getPatrolTemplate } from '../actions/template'; |
|
||||
import moment from 'moment'; |
|
||||
import './patrolPlan.less' |
|
||||
|
|
||||
function PatrolPlan(props) { |
|
||||
const { dispatch, user } = props; |
|
||||
const tableRef = useRef(); |
|
||||
const [dataSource, setDataSource] = useState([{}]); |
|
||||
const [visible, setVisible] = useState(false); |
|
||||
const [type, setType] = useState(); |
|
||||
const [curRecord, setCurRecord] = useState(); |
|
||||
|
|
||||
useEffect(() => { |
|
||||
dispatch(getPatrolTemplate({})) |
|
||||
}, []) |
|
||||
|
|
||||
const onCreate = (values) => { |
|
||||
if (type === 'create') { |
|
||||
dispatch(createPatrolPlan(values)).then(res => { |
|
||||
if (res.success) { |
|
||||
tableRef.current.reload(); |
|
||||
} |
|
||||
}) |
|
||||
} else { |
|
||||
dispatch(updatePatrolPlan({ ...values, id: curRecord.id })).then(res => { |
|
||||
if (res.success) { |
|
||||
tableRef.current.reload(); |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
setVisible(false); |
|
||||
setCurRecord(null); |
|
||||
}; |
|
||||
|
|
||||
const columns = [{ |
|
||||
title: '结构物名称', |
|
||||
dataIndex: 'projectName', |
|
||||
key: 'projectName', |
|
||||
ellipsis: true, |
|
||||
render: (_, record) => { |
|
||||
return <div>{record?.project?.name}</div> |
|
||||
} |
|
||||
}, { |
|
||||
title: '巡检任务名称', |
|
||||
dataIndex: 'name', |
|
||||
key: 'name', |
|
||||
ellipsis: true |
|
||||
}, { |
|
||||
title: '开始时间', |
|
||||
dataIndex: 'startTime', |
|
||||
key: 'startTime', |
|
||||
ellipsis: true, |
|
||||
search: false, |
|
||||
render: (_, record) => moment(record.startTime).format('YYYY-MM-DD') |
|
||||
}, { |
|
||||
title: '结束时间', |
|
||||
dataIndex: 'endTime', |
|
||||
key: 'endTime', |
|
||||
ellipsis: true, |
|
||||
search: false, |
|
||||
render: (_, record) => moment(record.endTime).format('YYYY-MM-DD') |
|
||||
}, { |
|
||||
title: '巡检频次', |
|
||||
dataIndex: 'frequency', |
|
||||
key: 'frequency', |
|
||||
ellipsis: true, |
|
||||
search: false, |
|
||||
}, { |
|
||||
title: '巡检点位', |
|
||||
dataIndex: 'patrolPoints', |
|
||||
key: 'patrolPoints', |
|
||||
ellipsis: true, |
|
||||
search: false, |
|
||||
render: (_, record) => record?.points?.length ? record?.points?.map(p => p.name).join() : '-' |
|
||||
}, { |
|
||||
title: '巡检人', |
|
||||
dataIndex: 'patrolPerson', |
|
||||
key: 'patrolPerson', |
|
||||
ellipsis: true, |
|
||||
search: false, |
|
||||
render: (_, record) => record?.users?.map(u => u.name).join() || '-' |
|
||||
}, { |
|
||||
title: '巡检次数统计', |
|
||||
dataIndex: 'patrolCount', |
|
||||
key: 'patrolCount', |
|
||||
ellipsis: true, |
|
||||
search: false, |
|
||||
}, { |
|
||||
title: '操作', |
|
||||
dataIndex: 'action', |
|
||||
key: 'action', |
|
||||
search: false, |
|
||||
width: 200, |
|
||||
render: (_, record) => { |
|
||||
return <> |
|
||||
<Button type="link" onClick={() => { |
|
||||
setType('edit') |
|
||||
setCurRecord(record) |
|
||||
setVisible(true) |
|
||||
}}>修改</Button> |
|
||||
<Button type="link" onClick={() => { |
|
||||
setType('view') |
|
||||
setCurRecord(record) |
|
||||
setVisible(true) |
|
||||
}}>查看</Button> |
|
||||
<Popconfirm |
|
||||
title="确认删除?" |
|
||||
onConfirm={() => { |
|
||||
dispatch(delPatrolPlan(record.id)).then(res => { |
|
||||
if (res.success) { |
|
||||
tableRef.current.reload(); |
|
||||
} |
|
||||
}) |
|
||||
}}> |
|
||||
<Button type="link" danger>删除</Button> |
|
||||
</Popconfirm> |
|
||||
</> |
|
||||
}, |
|
||||
}]; |
|
||||
|
|
||||
return ( |
|
||||
<div className='plan-main'> |
|
||||
<div className='title'> |
|
||||
<span className='line'></span> |
|
||||
<span className='cn'>巡检计划制定</span> |
|
||||
<span className='en'> Inspection plan making</span> |
|
||||
</div> |
|
||||
<ProTable |
|
||||
columns={columns} |
|
||||
actionRef={tableRef} |
|
||||
options={false} |
|
||||
dataSource={dataSource || []} |
|
||||
rowKey='id' |
|
||||
pagination={{ pageSize: 10, size: 'default', className: 'global-pagination' }} |
|
||||
search={{ |
|
||||
className: 'search-form', |
|
||||
defaultCollapsed: false, |
|
||||
labelWidth: 'auto', |
|
||||
optionRender: (searchConfig, formProps, dom) => [ |
|
||||
...dom.reverse(), |
|
||||
<Button |
|
||||
type="primary" |
|
||||
key="primary" |
|
||||
onClick={() => { |
|
||||
setType('create') |
|
||||
setVisible(true) |
|
||||
}} |
|
||||
>新增巡检计划</Button>, |
|
||||
], |
|
||||
}} |
|
||||
request={async (params = {}) => { |
|
||||
const res = await dispatch(getPatrolPlan(params)); |
|
||||
setDataSource(res?.payload.data?.rows); |
|
||||
return { ...res }; |
|
||||
}} |
|
||||
onReset={() => { }} |
|
||||
rowClassName={(record, index) => { |
|
||||
let className = 'global-light-row'; |
|
||||
if (index % 2 === 1) className = 'global-dark-row'; |
|
||||
return className; |
|
||||
}} |
|
||||
/> |
|
||||
{ |
|
||||
visible ? |
|
||||
<PlanModal |
|
||||
visible={visible} |
|
||||
onCreate={onCreate} |
|
||||
type={type} |
|
||||
curRecord={curRecord} |
|
||||
onCancel={() => { |
|
||||
setVisible(false); |
|
||||
setCurRecord(null) |
|
||||
}} |
|
||||
/> : null |
|
||||
} |
|
||||
</div> |
|
||||
) |
|
||||
} |
|
||||
|
|
||||
function mapStateToProps(state) { |
|
||||
const { auth } = state |
|
||||
return { |
|
||||
user: auth.user |
|
||||
} |
|
||||
} |
|
||||
export default connect(mapStateToProps)(PatrolPlan); |
|
@ -1,20 +0,0 @@ |
|||||
.plan-main { |
|
||||
background: #fff; |
|
||||
|
|
||||
.search-form { |
|
||||
.ant-row-start { |
|
||||
justify-content: flex-end; |
|
||||
|
|
||||
.ant-col-offset-6 { |
|
||||
margin-left: 0; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.title { |
|
||||
position: absolute; |
|
||||
top: 50px; |
|
||||
left: 50px; |
|
||||
z-index: 1; |
|
||||
} |
|
||||
} |
|
@ -1,387 +0,0 @@ |
|||||
|
|
||||
'use strict' |
|
||||
|
|
||||
import React, { useEffect, useState } from 'react'; |
|
||||
import { connect } from 'react-redux'; |
|
||||
import { Form, Input, Select, Button, Table, Modal, DatePicker, message, Row, Col, Collapse, Popconfirm } from 'antd'; |
|
||||
import moment from "moment"; |
|
||||
import XLSX from 'xlsx'; |
|
||||
import Uploads from '$components/Uploads'; |
|
||||
import '../style.less' |
|
||||
|
|
||||
const { Panel } = Collapse; |
|
||||
|
|
||||
const PatrolRecord = (props) => { |
|
||||
const { dispatch, actions, } = props |
|
||||
const { patrolManage } = actions |
|
||||
const [tableList, settableList] = useState([]) |
|
||||
const [showDetailModal, setShowDetail] = useState(false) |
|
||||
const [modelData, setModelData] = useState({}) |
|
||||
const [query, setQuery] = useState({ limit: 10, page: 0 }) |
|
||||
const [limits, setLimits] = useState() |
|
||||
const format = 'YYYY-MM-DD HH:mm:ss' |
|
||||
const [search, setSearch] = useState({ name: null, time: [moment().add(-7, 'd').format(format), moment().format(format)], state: 'null' }) |
|
||||
const [exportLoading, setExportLoading] = useState(false) |
|
||||
const aboutDisaster={handleObj:'排查及处理对象',installLocation:'安装位置',handleGoal:'排查及处理目的',rtuNo:'RTU编号'} |
|
||||
useEffect(() => { |
|
||||
record(search) |
|
||||
}, []) |
|
||||
|
|
||||
const record = (params) => { |
|
||||
dispatch(patrolManage.records(`patrolRecord/all/${params.time[0]}/${params.time[1]}/${params.state}/null`)).then(res => { |
|
||||
if (res.success) { |
|
||||
settableList(params.name != null ? res.payload.data?.filter(v => |
|
||||
(v.points.user.name.indexOf(params.name) != -1 || v.points.project.name.indexOf(params.name) != -1)) |
|
||||
.map(v => ({ ...v, key: v.id })) : res.payload.data?.map(v => ({ ...v, key: v.id }))) |
|
||||
setLimits(res.payload.data?.length) |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
const exportRecord = () => { |
|
||||
if (tableList.length === 0) { |
|
||||
message.warning('没有数据可以导出') |
|
||||
return |
|
||||
} |
|
||||
setExportLoading(true) |
|
||||
const workbook = XLSX.utils.book_new(); // 新建工作簿
|
|
||||
let data = [['结构物名称', '巡检计划', '巡检点位', '巡检人', '巡检单位', '巡检频次', '上次巡检日期', '本次巡检日期', '巡检结果']]; |
|
||||
for (const item of tableList) { |
|
||||
data.push([ |
|
||||
item.points?.project?.name || '--', |
|
||||
item.patrolPlan?.name || '--', |
|
||||
item.points?.itemData?.name || '--', |
|
||||
item.points?.user?.name || '--', |
|
||||
item.points?.user?.department?.name || '--', |
|
||||
item.points?.frequency || '--', |
|
||||
item.lastInspectionTime ? moment(item.lastInspectionTime).format('YYYY-MM-DD HH:mm:ss') : '--', |
|
||||
moment(item.inspectionTime).format('YYYY-MM-DD HH:mm:ss'), |
|
||||
!item.alarm ? '正常' : '异常', |
|
||||
]) |
|
||||
} |
|
||||
const worksheet = XLSX.utils.aoa_to_sheet(data); // 从二维数组新建工作表
|
|
||||
XLSX.utils.book_append_sheet(workbook, worksheet, "sheet1"); // 将工作表添加到工作簿
|
|
||||
XLSX.writeFile(workbook, '巡检记录.xlsx'); // 将工作簿数据建立为./xlsx文件(浏览器环境下会直接下载)
|
|
||||
message.success('导出成功') |
|
||||
setExportLoading(false) |
|
||||
} |
|
||||
|
|
||||
const columns = [{ |
|
||||
title: '结构物名称', |
|
||||
dataIndex: 'name', |
|
||||
key: 'name', |
|
||||
width: '10%', |
|
||||
showInDetail: true, |
|
||||
render: (text, record, index) => { |
|
||||
return !record.points?.project ? '--' : <div>{record.points.project.name}</div> |
|
||||
} |
|
||||
}, { |
|
||||
title: '巡检计划', |
|
||||
dataIndex: 'name', |
|
||||
key: 'name', |
|
||||
width: '10%', |
|
||||
showInDetail: true, |
|
||||
render: (text, record, index) => { |
|
||||
return !record.patrolPlan ? '--' : <div>{record?.patrolPlan?.name || '-'}</div> |
|
||||
} |
|
||||
}, { |
|
||||
title: '巡检点位', |
|
||||
dataIndex: 'type', |
|
||||
key: 'type', |
|
||||
showInDetail: true, |
|
||||
width: '10%', |
|
||||
render: (text, record, index) => { |
|
||||
return !record.points?.user ? '--' : <div>{record.points.itemData.name}</div> |
|
||||
} |
|
||||
}, { |
|
||||
title: '巡检人', |
|
||||
dataIndex: 'type', |
|
||||
key: 'type', |
|
||||
showInDetail: true, |
|
||||
width: '10%', |
|
||||
render: (text, record, index) => { |
|
||||
return !record.points?.user ? '--' : <div>{record.points.user.name}</div> |
|
||||
} |
|
||||
}, { |
|
||||
title: '巡检单位', |
|
||||
dataIndex: 'type', |
|
||||
showInDetail: true, |
|
||||
key: 'type', |
|
||||
width: '10%', |
|
||||
render: (text, record, index) => { |
|
||||
return !record.points?.user ? '--' : <div>{record.points.user.department.name}</div> |
|
||||
} |
|
||||
}, { |
|
||||
title: '巡检频次', |
|
||||
dataIndex: 'describe', |
|
||||
key: 'describe', |
|
||||
showInDetail: true, |
|
||||
width: '10%', |
|
||||
render: (text, record, index) => { |
|
||||
return !record.points ? '--' : <div>{record.points.frequency || '-'}</div> |
|
||||
} |
|
||||
}, { |
|
||||
title: '上次巡检日期', |
|
||||
dataIndex: 'describe', |
|
||||
showInDetail: true, |
|
||||
key: 'describe', |
|
||||
render: (text, record, index) => record.lastInspectionTime ? moment(record.lastInspectionTime).format('YYYY-MM-DD HH:mm:ss') : '--' |
|
||||
}, { |
|
||||
title: '本次巡检日期', |
|
||||
dataIndex: 'describe', |
|
||||
key: 'describe', |
|
||||
showInDetail: true, |
|
||||
render: (text, record, index) => moment(record.inspectionTime).format('YYYY-MM-DD HH:mm:ss') || '--' |
|
||||
}, { |
|
||||
title: '巡检结果', |
|
||||
dataIndex: 'describe', |
|
||||
key: 'describe', |
|
||||
render: (text, record, index) => !record.alarm ? '正常' : '异常' |
|
||||
}, { |
|
||||
title: '操作', |
|
||||
dataIndex: 'operation', |
|
||||
key: 'operation', |
|
||||
render: (text, record, index) => { |
|
||||
return ( |
|
||||
<div style={{ width: 190 }}> |
|
||||
<Button type="link" onClick={() => { |
|
||||
setShowDetail(true) |
|
||||
setModelData(record) |
|
||||
}}> |
|
||||
查看详情</Button> |
|
||||
</div> |
|
||||
) |
|
||||
} |
|
||||
} |
|
||||
] |
|
||||
|
|
||||
return ( |
|
||||
<div id='patrol-record' className='global-main'> |
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', padding: '0 10px' }}> |
|
||||
<Form |
|
||||
style={{ display: 'flex', }} |
|
||||
onFinish={r => { |
|
||||
record({ |
|
||||
name: r.name, |
|
||||
time: [moment(r.time[0]).format(format), moment(r.time[1]).format(format)], |
|
||||
state: r.state |
|
||||
}) |
|
||||
}} |
|
||||
> |
|
||||
<Form.Item |
|
||||
name="name" |
|
||||
style={{ marginRight: 16, minWidth: 250 }} |
|
||||
> |
|
||||
<Input placeholder="请输入结构物名称或巡检人" allowClear /> |
|
||||
</Form.Item> |
|
||||
<Form.Item |
|
||||
name="time" |
|
||||
style={{ marginRight: 16, }} |
|
||||
initialValue={[moment(search.time[0], format), moment(search.time[1], format)]} |
|
||||
> |
|
||||
<DatePicker.RangePicker showTime style={{ marginRight: 16, }} /> |
|
||||
</Form.Item> |
|
||||
<Form.Item |
|
||||
name="state" |
|
||||
style={{ marginRight: 16, }} |
|
||||
initialValue={'null'} |
|
||||
> |
|
||||
<Select allowClear |
|
||||
options={[ |
|
||||
{ value: 'null', label: '全部' }, |
|
||||
{ value: false, label: '正常' }, |
|
||||
{ value: true, label: '异常' }]} /> |
|
||||
</Form.Item> |
|
||||
<Form.Item wrapperCol={{}}> |
|
||||
<Button type="primary" htmlType="submit" style={{ marginRight: 16 }}>搜索</Button> |
|
||||
<Button type="primary" onClick={exportRecord} loading={exportLoading}>导出</Button> |
|
||||
</Form.Item> |
|
||||
</Form> |
|
||||
</div> |
|
||||
<Table |
|
||||
columns={columns} |
|
||||
dataSource={tableList} |
|
||||
pagination={{ |
|
||||
className: 'global-pagination', |
|
||||
showTotal: (total, range) => `第 ${range[0]}-${range[1]} 条/总共 ${total} 条` |
|
||||
}} |
|
||||
rowClassName={(record, index) => { |
|
||||
let className = 'global-light-row'; |
|
||||
if (index % 2 === 1) className = 'global-dark-row'; |
|
||||
return className; |
|
||||
}} |
|
||||
/> |
|
||||
<Modal |
|
||||
title='巡检记录详情' |
|
||||
open={showDetailModal} |
|
||||
onCancel={() => setShowDetail(false)} |
|
||||
footer={[<Button onClick={() => setShowDetail(false)}>关闭</Button>]} |
|
||||
className='patrol-record-detail-modal' |
|
||||
width={666} |
|
||||
> |
|
||||
{(() => { |
|
||||
let dataArr = [] |
|
||||
columns.forEach(c => { |
|
||||
if (c.showInDetail) { |
|
||||
dataArr.push( |
|
||||
<> |
|
||||
<Row> |
|
||||
<Col span={5} style={{ |
|
||||
// textAlign: 'justify', textAlignLast: 'justify'
|
|
||||
}}>{c.title} :</Col> |
|
||||
<Col span={19}>{c.render('', modelData)}</Col> |
|
||||
</Row> |
|
||||
</> |
|
||||
) |
|
||||
} |
|
||||
}) |
|
||||
|
|
||||
if (modelData && modelData.points && modelData.points.inspectContent) { |
|
||||
//地灾相关详情数据渲染
|
|
||||
if(modelData.points.aboutDisaster){ |
|
||||
for (let v in modelData.points.aboutDisaster) { |
|
||||
dataArr.push( <> |
|
||||
<Row> |
|
||||
<Col span={5} style={{ |
|
||||
// textAlign: 'justify', textAlignLast: 'justify'
|
|
||||
}}>{aboutDisaster[v]} :</Col> |
|
||||
<Col span={19}>{modelData.points.aboutDisaster[v]}</Col> |
|
||||
</Row> |
|
||||
</>) |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
if (modelData?.points?.itemData?.pointDevices?.length > 0) { |
|
||||
let inspectContent = modelData.points.inspectContent |
|
||||
inspectContent?.map(s => { |
|
||||
dataArr.push( |
|
||||
<> |
|
||||
<Row> |
|
||||
<Col span={5} style={{}}>{s?.deviceName} :</Col> |
|
||||
<Col span={19}> |
|
||||
{ |
|
||||
!s.alarm ? '正常' : |
|
||||
<Collapse ghost style={{ padding: 0 }}> |
|
||||
<Panel header="异常" key="1" style={{ padding: 0 }}> |
|
||||
{s?.checkItems?.map(k => { |
|
||||
return <> |
|
||||
<Row style={{ fontWeight: 'bold' }}>{k.name}:</Row> |
|
||||
<Row style={{ marginBottom: 20 }}> |
|
||||
<Col span={4} style={{}}>巡查详情 :</Col> |
|
||||
<Col span={20}>{k.msgInp}</Col> |
|
||||
<Col span={4} style={{}}>严重等级 :</Col> |
|
||||
<Col span={20}>{k.level}</Col> |
|
||||
<Col span={4} style={{}}>现场照片 :</Col> |
|
||||
<Col span={20}> |
|
||||
<Uploads |
|
||||
listType='picture-card' |
|
||||
uploadType='project' |
|
||||
maxFilesNum={1} |
|
||||
maxFileSize={10} |
|
||||
isQiniu={true} |
|
||||
disabled={true} |
|
||||
fileTypes={["png", "jpg"]} |
|
||||
defaultValue={ |
|
||||
(() => { |
|
||||
let nextV = [] |
|
||||
for (let s of (k.imgs || [])) { |
|
||||
if (s) { |
|
||||
nextV.push({ |
|
||||
storageUrl: s |
|
||||
}) |
|
||||
} |
|
||||
} |
|
||||
return nextV |
|
||||
})() |
|
||||
} |
|
||||
/> |
|
||||
</Col> |
|
||||
</Row> |
|
||||
</> |
|
||||
|
|
||||
})} |
|
||||
|
|
||||
</Panel> |
|
||||
</Collapse> |
|
||||
} |
|
||||
</Col> |
|
||||
</Row> |
|
||||
</> |
|
||||
) |
|
||||
}) |
|
||||
|
|
||||
} else { |
|
||||
let inspectContent = modelData.points.inspectContent |
|
||||
for (let v in inspectContent) { |
|
||||
inspectContent[v]?.checkItems?.map(k => { |
|
||||
dataArr.push( |
|
||||
<> |
|
||||
<Row> |
|
||||
<Col span={5} style={{}}>{k?.name} :</Col> |
|
||||
<Col span={19}> |
|
||||
{ |
|
||||
!k.level ? '正常' : |
|
||||
<Collapse ghost style={{ padding: 0 }}> |
|
||||
<Panel header="异常" key="1" style={{ padding: 0 }}> |
|
||||
<Row> |
|
||||
<Col span={4} style={{}}>巡查详情 :</Col> |
|
||||
<Col span={20}>{k.msgInp}</Col> |
|
||||
<Col span={4} style={{}}>严重等级 :</Col> |
|
||||
<Col span={20}>{k.level}</Col> |
|
||||
<Col span={4} style={{}}>现场照片 :</Col> |
|
||||
<Col span={20}> |
|
||||
<Uploads |
|
||||
listType='picture-card' |
|
||||
uploadType='project' |
|
||||
maxFilesNum={1} |
|
||||
maxFileSize={10} |
|
||||
isQiniu={true} |
|
||||
disabled={true} |
|
||||
fileTypes={["png", "jpg"]} |
|
||||
defaultValue={ |
|
||||
(() => { |
|
||||
let nextV = [] |
|
||||
for (let s of (k.imgs || [])) { |
|
||||
if (s) { |
|
||||
nextV.push({ |
|
||||
storageUrl: s |
|
||||
}) |
|
||||
} |
|
||||
} |
|
||||
return nextV |
|
||||
})() |
|
||||
} |
|
||||
/> |
|
||||
</Col> |
|
||||
</Row> |
|
||||
</Panel> |
|
||||
</Collapse> |
|
||||
} |
|
||||
</Col> |
|
||||
</Row> |
|
||||
</> |
|
||||
) |
|
||||
}) |
|
||||
|
|
||||
|
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
} |
|
||||
return dataArr |
|
||||
})()} |
|
||||
</Modal> |
|
||||
</div> |
|
||||
) |
|
||||
} |
|
||||
|
|
||||
function mapStateToProps(state) { |
|
||||
const { auth, global } = state; |
|
||||
return { |
|
||||
user: auth.user, |
|
||||
actions: global.actions, |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
export default connect(mapStateToProps)(PatrolRecord); |
|
@ -1,378 +0,0 @@ |
|||||
import React, { useState, useRef, useEffect } from 'react'; |
|
||||
import { connect } from 'react-redux'; |
|
||||
import { Button, Tabs, Popconfirm, Tooltip, Spin } from 'antd'; |
|
||||
import ProTable from '@ant-design/pro-table'; |
|
||||
import { getPatrolReport } from '../actions/report'; |
|
||||
import { getProjectList } from '../actions/plan'; |
|
||||
import moment from 'moment'; |
|
||||
import AddReportRulesModal from '../components/addReportRulesModal'; |
|
||||
function patrolReport(props) { |
|
||||
const { dispatch, actions } = props; |
|
||||
const { projectRegime, patrolManage } = actions |
|
||||
const tableRef = useRef(); |
|
||||
const tableRef2 = useRef(); |
|
||||
const [selectOpts, setSelectOpts] = useState([]); |
|
||||
const [date, setDate] = useState([moment().subtract(1, 'days'), moment()]); |
|
||||
const [dataSource, setDataSource] = useState([]); |
|
||||
const [modalVis, setModalVis] = useState(false) |
|
||||
const [structAll, setStructAll] = useState([])//完整的结构物列表(包括subType)
|
|
||||
const [reportList, setReportList] = useState([])//报表
|
|
||||
const qnDomain = localStorage.getItem('qnDomain'); |
|
||||
const [query, setQuery] = useState({ limit: 10, page: 0 }) |
|
||||
const [typeList, setTypeList] = useState([{ value: 1, label: '周报表' }, { value: 2, label: '月报表' }]) |
|
||||
const [modalData, setModalData] = useState(null) |
|
||||
const [loading, setLoading] = useState(false) |
|
||||
//报表配置
|
|
||||
// const getReportConfig = (query) => {
|
|
||||
// const { limit, page, name } = query
|
|
||||
// dispatch(patrolManage.getReportList({ limit, page, name })).then(res => {
|
|
||||
// if (res.success) {
|
|
||||
// //过滤管廊类型的数据
|
|
||||
// const list = res.payload.data?.rows
|
|
||||
// setReportList(list)
|
|
||||
// }
|
|
||||
// })
|
|
||||
// }
|
|
||||
//结构物
|
|
||||
const projectList = () => { |
|
||||
dispatch(projectRegime.getProjectList()).then(res => { |
|
||||
if (res.success) { |
|
||||
|
|
||||
const nextSelectOpts = res.payload?.data?.rows.map(d => { |
|
||||
return { label: d.name, value: d.id } |
|
||||
}) |
|
||||
setStructAll(res.payload?.data?.rows) |
|
||||
setSelectOpts(nextSelectOpts) |
|
||||
// setStructlist(list)
|
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
useEffect(() => { |
|
||||
// dispatch(getProjectList()).then(res => {
|
|
||||
// if (res.success) {
|
|
||||
|
|
||||
// }
|
|
||||
// });
|
|
||||
projectList() |
|
||||
// getReportConfig(query)
|
|
||||
}, []) |
|
||||
const edithandler = (e) => { |
|
||||
setModalData(e) |
|
||||
setModalVis(true) |
|
||||
} |
|
||||
const onOk = () => { |
|
||||
tableRef2.current.reload(); |
|
||||
} |
|
||||
const confirmHandler = (id) => { |
|
||||
dispatch(patrolManage.delReport(id)).then(res => { |
|
||||
if (res.success) { |
|
||||
// getReportConfig(query)
|
|
||||
tableRef2.current.reload(); |
|
||||
|
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
const generateReport = (record) => { |
|
||||
setLoading(true) |
|
||||
let data = { |
|
||||
reportName: record?.name, |
|
||||
startTime: moment(record?.startTime).format('YYYY-MM-DD HH:mm:ss'), |
|
||||
endTime: moment(record?.endTime).format('YYYY-MM-DD HH:mm:ss'), |
|
||||
structIds: record?.structure, |
|
||||
structNames: structAll?.filter(item => record?.structure.some(q => q == item.id))?.map(o => o.name) || [], |
|
||||
reportType: record?.type, |
|
||||
system: record?.system, |
|
||||
images: record?.reportpic.map(item => qnDomain + '/' + item) || [] |
|
||||
} |
|
||||
dispatch(patrolManage.postGenerateReport(data)).then(res => { |
|
||||
if (res.success) { |
|
||||
setLoading(false) |
|
||||
tableRef.current.reload(); |
|
||||
|
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
//删除巡检记录
|
|
||||
const delReport = (id) => { |
|
||||
|
|
||||
} |
|
||||
|
|
||||
|
|
||||
const columns = [{ |
|
||||
title: '结构物名称', |
|
||||
dataIndex: 'projectName', |
|
||||
key: 'projectName', |
|
||||
valueType: 'select', |
|
||||
fieldProps: { |
|
||||
showSearch: true, |
|
||||
defaultValue: '', |
|
||||
options: [{ label: '全部', value: '' }, ...selectOpts], |
|
||||
}, |
|
||||
ellipsis: true, |
|
||||
width: 150, |
|
||||
render: (_, record) => { |
|
||||
const rslt = structAll?.filter(p => record.structure?.some(q => q == p.id)) |
|
||||
return <> |
|
||||
<div>{record?.project ? record?.project?.name : record.structure?.length > 1 ? <Tooltip title={rslt?.map(item => item.name)?.join(',')}> |
|
||||
<span>{rslt && rslt.length ? rslt[0].name + '...' : ''}</span> |
|
||||
</Tooltip> : rslt?.map(item => item.name)?.join(',') |
|
||||
}</div> |
|
||||
|
|
||||
</> |
|
||||
|
|
||||
|
|
||||
} |
|
||||
}, { |
|
||||
title: '巡检报告名称', |
|
||||
dataIndex: 'groupName', |
|
||||
key: 'groupName', |
|
||||
ellipsis: true, |
|
||||
search: false, |
|
||||
width: 250, |
|
||||
render: (_, record) => { |
|
||||
const fileName = record?.excelPath?.substring(record?.excelPath?.lastIndexOf('/') + 1); |
|
||||
return <div>{fileName}</div> |
|
||||
} |
|
||||
}, { |
|
||||
title: '生成日期', |
|
||||
dataIndex: 'date', |
|
||||
key: 'date', |
|
||||
valueType: 'dateRange', |
|
||||
fieldProps: { |
|
||||
value: date, |
|
||||
onChange: e => { setDate(e) } |
|
||||
}, |
|
||||
ellipsis: true, |
|
||||
width: 150, |
|
||||
render: (_, record) => { |
|
||||
return <div>{moment(record?.inspectTm).format('YYYY-MM-DD')}</div> |
|
||||
} |
|
||||
}, { |
|
||||
title: '操作', |
|
||||
dataIndex: 'action', |
|
||||
key: 'action', |
|
||||
search: false, |
|
||||
width: 200, |
|
||||
render: (_, record) => { |
|
||||
return <> |
|
||||
<Button type="link" onClick={() => { |
|
||||
window.open(`https://view.officeapps.live.com/op/view.aspx?src=${qnDomain}/${record?.excelPath}`) |
|
||||
}}>预览</Button> |
|
||||
{/* onClick={() => { window.open() }} */} |
|
||||
<a href={'/_file-server' + '/' + record?.excelPath}>下载</a> |
|
||||
<Popconfirm |
|
||||
placement='left' |
|
||||
title={`确定删除?`} |
|
||||
onConfirm={() => { |
|
||||
dispatch(patrolManage.delpatrolRecord(record?.id)).then(res=>{ |
|
||||
if(res.success){ |
|
||||
tableRef.current.reload(); |
|
||||
} |
|
||||
}) |
|
||||
}} |
|
||||
> |
|
||||
<Button type="link">删除</Button> |
|
||||
</Popconfirm> |
|
||||
</> |
|
||||
}, |
|
||||
}]; |
|
||||
const column2 = [ |
|
||||
{ |
|
||||
title: '报表名称', |
|
||||
dataIndex: 'name', |
|
||||
key: 'name', |
|
||||
ellipsis: true, |
|
||||
width: 250, |
|
||||
fieldProps: { |
|
||||
showSearch: true, |
|
||||
defaultValue: '', |
|
||||
}, |
|
||||
}, |
|
||||
{ |
|
||||
title: '报表类型', |
|
||||
dataIndex: 'type', |
|
||||
key: 'type', |
|
||||
ellipsis: true, |
|
||||
search: false, |
|
||||
width: 250, |
|
||||
render: (_, record) => { |
|
||||
return <> |
|
||||
{typeList.find(item => record.type == item.value)?.label} |
|
||||
</> |
|
||||
} |
|
||||
|
|
||||
}, |
|
||||
{ |
|
||||
title: '关联结构物', |
|
||||
dataIndex: 'structure', |
|
||||
key: 'structure', |
|
||||
ellipsis: true, |
|
||||
search: false, |
|
||||
width: 250, |
|
||||
render: (_, record) => { |
|
||||
const rslt = structAll?.filter(p => record.structure?.some(q => q == p.id)) |
|
||||
return <> |
|
||||
{record.structure.length > 1 ? <Tooltip title={rslt?.map(item => item.name)?.join(',')}> |
|
||||
<span>{rslt && rslt.length ? rslt[0].name + '...' : ''}</span> |
|
||||
</Tooltip> : rslt?.map(item => item.name)?.join(',')} |
|
||||
</> |
|
||||
} |
|
||||
}, |
|
||||
{ |
|
||||
title: '生成时间范围', |
|
||||
key: 'timeRange', |
|
||||
// ellipsis: true,
|
|
||||
search: false, |
|
||||
width: 250, |
|
||||
render: (_, record) => { |
|
||||
return <> |
|
||||
{moment(record.startTime).format('YYYY-MM-DD')} ~ {moment(record.endTime).format('YYYY-MM-DD')} |
|
||||
</> |
|
||||
} |
|
||||
}, |
|
||||
{ |
|
||||
title: '系统', |
|
||||
key: 'system', |
|
||||
// ellipsis: true,
|
|
||||
search: false, |
|
||||
width: 250, |
|
||||
render: (_, record) => { |
|
||||
return <> |
|
||||
{record.system ? record.system === 1 ? '动力系统' : record.system === 2 ? '网络系统' : '--' : '--'} |
|
||||
</> |
|
||||
} |
|
||||
}, |
|
||||
{ |
|
||||
title: '操作', |
|
||||
key: 'option', |
|
||||
// ellipsis: true,
|
|
||||
search: false, |
|
||||
width: 250, |
|
||||
render: (_, record) => { |
|
||||
return <> |
|
||||
<Button type="primary" style={{ marginRight: 10 }} onClick={() => { edithandler(record) }}>编辑</Button> |
|
||||
<Popconfirm title="确定删除报表吗" |
|
||||
description="确定删除报表吗?" |
|
||||
onConfirm={() => { confirmHandler(record?.id) }} |
|
||||
><Button type="primary" style={{ marginRight: 10 }} danger>删除</Button></Popconfirm> |
|
||||
<Button type="primary" onClick={() => { generateReport(record) }}>立即生成</Button> |
|
||||
</> |
|
||||
} |
|
||||
} |
|
||||
] |
|
||||
|
|
||||
const onChange = (key) => { |
|
||||
|
|
||||
}; |
|
||||
const cancelHandle = () => { |
|
||||
setModalVis(false) |
|
||||
setModalData(null) |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
return ( |
|
||||
|
|
||||
<> |
|
||||
<Tabs |
|
||||
defaultActiveKey="1" |
|
||||
onChange={onChange} |
|
||||
items={[ |
|
||||
{ |
|
||||
label: `报表列表`, |
|
||||
key: '1', |
|
||||
children: <ProTable |
|
||||
columns={columns} |
|
||||
actionRef={tableRef} |
|
||||
options={false} |
|
||||
dataSource={dataSource || []} |
|
||||
rowKey='id' |
|
||||
pagination={{ pageSize: 10, size: 'default', className: 'global-pagination' }} |
|
||||
request={async (params = {}) => { |
|
||||
const res = await dispatch(getPatrolReport({ |
|
||||
limit: params?.pageSize, |
|
||||
page: params?.current - 1, |
|
||||
projectId: params?.projectName, |
|
||||
startTime: date ? date[0].format('YYYY-MM-DD') + ' 00:00:00' : '', |
|
||||
endTime: date ? date[1].format('YYYY-MM-DD') + ' 23:59:59' : '', |
|
||||
})); |
|
||||
setDataSource(res?.payload.data?.rows); |
|
||||
return { |
|
||||
...res, |
|
||||
total: res.payload.data.count ? res.payload.data.count : 0, |
|
||||
}; |
|
||||
}} |
|
||||
onReset={() => { setDate([moment().subtract(1, 'days'), moment()]) }} |
|
||||
rowClassName={(record, index) => { |
|
||||
let className = 'global-light-row'; |
|
||||
if (index % 2 === 1) className = 'global-dark-row'; |
|
||||
return className; |
|
||||
}} |
|
||||
/>, |
|
||||
}, |
|
||||
{ |
|
||||
label: `报表配置`, |
|
||||
key: '2', |
|
||||
children: <> |
|
||||
<Spin spinning={loading}> |
|
||||
<ProTable |
|
||||
|
|
||||
actionRef={tableRef2} |
|
||||
options={false} |
|
||||
columns={column2} |
|
||||
dataSource={reportList || []} |
|
||||
pagination={{ pageSize: 10, size: 'default', className: 'global-pagination' }} |
|
||||
request={async (query) => { |
|
||||
const { limit, page, name } = query |
|
||||
const res = await dispatch(patrolManage.getReportList({ limit, page, name })) |
|
||||
const list = res?.payload?.data?.rows |
|
||||
setReportList(list) |
|
||||
return { |
|
||||
...res, |
|
||||
total: res.payload.data.count ? res.payload.data.count : 0, |
|
||||
}; |
|
||||
}} |
|
||||
// cardProps={{ title: '新建报表规则', bordered: true }}
|
|
||||
headerTitle={ |
|
||||
<Button |
|
||||
key="primary" |
|
||||
type="primary" |
|
||||
onClick={() => { |
|
||||
setModalVis(true) |
|
||||
}} |
|
||||
> |
|
||||
新建报表规则 |
|
||||
</Button> |
|
||||
|
|
||||
} |
|
||||
rowKey="key" |
|
||||
search={true} |
|
||||
/> |
|
||||
</Spin> |
|
||||
<AddReportRulesModal structAll={structAll} typeList={typeList} modalData={modalData} onOk={onOk} visible={modalVis} cancelHandle={cancelHandle}> |
|
||||
|
|
||||
</AddReportRulesModal> |
|
||||
</> |
|
||||
, |
|
||||
}, |
|
||||
|
|
||||
]} |
|
||||
/> |
|
||||
|
|
||||
</> |
|
||||
) |
|
||||
} |
|
||||
|
|
||||
function mapStateToProps(state) { |
|
||||
const { auth, structureList, global } = state |
|
||||
return { |
|
||||
user: auth.user, |
|
||||
struList: structureList.data || [], |
|
||||
struLoading: structureList.isRequesting, |
|
||||
actions: global.actions, |
|
||||
} |
|
||||
} |
|
||||
export default connect(mapStateToProps)(patrolReport); |
|
@ -1,136 +0,0 @@ |
|||||
import React, { useState, useRef, useEffect } from 'react'; |
|
||||
import { connect } from 'react-redux'; |
|
||||
import { Button, Popconfirm, Tag } from 'antd'; |
|
||||
import ProTable from '@ant-design/pro-table'; |
|
||||
import PlanTemplateModal from '../components/planTemplateModal'; |
|
||||
import { createPatrolTemplate, delPatrolTemplate, updatePatrolTemplate, getPatrolTemplate } from '../actions/template'; |
|
||||
import { getCheckItemsGroup } from '../actions/checkItems'; |
|
||||
|
|
||||
function PatrolTemplate(props) { |
|
||||
const { dispatch, user } = props; |
|
||||
const tableRef = useRef(); |
|
||||
const [dataSource, setDataSource] = useState([{}]); |
|
||||
const [visible, setVisible] = useState(false); |
|
||||
const [type, setType] = useState(); |
|
||||
const [curRecord, setCurRecord] = useState(); |
|
||||
|
|
||||
useEffect(() => { |
|
||||
dispatch(getCheckItemsGroup()) |
|
||||
}, []) |
|
||||
|
|
||||
const columns = [{ |
|
||||
title: '模板名称', |
|
||||
dataIndex: 'name', |
|
||||
key: 'name', |
|
||||
ellipsis: true, |
|
||||
}, { |
|
||||
title: '模板描述', |
|
||||
dataIndex: 'describe', |
|
||||
key: 'describe', |
|
||||
ellipsis: true, |
|
||||
search: false, |
|
||||
}, { |
|
||||
title: '操作人', |
|
||||
dataIndex: 'user.name', |
|
||||
key: 'user.name', |
|
||||
ellipsis: true, |
|
||||
search: false, |
|
||||
render: (t, r, i) => { |
|
||||
return r.user ? r.user.name : '-' |
|
||||
} |
|
||||
}, { |
|
||||
title: '检查项', |
|
||||
dataIndex: 'checkItems', |
|
||||
key: 'checkItems', |
|
||||
ellipsis: true, |
|
||||
search: false, |
|
||||
render: (_, r) => { |
|
||||
return r?.checkItems ? r?.checkItems.map(c => <Tag>{c.name}</Tag>) : '-' |
|
||||
} |
|
||||
}, { |
|
||||
title: '操作', |
|
||||
dataIndex: 'action', |
|
||||
key: 'action', |
|
||||
search: false, |
|
||||
width: 200, |
|
||||
render: (_, record) => { |
|
||||
return <> |
|
||||
<Button type="link" onClick={() => { |
|
||||
setType('edit') |
|
||||
setCurRecord(record) |
|
||||
setVisible(true) |
|
||||
}}>修改</Button> |
|
||||
<Popconfirm |
|
||||
title="确认删除?" |
|
||||
onConfirm={() => { |
|
||||
dispatch(delPatrolTemplate(record.id)).then(res => { |
|
||||
if (res.success) { |
|
||||
tableRef.current.reload(); |
|
||||
} |
|
||||
}) |
|
||||
}}> |
|
||||
<Button type="link" danger disabled={record && record.patrolPlans && record.patrolPlans.length}>删除</Button> |
|
||||
</Popconfirm> |
|
||||
</> |
|
||||
}, |
|
||||
}]; |
|
||||
|
|
||||
return ( |
|
||||
<> |
|
||||
<ProTable |
|
||||
columns={columns} |
|
||||
actionRef={tableRef} |
|
||||
options={false} |
|
||||
dataSource={dataSource || []} |
|
||||
rowKey='id' |
|
||||
pagination={{ pageSize: 10, size: 'default', className: 'global-pagination' }} |
|
||||
search={{ |
|
||||
defaultCollapsed: false, |
|
||||
optionRender: (searchConfig, formProps, dom) => [ |
|
||||
...dom.reverse(), |
|
||||
<Button |
|
||||
type="primary" |
|
||||
key="primary" |
|
||||
onClick={() => { |
|
||||
setType('create') |
|
||||
setVisible(true) |
|
||||
}} |
|
||||
>新增巡检模板</Button>, |
|
||||
], |
|
||||
}} |
|
||||
request={async (params = {}) => { |
|
||||
const res = await dispatch(getPatrolTemplate(params)); |
|
||||
setDataSource(res?.payload.data?.rows); |
|
||||
return { ...res }; |
|
||||
}} |
|
||||
onReset={() => { }} |
|
||||
rowClassName={(record, index) => { |
|
||||
let className = 'global-light-row'; |
|
||||
if (index % 2 === 1) className = 'global-dark-row'; |
|
||||
return className; |
|
||||
}} |
|
||||
/> |
|
||||
{ |
|
||||
visible ? |
|
||||
<PlanTemplateModal |
|
||||
visible={visible} |
|
||||
type={type} |
|
||||
curRecord={curRecord} |
|
||||
onCancel={() => { |
|
||||
setVisible(false); |
|
||||
setCurRecord({}) |
|
||||
}} |
|
||||
tableRef={tableRef} |
|
||||
/> : null |
|
||||
} |
|
||||
</> |
|
||||
) |
|
||||
} |
|
||||
|
|
||||
function mapStateToProps(state) { |
|
||||
const { auth } = state |
|
||||
return { |
|
||||
user: auth.user |
|
||||
} |
|
||||
} |
|
||||
export default connect(mapStateToProps)(PatrolTemplate); |
|
@ -1,300 +0,0 @@ |
|||||
import React, { useState, useRef, useEffect } from 'react'; |
|
||||
import { connect } from 'react-redux'; |
|
||||
import { Button, Popconfirm, Tag,Tabs } from 'antd'; |
|
||||
import ProTable from '@ant-design/pro-table'; |
|
||||
import Xiafagaojin from '../components/xiafagaojin'; |
|
||||
import {getDepUser} from '../../organization/actions/user' |
|
||||
import { createPatrolTemplate, delPatrolTemplate, updatePatrolTemplate, getPatrolTemplate } from '../actions/template'; |
|
||||
import { getCheckItemsGroup } from '../actions/checkItems'; |
|
||||
import moment from 'moment'; |
|
||||
function YujingGuanli (props) { |
|
||||
const { dispatch, user,actions,depUser} = props; |
|
||||
const tableRef = useRef(); |
|
||||
const format = 'YYYY-MM-DD HH:mm:ss' |
|
||||
const { patrolManage } = actions |
|
||||
const [dataSource, setDataSource] = useState([{}]); |
|
||||
const [dataSource2, setDataSource2] = useState([{}]); |
|
||||
const [visible, setVisible] = useState(false); |
|
||||
const [type, setType] = useState(); |
|
||||
const [curRecord, setCurRecord] = useState(); |
|
||||
const [tabs,settabs] = useState(1) |
|
||||
const [data,setdata]= useState([]) |
|
||||
const [tableList, settableList] = useState([]) |
|
||||
const [name, setName] = useState(''); |
|
||||
const [curState, setCurState] = useState('全部'); |
|
||||
const times = [moment().subtract(70, 'years').format(format), moment().format(format)] |
|
||||
const [search, setSearch] = useState({ name: null, time: [times[0], times[1]], state: 'null' }) |
|
||||
const STATE_TEXT = { 1: '待制定计划', 2: '待审核', 3: '计划驳回', 4: '待维修', 5: '待验收', 6: '验收通过', 7: '验收不通过', } |
|
||||
const onChange = (key) => { |
|
||||
settabs(key) |
|
||||
}; |
|
||||
const renderOptionText = (currentState) => { |
|
||||
let text = '待制定计划' |
|
||||
|
|
||||
return STATE_TEXT[currentState] || text |
|
||||
} |
|
||||
const queryData = () => { |
|
||||
dispatch(patrolManage.records(`patrolRecord/all/${times[0]}/${times[1]}/true/null`)).then(res => { |
|
||||
if (res.success) { |
|
||||
console.log(res,'水平') |
|
||||
|
|
||||
// res?.payload?.data?.map(i=>{
|
|
||||
// if(obj[i?.points?.project?.id]){
|
|
||||
// // if(obj[i?.points?.project?.id.toString()][i.pointId.toString()]){
|
|
||||
// // obj[i?.points?.project?.id.toString()][i.pointId.toString()].ponintname=i.points?.itemData?.name
|
|
||||
// // obj[i?.points?.project?.id.toString()][i.pointId.toString()].num=obj[i?.points?.project?.id.toString()][i.pointId.toString()].num+i?.patrolRecordIssueHandles[0]?.state==6?1:0
|
|
||||
|
|
||||
// // }else{
|
|
||||
// // obj[i?.points?.project?.id.toString()][i.pointId.toString()].ponintname=i.points?.itemData?.name
|
|
||||
// // obj[i?.points?.project?.id.toString()][i.pointId.toString()].num=i?.patrolRecordIssueHandles[0]?.state==6?1:0
|
|
||||
// // }
|
|
||||
// obj[i?.points?.project?.id]?.push({pointId:i.pointId,pointname:i.points.itemData.name})
|
|
||||
// // i?patrolRecordIssueHandles[0]?.state==6
|
|
||||
// obj[i?.points?.project?.id].num= obj[i?.points?.project?.id].num + i?.patrolRecordIssueHandles[0]?.state==6 ?1:0
|
|
||||
// }else{
|
|
||||
// obj[i?.points?.project?.id]={name:i?.points?.project?.name,num:i?.patrolRecordIssueHandles[0]?.state==6 ?1:0 }
|
|
||||
|
|
||||
// }
|
|
||||
// console.log(obj,'obj')
|
|
||||
// })
|
|
||||
|
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
console.log(depUser,'depUser') |
|
||||
useEffect(() => { |
|
||||
|
|
||||
dispatch(getDepUser()) |
|
||||
queryData() |
|
||||
// dispatch(getCheckItemsGroup())
|
|
||||
}, []) |
|
||||
// console.log(tableList,'tablist')
|
|
||||
const columns = [{ |
|
||||
title: '结构物名称', |
|
||||
dataIndex: 'name', |
|
||||
key: 'name', |
|
||||
// search: false,
|
|
||||
ellipsis: true, |
|
||||
render: (t, r, i) => { |
|
||||
// console.log(r,'测试')
|
|
||||
return r?.points?.project?.name |
|
||||
} |
|
||||
}, { |
|
||||
title: '点位名称', |
|
||||
dataIndex: 'pointname', |
|
||||
key: 'pointname', |
|
||||
search: false, |
|
||||
ellipsis: true, |
|
||||
render: (t, r, i) => { |
|
||||
// console.log(r,'测试')
|
|
||||
return r?.points?.itemData?.name |
|
||||
} |
|
||||
}, { |
|
||||
title: '异常次数', |
|
||||
dataIndex: 'yanshoucishu', |
|
||||
key: 'yanshoucishu', |
|
||||
ellipsis: true, |
|
||||
search: false, |
|
||||
render: (t, r, i) => { |
|
||||
|
|
||||
return r?.patrolRecordIssueHandles && r?.patrolRecordIssueHandles[0]?.yanshoucishu |
|
||||
} |
|
||||
}, { |
|
||||
title: '产生时间', |
|
||||
dataIndex: 'yujingshijian', |
|
||||
key: 'yujingshijia', |
|
||||
ellipsis: true, |
|
||||
search: false, |
|
||||
render: (_, r) => { |
|
||||
return r?.patrolRecordIssueHandles && moment(r?.patrolRecordIssueHandles[0]?.yujingshijian).format('YYYY-MM-DD HH:mm:ss') |
|
||||
} |
|
||||
}, { |
|
||||
title: '更新时间', |
|
||||
dataIndex: 'updatatime', |
|
||||
key: 'updatatime', |
|
||||
search: false, |
|
||||
ellipsis: true, |
|
||||
render: (_, r) => { |
|
||||
return r?.patrolRecordIssueHandles && moment(r?.patrolRecordIssueHandles[0]?.yanshoushijian).format('YYYY-MM-DD HH:mm:ss') |
|
||||
} |
|
||||
}, { |
|
||||
title: '操作', |
|
||||
dataIndex: 'action', |
|
||||
key: 'action', |
|
||||
search: false, |
|
||||
width: 200, |
|
||||
render: (_, record) => { |
|
||||
return <> |
|
||||
<Button type="link" onClick={() => { |
|
||||
setType('edit') |
|
||||
setCurRecord(record) |
|
||||
setVisible(true) |
|
||||
}}>下发告警</Button> |
|
||||
|
|
||||
</> |
|
||||
}, |
|
||||
}]; |
|
||||
const columns1 = [{ |
|
||||
title: '结构物名称', |
|
||||
dataIndex: 'name', |
|
||||
key: 'name', |
|
||||
// search: false,
|
|
||||
ellipsis: true, |
|
||||
render: (t, r, i) => { |
|
||||
// console.log(r,'测试')
|
|
||||
return r?.points?.project?.name |
|
||||
} |
|
||||
}, { |
|
||||
title: '点位名称', |
|
||||
dataIndex: 'pointname', |
|
||||
key: 'pointname', |
|
||||
search: false, |
|
||||
ellipsis: true, |
|
||||
render: (t, r, i) => { |
|
||||
// console.log(r,'测试')
|
|
||||
return r?.points?.itemData?.name |
|
||||
} |
|
||||
}, { |
|
||||
title: '异常次数', |
|
||||
dataIndex: 'yanshoucishu', |
|
||||
key: 'yanshoucishu', |
|
||||
ellipsis: true, |
|
||||
search: false, |
|
||||
render: (t, r, i) => { |
|
||||
// console.log(r,'r')
|
|
||||
return r?.patrolRecordIssueHandles && r?.patrolRecordIssueHandles[0]?.yanshoucishu |
|
||||
} |
|
||||
}, { |
|
||||
title: '下发时间', |
|
||||
dataIndex: 'yujingshijian', |
|
||||
key: 'yujingshijia', |
|
||||
ellipsis: true, |
|
||||
search: false, |
|
||||
render: (_, r) => { |
|
||||
return r?.patrolRecordIssueHandles && moment(r?.patrolRecordIssueHandles[0]?.yujingshijian).format('YYYY-MM-DD HH:mm:ss') |
|
||||
} |
|
||||
}]; |
|
||||
return ( |
|
||||
<> |
|
||||
<Tabs |
|
||||
activeKey={tabs} |
|
||||
onChange={onChange} |
|
||||
style={{marginLeft:'20px',marginRight:'20px'}} |
|
||||
items={[ |
|
||||
{ |
|
||||
label: `未告警`, |
|
||||
key: 1, |
|
||||
children: <ProTable |
|
||||
columns={columns} |
|
||||
actionRef={tableRef} |
|
||||
options={false} |
|
||||
dataSource={dataSource || []} |
|
||||
rowKey='id' |
|
||||
pagination={{ pageSize: 10 }} |
|
||||
// search={false}
|
|
||||
request={async (params = {}) => { |
|
||||
// dispatch(patrolManage.records(`patrolRecord/all/${times[0]}/${times[1]}/true/null`)).then(res => {
|
|
||||
// if (res.success) {
|
|
||||
// console.log(res,'水平')
|
|
||||
// const t1 = res?.payload?.data?.filter(i=>i.patrolRecordIssueHandles[0]?.isgaojing!==true&& i.patrolRecordIssueHandles[0]?.yanshoucishu>=3)
|
|
||||
// }
|
|
||||
// })
|
|
||||
const res = await dispatch(patrolManage.records(`patrolRecord/all/${times[0]}/${times[1]}/true/null`)); |
|
||||
const data = res?.payload?.data?.filter(i=>{ |
|
||||
|
|
||||
return i?.patrolRecordIssueHandles[0]?.yanshoucishu>2&&i?.patrolRecordIssueHandles[0]?.isgaojing!==true |
|
||||
&&res?.payload?.data?.filter(j=>j?.pointId===i?.pointId&&j?.points?.project?.id===i?.points?.project?.id |
|
||||
&&j?.patrolRecordIssueHandles[0]?.yujingshijian |
|
||||
&&i?.patrolRecordIssueHandles[0]?.yujingshijian |
|
||||
&&moment(i?.patrolRecordIssueHandles[0].yanshoushijian).valueOf()<moment(j?.patrolRecordIssueHandles[0]?.yanshoushijian).valueOf() |
|
||||
).length===0 |
|
||||
}) |
|
||||
// console.log(res,'res')
|
|
||||
// console.log(data,'data')
|
|
||||
// setDataSource(res?.payload?.data.filter(i=>i?.points?.project?.name.match(params.name)));
|
|
||||
setDataSource(data.filter(i=>i?.points?.project?.name.match(params.name))); |
|
||||
}} |
|
||||
/>, |
|
||||
}, |
|
||||
{ |
|
||||
label: `已告警`, |
|
||||
key: 2, |
|
||||
children: <ProTable |
|
||||
columns={columns1} |
|
||||
actionRef={tableRef} |
|
||||
options={false} |
|
||||
dataSource={dataSource2 || []} |
|
||||
rowKey='id' |
|
||||
pagination={{ pageSize: 10 }} |
|
||||
// search={false}
|
|
||||
request={async (params = {}) => { |
|
||||
const res = await dispatch(patrolManage.records(`patrolRecord/all/${times[0]}/${times[1]}/true/null`)); |
|
||||
const data = res?.payload?.data?.filter(i=>{ |
|
||||
return i?.patrolRecordIssueHandles[0]?.isgaojing===true&&i?.patrolRecordIssueHandles[0]?.yujingafchishu===null |
|
||||
// &&res?.payload?.data?.filter(j=>
|
|
||||
// {
|
|
||||
// return j?.pointId===i?.pointId
|
|
||||
// &&j?.points?.project?.id===i?.points?.project?.id&&i?.patrolRecordIssueHandles[0]?.yujingshijian&&
|
|
||||
// parseInt(moment(i?.patrolRecordIssueHandles[0].yujingshijian).format('YYYYMMDDHHMMSS'))<parseInt(moment(j?.patrolRecordIssueHandles[0]?.yujingshijian).format('YYYYMMDDHHMMSS'))
|
|
||||
// }).length===0
|
|
||||
}) |
|
||||
console.log(data,'data') |
|
||||
setDataSource2(data.filter(i=>i?.points?.project?.name.match(params.name)).sort((a, b) => moment(b.patrolRecordIssueHandles[0].yanshoushijian).valueOf() - moment(a.patrolRecordIssueHandles[0].yanshoushijian).valueOf())); |
|
||||
|
|
||||
}} |
|
||||
/>, |
|
||||
} |
|
||||
]} |
|
||||
/> |
|
||||
{ |
|
||||
visible &&depUser.filter(i=>i.username&&i.email).length!==0 ? |
|
||||
<Xiafagaojin |
|
||||
visible={visible} |
|
||||
type={type} |
|
||||
curRecord={curRecord} |
|
||||
userlist={depUser.filter(i=>i.username&&i.email)} |
|
||||
onCancel={() => { |
|
||||
setVisible(false); |
|
||||
setCurRecord({}) |
|
||||
}} |
|
||||
onHandle={async ()=>{ |
|
||||
const res = await dispatch(patrolManage.records(`patrolRecord/all/${times[0]}/${times[1]}/true/null`)); |
|
||||
const data2 = res?.payload?.data?.filter(i=>{ |
|
||||
return i?.patrolRecordIssueHandles[0]?.isgaojing===true&&i?.patrolRecordIssueHandles[0]?.yujingafchishu===null |
|
||||
// &&res?.payload?.data?.filter(j=>
|
|
||||
// {
|
|
||||
// return j?.pointId===i?.pointId
|
|
||||
// &&j?.points?.project?.id===i?.points?.project?.id&&i?.patrolRecordIssueHandles[0]?.yujingshijian&&
|
|
||||
// parseInt(moment(i?.patrolRecordIssueHandles[0].yujingshijian).format('YYYYMMDDHHMMSS'))<parseInt(moment(j?.patrolRecordIssueHandles[0]?.yujingshijian).format('YYYYMMDDHHMMSS'))
|
|
||||
// }).length===0
|
|
||||
}) |
|
||||
// console.log(data,'data')
|
|
||||
const data = res?.payload?.data?.filter(i=>{ |
|
||||
return i?.patrolRecordIssueHandles[0]?.yanshoucishu>2&&i?.patrolRecordIssueHandles[0]?.isgaojing!==true |
|
||||
&&res?.payload?.data?.filter(j=>j?.pointId===i?.pointId |
|
||||
&&j?.points?.project?.id===i?.points?.project?.id |
|
||||
&&moment(i?.patrolRecordIssueHandles[0].yanshoushijian).valueOf()<moment(j?.patrolRecordIssueHandles[0]?.yanshoushijian).valueOf() |
|
||||
).length===0 |
|
||||
}) |
|
||||
console.log(res,'res') |
|
||||
// setDataSource(res?.payload?.data.filter(i=>i?.points?.project?.name.match(params.name)));
|
|
||||
setDataSource(data); |
|
||||
setDataSource2(data2.sort((a, b) => moment(b.patrolRecordIssueHandles[0].yanshoushijian).valueOf() - moment(a.patrolRecordIssueHandles[0].yanshoushijian).valueOf())); |
|
||||
settabs(2) |
|
||||
}} |
|
||||
tableRef={tableRef} |
|
||||
/> : null |
|
||||
} |
|
||||
</> |
|
||||
) |
|
||||
} |
|
||||
|
|
||||
function mapStateToProps (state) { |
|
||||
const { auth, global ,depUser} = state |
|
||||
return { |
|
||||
user: auth.user, |
|
||||
actions: global.actions, |
|
||||
depUser: depUser.data || [], |
|
||||
} |
|
||||
} |
|
||||
export default connect(mapStateToProps)(YujingGuanli); |
|
@ -1,15 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
import reducers from './reducers'; |
|
||||
import routes from './routes'; |
|
||||
import actions from './actions'; |
|
||||
import { getNavItem } from './nav-item'; |
|
||||
|
|
||||
export default { |
|
||||
key: 'patrolManage', |
|
||||
name: '', |
|
||||
reducers: reducers, |
|
||||
routes: routes, |
|
||||
actions: actions, |
|
||||
getNavItem: getNavItem |
|
||||
}; |
|
@ -1,34 +0,0 @@ |
|||||
import React from 'react'; |
|
||||
import { Link } from 'react-router-dom'; |
|
||||
import { Menu } from 'antd'; |
|
||||
import { GatewayOutlined } from '@ant-design/icons'; |
|
||||
import { Func } from '$utils'; |
|
||||
const SubMenu = Menu.SubMenu; |
|
||||
|
|
||||
export function getNavItem (user, dispatch) { |
|
||||
// if (!Func.isAuthorized("ORG_MANAGE")) {
|
|
||||
// return null
|
|
||||
// }
|
|
||||
return ( |
|
||||
Func.isAuthorized('PATROL_MANAGE') && <SubMenu key="patrolManage" icon={<img src='/assets/images/menu/xun.svg' style={{ width: 24, height: 24 }} />} title={'巡检管理'}> |
|
||||
{Func.isAuthorized('PATROL_PLAN_CONFIG') && <Menu.Item key="patrolPlan"> |
|
||||
<Link to="/patrolManage/patrolPlan">巡检计划制定</Link> |
|
||||
</Menu.Item>} |
|
||||
{Func.isAuthorized('PATROL_RECORD_VIEW') && <Menu.Item key="patrolRecord"> |
|
||||
<Link to="/patrolManage/patrolRecord">巡检记录</Link> |
|
||||
</Menu.Item>} |
|
||||
{Func.isAuthorized('CHECKREPORT') && <Menu.Item key="patrolReport"> |
|
||||
<Link to="/patrolManage/patrolReport">巡检报告</Link> |
|
||||
</Menu.Item>} |
|
||||
{Func.isAuthorized('CHECKITEMSET') && <Menu.Item key="checkItems"> |
|
||||
<Link to="/patrolManage/checkItems">检查项设定</Link> |
|
||||
</Menu.Item>} |
|
||||
{Func.isAuthorized('CHECKMOULD') && <Menu.Item key="patrolTemplate"> |
|
||||
<Link to="/patrolManage/patrolTemplate">巡检模板</Link> |
|
||||
</Menu.Item>} |
|
||||
{ <Menu.Item key="yujingguanli"> |
|
||||
<Link to="/patrolManage/yujingguanli">预警管理</Link> |
|
||||
</Menu.Item>} |
|
||||
</SubMenu> |
|
||||
); |
|
||||
} |
|
@ -1,5 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
export default { |
|
||||
|
|
||||
}; |
|
@ -1,32 +0,0 @@ |
|||||
'use strict'; |
|
||||
import * as actionTypes from '../actions/record'; |
|
||||
import Immutable from 'immutable'; |
|
||||
|
|
||||
const initState = { |
|
||||
data: {}, |
|
||||
isRequesting: false, |
|
||||
error: null |
|
||||
}; |
|
||||
|
|
||||
function record(state = initState, action) { |
|
||||
const payload = action.payload; |
|
||||
switch (action.type){ |
|
||||
case actionTypes.GET_PATROL_RECORD_LIST: |
|
||||
return Immutable.fromJS(state).set('data', |
|
||||
payload.data).toJS(); |
|
||||
case actionTypes.GET_PATROL_RECORD_LIST_SUCCESS: |
|
||||
return Immutable.fromJS(state).merge({ |
|
||||
isRequesting: false, |
|
||||
data: payload.data |
|
||||
}).toJS(); |
|
||||
case actionTypes.GET_PATROL_RECORD_LIST_ERROR: |
|
||||
return Immutable.fromJS(state).merge({ |
|
||||
isRequesting: false, |
|
||||
error: payload.error |
|
||||
}).toJS(); |
|
||||
default: |
|
||||
return state; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
export default record; |
|
@ -1,44 +0,0 @@ |
|||||
'use strict'; |
|
||||
import { PatrolPlan, PatrolReocrd, PatrolReport, CheckItems, PlanTemplate ,YujingGuanli} from './containers'; |
|
||||
|
|
||||
export default [{ |
|
||||
type: 'inner', |
|
||||
route: { |
|
||||
path: '/patrolManage', |
|
||||
key: 'patrolManage', |
|
||||
breadcrumb: '巡检管理', |
|
||||
childRoutes: [{ |
|
||||
path: '/patrolPlan', |
|
||||
key: 'patrolPlan', |
|
||||
component: PatrolPlan, |
|
||||
breadcrumb: '巡检计划制定', |
|
||||
}, { |
|
||||
path: '/patrolRecord', |
|
||||
key: 'patrolRecord', |
|
||||
component: PatrolReocrd, |
|
||||
breadcrumb: '巡检记录', |
|
||||
}, { |
|
||||
path: '/patrolReport', |
|
||||
key: 'patrolReport', |
|
||||
component: PatrolReport, |
|
||||
breadcrumb: '巡检报告', |
|
||||
}, { |
|
||||
path: '/checkItems', |
|
||||
key: 'checkItems', |
|
||||
component: CheckItems, |
|
||||
breadcrumb: '检查项设定', |
|
||||
}, { |
|
||||
path: '/patrolTemplate', |
|
||||
key: 'patrolTemplate', |
|
||||
component: PlanTemplate, |
|
||||
breadcrumb: '巡检模板', |
|
||||
}, |
|
||||
{ |
|
||||
path: '/yujingguanli', |
|
||||
key: 'yujingguanli', |
|
||||
component: YujingGuanli, |
|
||||
breadcrumb: '预警管理', |
|
||||
} |
|
||||
] |
|
||||
} |
|
||||
}]; |
|
@ -1,5 +0,0 @@ |
|||||
.patrol-record-detail-modal { |
|
||||
.ant-collapse>.ant-collapse-item>.ant-collapse-header { |
|
||||
padding: 0 |
|
||||
} |
|
||||
} |
|
@ -1,6 +0,0 @@ |
|||||
|
|
||||
'use strict'; |
|
||||
import projectBinding from './projectBinding' |
|
||||
export default { |
|
||||
...projectBinding |
|
||||
} |
|
@ -1,59 +0,0 @@ |
|||||
'use strict'; |
|
||||
import { basicAction } from '@peace/utils' |
|
||||
import { ApiTable } from '$utils' |
|
||||
|
|
||||
export function getanxinyunProject(data) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'post', |
|
||||
dispatch: dispatch, |
|
||||
data, |
|
||||
actionType: 'GET_ANXINYUN_PROJECT', |
|
||||
url: `${ApiTable.getanxinyunProject}`, |
|
||||
msg: { error: '获取安心云结构物失败' }, |
|
||||
reducer: { name: 'anxinyunProject'} |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
export function addorEditRelation(data) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'post', |
|
||||
dispatch: dispatch, |
|
||||
data, |
|
||||
actionType: 'ADD_OR_EDIT_RELATION', |
|
||||
url: `${ApiTable.addorEditRelation}`, |
|
||||
msg: { option:data?.id? '编辑绑定关系':'新增绑定关系' }, |
|
||||
// reducer: { name: 'anxinyunProject'}
|
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function getRelation(query) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'get', |
|
||||
query, |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'GET_RELATION', |
|
||||
url: `${ApiTable.getRelation}`, |
|
||||
msg: { error:'查询项目映射关系失败' }, |
|
||||
reducer: { name: 'relation'} |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function delRelation(id) { |
|
||||
return dispatch => basicAction({ |
|
||||
type: 'delete', |
|
||||
dispatch: dispatch, |
|
||||
actionType: 'DEL_RELATION', |
|
||||
url: ApiTable.delRelation.replace('{id}', id), |
|
||||
msg: { option:'删除项目映射关系' }, |
|
||||
// reducer: { name: 'anxinyunProject'}
|
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
export default{ |
|
||||
getanxinyunProject, |
|
||||
getRelation, |
|
||||
addorEditRelation, |
|
||||
delRelation |
|
||||
} |
|
@ -1,88 +0,0 @@ |
|||||
import React, { useRef,useState,useEffect } from 'react' |
|
||||
import { Button, Form } from 'antd' |
|
||||
import { connect } from 'react-redux'; |
|
||||
import { InfoCircleOutlined } from '@ant-design/icons' |
|
||||
import { ModalForm, ProFormSelect, ProFormText, ProFormDatePicker } from '@ant-design/pro-form' |
|
||||
import moment from 'moment' |
|
||||
function RelationModal(props) { |
|
||||
const { title, triggerRender, editData = null, onFinish, devices,actions,dispatch,proejctListOpt,structureListOpt } = props |
|
||||
const{projectBinding}=actions |
|
||||
const formItemLayout = { labelCol: { span: 6 }, wrapperCol: { span: 16 } } |
|
||||
const initialValues = editData? { ...editData,} : {} |
|
||||
const [form] = Form.useForm() |
|
||||
const formRef = useRef() |
|
||||
|
|
||||
|
|
||||
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 => { |
|
||||
// console.log('values1',editData)
|
|
||||
let value={ |
|
||||
anxinyunProject:values?.anxinyunProject, |
|
||||
structName:values?.structName, |
|
||||
id:initialValues?initialValues.key:null |
|
||||
} |
|
||||
return onFinish && (await onFinish(value)) |
|
||||
// return true;
|
|
||||
}} |
|
||||
width={500}> |
|
||||
<ProFormSelect |
|
||||
rules={[{ required: true, message: '安心云结构物' }]} |
|
||||
showSearch |
|
||||
options={proejctListOpt?.map(s => { |
|
||||
return { label: s.label, value: s.value } |
|
||||
})} |
|
||||
name='anxinyunProject' |
|
||||
label='安心云结构物' |
|
||||
/> |
|
||||
<ProFormSelect |
|
||||
rules={[{ required: true, message: '关联结构物' }]} |
|
||||
showSearch |
|
||||
options={structureListOpt?.map(s => { |
|
||||
return { label: s.label, value: s.value } |
|
||||
})} |
|
||||
name='structName' |
|
||||
label='关联结构物' |
|
||||
/> |
|
||||
</ModalForm> |
|
||||
) |
|
||||
} |
|
||||
function mapStateToProps(state) { |
|
||||
const {auth, global, device } = state; |
|
||||
return { |
|
||||
loading: device.isRequesting, |
|
||||
clientHeight: global.clientHeight, |
|
||||
actions: global.actions, |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
export const DEVICE_TYPES = [ |
|
||||
'安防系统', |
|
||||
'厨房系统', |
|
||||
'电梯', |
|
||||
'供电系统', |
|
||||
'空调', |
|
||||
'排水系统', |
|
||||
'水系统', |
|
||||
'通道门禁', |
|
||||
'通风系统', |
|
||||
'通信系统', |
|
||||
'显示视频', |
|
||||
'消防系统', |
|
||||
'照明系统', |
|
||||
] |
|
||||
export default connect(mapStateToProps)(RelationModal) |
|
@ -1,5 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
import ProjectBinding from './projectBinding' |
|
||||
|
|
||||
export { ProjectBinding }; |
|
@ -1,304 +0,0 @@ |
|||||
import React, { useEffect, useState, useRef, useMemo } from 'react' |
|
||||
import { Spin, Popconfirm, message, Button, Input, Select } from 'antd' |
|
||||
import { connect } from 'react-redux' |
|
||||
import ProTable from '@ant-design/pro-table' |
|
||||
import moment from 'moment' |
|
||||
import RelationModal from '../components/relationModal' |
|
||||
function ProjectBinding(props) { |
|
||||
const {loading, clientHeight, actions, dispatch, devices,anxinyunProjectLoading,relationLoading } = props |
|
||||
const { projectBinding, projectRegime } = actions |
|
||||
const tableRef = useRef() |
|
||||
const proTableFormRef = useRef() |
|
||||
const [proejctListOpt, setProjectListOpt] = useState([])//安心云结构物
|
|
||||
const [structureListOpt, setStructureListOpt] = useState([])//巡检结构物
|
|
||||
const [dataSource, setDataSource] = useState([]) |
|
||||
// const [dataCopy,setDataCopy]=useState([])
|
|
||||
const [tableParams, setTableParams] = useState({}) |
|
||||
// const fetchData = async () => {
|
|
||||
// let data={
|
|
||||
// url:"users/{orgId}/projects",
|
|
||||
// type:"get"
|
|
||||
// }
|
|
||||
// dispatch(projectBinding.getanxinyunProject(data)).then(async res=>{
|
|
||||
// if(res.success){
|
|
||||
// const d=res.payload.data?.map(item=>{
|
|
||||
// return {
|
|
||||
// label:item?.projects[0]?.name,
|
|
||||
// value:item?.projects[0]?.id
|
|
||||
// }
|
|
||||
// })
|
|
||||
// setProjectListOpt(d)
|
|
||||
// const r2= await dispatch(projectRegime.getProjectList())
|
|
||||
// const dp=r2.pauseStatemap(item=>{
|
|
||||
// return {
|
|
||||
// label:item?.name,
|
|
||||
// value:item?.id
|
|
||||
// }
|
|
||||
// })
|
|
||||
// setStructureListOpt(dp)
|
|
||||
// const r= await dispatch(projectBinding.getRelation())
|
|
||||
// const list = r?.payload?.data?.rows?.map(item=>{
|
|
||||
// return {
|
|
||||
// key: item.id,
|
|
||||
// anxinyunProject:d?.find(q=>q.value===item.axyProjectId)?.label,
|
|
||||
// structName:dp?.find(q=>q.value===item.structureId)?.label
|
|
||||
// }
|
|
||||
// })
|
|
||||
// setDataSource(list)
|
|
||||
// }
|
|
||||
// })
|
|
||||
|
|
||||
// }
|
|
||||
//初始化
|
|
||||
useEffect(() => { |
|
||||
let data = { |
|
||||
url:'organizations/{orgId}/structures', |
|
||||
// url: 'users/{orgId}/projects',
|
|
||||
type: 'get', |
|
||||
} |
|
||||
dispatch(projectBinding.getanxinyunProject(data)).then(res => { |
|
||||
if (res.success) { |
|
||||
const d = res.payload.data?.map(item => { |
|
||||
return { |
|
||||
label: item?.name, |
|
||||
value: item?.iotaThingId, |
|
||||
} |
|
||||
}) |
|
||||
setProjectListOpt(d) |
|
||||
} |
|
||||
}) |
|
||||
dispatch(projectRegime.getProjectList()).then(res => { |
|
||||
if (res.success) { |
|
||||
const dp = res.payload.data?.rows?.map(item => { |
|
||||
return { |
|
||||
label: item?.name, |
|
||||
value: item?.id, |
|
||||
} |
|
||||
}) |
|
||||
setStructureListOpt(dp) |
|
||||
} |
|
||||
}) |
|
||||
}, []) |
|
||||
const queryData = () => { |
|
||||
dispatch(projectBinding.getRelation()).then(res => { |
|
||||
if (res.success) { |
|
||||
const list = res?.payload?.data?.rows?.map(item => { |
|
||||
return { |
|
||||
key: item.id, |
|
||||
anxinyunProject: proejctListOpt?.find(q => q.value === item.axyProjectId)?.value, |
|
||||
structName: structureListOpt?.find(q => q.value === item.structureId)?.value, |
|
||||
} |
|
||||
}) |
|
||||
setDataSource(list) |
|
||||
// setDataCopy(list)
|
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
useEffect(() => { |
|
||||
if (proejctListOpt && structureListOpt && proejctListOpt.length && structureListOpt.length) { |
|
||||
queryData() |
|
||||
} |
|
||||
}, [proejctListOpt, structureListOpt]) |
|
||||
|
|
||||
const onFinish = async values => { |
|
||||
const dataToSave = { axyProjectId: values?.anxinyunProject, structrueId: values?.structName, id: values?.id } |
|
||||
return dispatch(projectBinding.addorEditRelation(dataToSave)).then(res => { |
|
||||
if (res.success) { |
|
||||
queryData() |
|
||||
// tableRef.current.reload()
|
|
||||
return true |
|
||||
} else { |
|
||||
return false |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
//删除按钮
|
|
||||
const handleDelete = id => { |
|
||||
dispatch(projectBinding.delRelation(id)).then(res => { |
|
||||
if (res.success) { |
|
||||
queryData() |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
const filterOption = (input, option) => (option?.label ?? '').toLowerCase().includes(input.toLowerCase()) |
|
||||
|
|
||||
const columns = [ |
|
||||
{ |
|
||||
title: '安心云结构物', |
|
||||
dataIndex: 'anxinyunProject', |
|
||||
ellipsis: true, |
|
||||
valueType: 'select', |
|
||||
fieldProps: { |
|
||||
options: proejctListOpt, |
|
||||
}, |
|
||||
renderFormItem: () => ( |
|
||||
<Select |
|
||||
showSearch |
|
||||
// style={{paddingLeft:10}}
|
|
||||
allowClear |
|
||||
placeholder='请选择' |
|
||||
options={proejctListOpt?.map(item => ({ label: item.label, value: item.value }))} |
|
||||
filterOption={filterOption} |
|
||||
optionFilterProp='children'></Select> |
|
||||
), |
|
||||
// fieldProps: {
|
|
||||
// showSearch: true,
|
|
||||
// defaultValue: '',
|
|
||||
// },
|
|
||||
// onFilter: (value, record) => record.name.includes(value),
|
|
||||
// search:false
|
|
||||
}, |
|
||||
{ |
|
||||
title: '结构物名称', |
|
||||
dataIndex: 'structName', |
|
||||
ellipsis: true, |
|
||||
valueType: 'select', |
|
||||
fieldProps: { |
|
||||
options: structureListOpt, |
|
||||
}, |
|
||||
renderFormItem: () => ( |
|
||||
<Select |
|
||||
showSearch |
|
||||
// style={{paddingLeft:10}}
|
|
||||
allowClear |
|
||||
placeholder='请选择' |
|
||||
options={structureListOpt?.map(item => ({ label: item.label, value: item.value }))} |
|
||||
filterOption={filterOption} |
|
||||
optionFilterProp='children'></Select> |
|
||||
), |
|
||||
// fieldProps: {
|
|
||||
// showSearch: true,
|
|
||||
// defaultValue: '',
|
|
||||
// },
|
|
||||
// search:false
|
|
||||
valueType: 'select', |
|
||||
fieldProps: { |
|
||||
options: structureListOpt, |
|
||||
}, |
|
||||
}, |
|
||||
{ |
|
||||
title: '操作', |
|
||||
width: 160, |
|
||||
key: 'option', |
|
||||
valueType: 'option', |
|
||||
render: (text, record) => { |
|
||||
const options = [] |
|
||||
options.push( |
|
||||
<RelationModal |
|
||||
proejctListOpt={proejctListOpt} |
|
||||
triggerRender={<a>修改映射关系</a>} |
|
||||
editData={record} |
|
||||
structureListOpt={structureListOpt} |
|
||||
title='修改映射关系' |
|
||||
onFinish={onFinish} |
|
||||
key='editModel' |
|
||||
/> |
|
||||
) |
|
||||
|
|
||||
options.push( |
|
||||
<Popconfirm |
|
||||
key='del' |
|
||||
placement='top' |
|
||||
title='是否确认删除映射关系?' |
|
||||
onConfirm={() => handleDelete(record.key)} |
|
||||
okText='是' |
|
||||
cancelText='否'> |
|
||||
<a>删除</a> |
|
||||
</Popconfirm> |
|
||||
) |
|
||||
|
|
||||
return options |
|
||||
}, |
|
||||
}, |
|
||||
] |
|
||||
// useMemo(()=>{
|
|
||||
|
|
||||
// })
|
|
||||
|
|
||||
const tableDatas = useMemo(() => { |
|
||||
const { anxinyunProject, structName } = tableParams |
|
||||
let rslt = dataSource |
|
||||
rslt = rslt |
|
||||
.filter(s => (anxinyunProject ? (s.anxinyunProject ? s.anxinyunProject === anxinyunProject : false) : true)) |
|
||||
?.filter(s => (structName ? (s.structName ? s.structName === structName : false) : true)) |
|
||||
return rslt |
|
||||
}) |
|
||||
|
|
||||
// const searchHandler=()=>{
|
|
||||
// const anxinyunProject=proTableFormRef.current.getFieldsValue()?.anxinyunProject
|
|
||||
// const structName=proTableFormRef.current.getFieldsValue()?.structName
|
|
||||
// setDataSource(
|
|
||||
// dataCopy.filter(f =>
|
|
||||
// (!anxinyunProject || f.anxinyunProject?.includes(anxinyunProject)) &&
|
|
||||
// (!structName || f?.structName === structName)
|
|
||||
// )
|
|
||||
// )
|
|
||||
|
|
||||
// }
|
|
||||
|
|
||||
return ( |
|
||||
<Spin spinning={anxinyunProjectLoading||relationLoading}> |
|
||||
<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'> PROJECT</span> |
|
||||
</div> |
|
||||
<div></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<RelationModal |
|
||||
structureListOpt={structureListOpt} |
|
||||
proejctListOpt={proejctListOpt} |
|
||||
triggerRender={<Button type='primary'>新增</Button>} |
|
||||
title='新增映射关系' |
|
||||
onFinish={onFinish} |
|
||||
key='addModel' |
|
||||
/> |
|
||||
<ProTable |
|
||||
formRef={proTableFormRef} |
|
||||
rowKey='id' |
|
||||
options={false} |
|
||||
request={async params => { |
|
||||
setTableParams(params) |
|
||||
return { |
|
||||
data: [], |
|
||||
success: true, |
|
||||
} |
|
||||
}} |
|
||||
actionRef={tableRef} |
|
||||
columns={columns} |
|
||||
pagination={{ pageSize: 10, size: 'default', className: 'global-pagination' }} |
|
||||
dataSource={tableDatas || []} |
|
||||
search={{ |
|
||||
labelWidth: 100, |
|
||||
|
|
||||
}} |
|
||||
// search={{
|
|
||||
// optionRender: ({searchText, resetText}, {form}, dom) => [
|
|
||||
// <Button type="primary" onClick={searchHandler}>查询</Button>,
|
|
||||
// ]
|
|
||||
// }}
|
|
||||
></ProTable> |
|
||||
{/* </Spin> */} |
|
||||
</div> |
|
||||
</Spin> |
|
||||
) |
|
||||
} |
|
||||
|
|
||||
function mapStateToProps(state) { |
|
||||
const { auth, global, device,anxinyunProject, relation} = state |
|
||||
return { |
|
||||
loading: device.isRequesting, |
|
||||
clientHeight: global.clientHeight, |
|
||||
actions: global.actions, |
|
||||
relationLoading:relation.isRequesting, |
|
||||
anxinyunProjectLoading:anxinyunProject.isRequesting, |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
export default connect(mapStateToProps)(ProjectBinding) |
|
@ -1,15 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
import reducers from './reducers'; |
|
||||
import routes from './routes'; |
|
||||
import actions from './actions'; |
|
||||
import { getNavItem } from './nav-item'; |
|
||||
|
|
||||
export default { |
|
||||
key: 'projectBinding', |
|
||||
name: '项目绑定', |
|
||||
reducers: reducers, |
|
||||
routes: routes, |
|
||||
actions: actions, |
|
||||
getNavItem: getNavItem |
|
||||
}; |
|
@ -1,13 +0,0 @@ |
|||||
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="projectBinding"> |
|
||||
<Link to="/projectBinding">项目绑定</Link> |
|
||||
</Menu.Item> |
|
||||
|
|
||||
); |
|
||||
} |
|
@ -1,5 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
export default { |
|
||||
|
|
||||
} |
|
@ -1,13 +0,0 @@ |
|||||
'use strict'; |
|
||||
import { ProjectBinding } from './containers'; |
|
||||
|
|
||||
export default [{ |
|
||||
type: 'inner', |
|
||||
route: { |
|
||||
path: '/projectBinding', |
|
||||
key: 'projectBinding', |
|
||||
breadcrumb: '项目绑定', |
|
||||
component: ProjectBinding, |
|
||||
|
|
||||
} |
|
||||
}]; |
|
@ -1,83 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
import { basicAction } from '@peace/utils' |
|
||||
import { ApiTable } from '$utils' |
|
||||
|
|
||||
export function getProjectGraph(projectId) { |
|
||||
return (dispatch) => basicAction({ |
|
||||
type: 'get', |
|
||||
dispatch, |
|
||||
actionType: 'GET_PROJECT_PLANAR_GRAPH', |
|
||||
url: ApiTable.getProjectGraph.replace('{projectId}', projectId), |
|
||||
msg: { option: '获取结构物平面图' }, |
|
||||
reducer: { name: 'projectGraph' } |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
export function createGraph(data) { |
|
||||
return (dispatch) => basicAction({ |
|
||||
type: 'post', |
|
||||
data, |
|
||||
dispatch, |
|
||||
actionType: 'ADD_PROJECT_PLANAR_GRAPH', |
|
||||
url: ApiTable.createGraph, |
|
||||
msg: { option: '新增结构物平面图' }, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function updateGraph(id, data) { |
|
||||
return (dispatch) => basicAction({ |
|
||||
type: 'post', |
|
||||
data, |
|
||||
dispatch, |
|
||||
actionType: 'UPDATE_PROJECT_PLANAR_GRAPH', |
|
||||
url: ApiTable.updateGraph.replace('{id}', id), |
|
||||
msg: { option: '修改结构物平面图' }, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function deleteGraph(id) { |
|
||||
return (dispatch) => basicAction({ |
|
||||
type: 'del', |
|
||||
dispatch, |
|
||||
actionType: 'DELETE_PROJECT_GRAPH', |
|
||||
url: ApiTable.deleteGraph.replace('{id}', id), |
|
||||
msg: { |
|
||||
option: '删除结构物布设图', |
|
||||
}, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function getProjectPoints(projectId) { |
|
||||
return (dispatch) => basicAction({ |
|
||||
type: 'get', |
|
||||
dispatch, |
|
||||
actionType: 'GET_PROJECT_ALL_POINTS', |
|
||||
url: ApiTable.getProjectPoints.replace('{projectId}', projectId), |
|
||||
msg: { option: '获取结构物所有点位' }, |
|
||||
reducer: { name: 'projectAllPoints' } |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function getDeployPoints(pictureId) { |
|
||||
return (dispatch) => basicAction({ |
|
||||
type: 'get', |
|
||||
dispatch, |
|
||||
actionType: 'GET_PROJECT_DEPLOY_POINTS', |
|
||||
url: ApiTable.getDeployPoints.replace('{pictureId}', pictureId), |
|
||||
msg: { option: '获取结构物平面图测点分布' }, |
|
||||
reducer: { name: 'projectDeployPoints' } |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function setDeployPoints(pictureId, data) { |
|
||||
return (dispatch) => basicAction({ |
|
||||
type: 'post', |
|
||||
data, |
|
||||
dispatch, |
|
||||
actionType: 'SET_PROJECT_DEPLOY_POINTS', |
|
||||
url: ApiTable.setDeployPoints.replace('{pictureId}', pictureId), |
|
||||
msg: { option: '结构物平面图点位布设' }, |
|
||||
}); |
|
||||
} |
|
@ -1,10 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
|
|
||||
import * as projectSituation from './projectSituation' |
|
||||
import * as projectGraph from './graph' |
|
||||
|
|
||||
export default { |
|
||||
...projectSituation, |
|
||||
...projectGraph |
|
||||
} |
|
@ -1,101 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
import { basicAction } from '@peace/utils' |
|
||||
import { ApiTable } from '$utils' |
|
||||
|
|
||||
|
|
||||
export function getProjectList (query) { |
|
||||
return (dispatch) => basicAction({ |
|
||||
type: 'get', |
|
||||
query, |
|
||||
dispatch, |
|
||||
actionType: 'GET_PROJEECT_LIST', |
|
||||
url: ApiTable.getProjectList, |
|
||||
msg: { error: '获取结构物列表失败', }, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
export function postAddProject (data) { |
|
||||
return (dispatch) => basicAction({ |
|
||||
type: 'post', |
|
||||
data, |
|
||||
dispatch, |
|
||||
actionType: 'POST_ADD_PROJECT', |
|
||||
url: ApiTable.postAddProject, |
|
||||
msg: { option: data?.id ? '编辑结构物' : '新增结构物', }, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
export function delProject (id) { |
|
||||
return (dispatch) => basicAction({ |
|
||||
type: 'del', |
|
||||
dispatch, |
|
||||
actionType: 'DEL_PROJECT', |
|
||||
url: ApiTable.delProject.replace('{id}', id), |
|
||||
msg: { |
|
||||
option: '删除结构物', |
|
||||
}, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
export function addPosition (data, point) { |
|
||||
return (dispatch) => basicAction({ |
|
||||
type: 'post', |
|
||||
data, |
|
||||
dispatch, |
|
||||
actionType: 'ADD_POSITION', |
|
||||
url: ApiTable.position, |
|
||||
msg: { option: point ? '二维码生成' : data?.id ? '编辑点位' : '新增点位', }, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function positionList (query) { |
|
||||
return (dispatch) => basicAction({ |
|
||||
type: 'get', |
|
||||
query, |
|
||||
dispatch, |
|
||||
actionType: 'POSITION_LIST', |
|
||||
url: ApiTable.position, |
|
||||
msg: { error: '获取点位列表失败', }, |
|
||||
reducer: { name: 'projectPoints' } |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
export function delPosition (id) { |
|
||||
return (dispatch) => basicAction({ |
|
||||
type: 'del', |
|
||||
dispatch, |
|
||||
actionType: 'DEL_POSITION', |
|
||||
url: ApiTable.delPosition.replace('{id}', id), |
|
||||
msg: { |
|
||||
option: '删除点位', |
|
||||
}, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
export function qrCodeShow (query) { |
|
||||
return (dispatch) => basicAction({ |
|
||||
type: 'get', |
|
||||
query, |
|
||||
dispatch, |
|
||||
actionType: 'GET_QR_CODE', |
|
||||
url: ApiTable.qrCodeShow, |
|
||||
msg: { error: '获取二维码列表失败', }, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
export function q () { |
|
||||
return (dispatch) => basicAction({ |
|
||||
type: 'get', |
|
||||
dispatch, |
|
||||
actionType: 'GET_CODE', |
|
||||
url: ApiTable.q, |
|
||||
msg: { error: '获取二维码列表失败', }, |
|
||||
}); |
|
||||
} |
|
||||
|
|
@ -1,57 +0,0 @@ |
|||||
'use strict' |
|
||||
|
|
||||
import React, { Component, PropTypes } from 'react'; |
|
||||
import { DropTarget } from 'react-dnd'; |
|
||||
import StationSpot from './station-spot'; |
|
||||
|
|
||||
const heatmapTarget = { |
|
||||
drop(props, monitor) { |
|
||||
//get item from station-spot.js
|
|
||||
//item:{deployed, rect, spotInlist, info}
|
|
||||
const item = monitor.getItem(); |
|
||||
const move = monitor.getDifferenceFromInitialOffset(); |
|
||||
props.onDeploySpot({ ...item, move }); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
function collect(connect, monitor) { |
|
||||
return { |
|
||||
connectDropTarget: connect.dropTarget(), |
|
||||
isOver: monitor.isOver() |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
class Heatmap extends React.Component { |
|
||||
componentDidMount() { |
|
||||
|
|
||||
} |
|
||||
|
|
||||
renderSpots() { |
|
||||
const { width, height, spots, onRemoveSpot } = this.props; |
|
||||
return spots.map(s => <StationSpot key={s.sensorId} info={s} |
|
||||
size={{ "width": width, "height": height }} |
|
||||
onRemoveSpot={onRemoveSpot} />); |
|
||||
} |
|
||||
|
|
||||
render() { |
|
||||
const { connectDropTarget, height, width, image } = this.props; |
|
||||
|
|
||||
let targetStyle = { |
|
||||
position: 'relative', |
|
||||
width: width, |
|
||||
// overflow:'hidden',
|
|
||||
height: height, |
|
||||
background: `url("/_file-server/${image}") no-repeat`, |
|
||||
backgroundSize: '100% 100%', |
|
||||
}; |
|
||||
|
|
||||
return connectDropTarget( |
|
||||
<div id="dragTarget" style={targetStyle}> |
|
||||
{this.renderSpots()} |
|
||||
</div> |
|
||||
) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
export default DropTarget('stationSpot', heatmapTarget, collect)(Heatmap); |
|
||||
|
|
@ -1,114 +0,0 @@ |
|||||
/** |
|
||||
* Created by yuanfenghua on 2018/6/18. |
|
||||
*/ |
|
||||
'use strict' |
|
||||
|
|
||||
import React, { Component } from 'react'; |
|
||||
import { findDOMNode } from 'react-dom'; |
|
||||
import { connect } from 'react-redux'; |
|
||||
import { DragSource } from 'react-dnd'; |
|
||||
import { Tooltip } from 'antd'; |
|
||||
import { MinusOutlined } from '@ant-design/icons'; |
|
||||
import Style from './style.css'; |
|
||||
|
|
||||
const stationSource = { |
|
||||
beginDrag(props, monitor, component) { |
|
||||
const dom = findDOMNode(component); |
|
||||
const rect = { |
|
||||
x: dom.offsetLeft - dom.offsetParent.scrollLeft, |
|
||||
y: dom.offsetTop - dom.offsetParent.scrollTop |
|
||||
}; |
|
||||
const spotInlist = { |
|
||||
x: dom.getBoundingClientRect().left, |
|
||||
y: dom.getBoundingClientRect().top |
|
||||
}; |
|
||||
|
|
||||
return { |
|
||||
info: props.info, |
|
||||
rect: rect, |
|
||||
spotInlist: spotInlist, |
|
||||
deployed: props.info.deployed |
|
||||
}; |
|
||||
}, |
|
||||
endDrag(props, monitor) { |
|
||||
if (!monitor.didDrop() && props.onRemoveSpot) { |
|
||||
props.onRemoveSpot(monitor.getItem().info); |
|
||||
} |
|
||||
}, |
|
||||
canDrag(props) { |
|
||||
if (props.size) { |
|
||||
//热点图上的热点可拖拽
|
|
||||
return true; |
|
||||
} else { |
|
||||
//测点树未布设的叶结点可拖拽
|
|
||||
return !props.children && props.info.deployed == false |
|
||||
} |
|
||||
}, |
|
||||
}; |
|
||||
|
|
||||
function collect(connect, monitor) { |
|
||||
return { |
|
||||
connectDragSource: connect.dragSource(), |
|
||||
isDragging: monitor.isDragging() |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
class StationSpot extends React.Component { |
|
||||
constructor(props) { |
|
||||
super(props); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
renderTreeTitle = () => { |
|
||||
const { isDragging, info } = this.props; |
|
||||
const { spotId, location, deployed } = info; |
|
||||
const opacity = isDragging ? 0.4 : 1; |
|
||||
return ( |
|
||||
<span style={{ lineHeight: '15px', opacity }} className={Style['icon']}> |
|
||||
<span key={spotId}> |
|
||||
<Tooltip title={location}> |
|
||||
<span className={deployed == false ? Style['station-tree-node-normal'] : null}>{location.length >= 12 ? location.substring(0, 12) + "..." : location}</span> |
|
||||
</Tooltip> |
|
||||
{deployed ? <MinusOutlined type="minus-circle-o" className={Style['tip']} onClick={this.onRemoveSpot} /> : null} |
|
||||
</span> |
|
||||
</span> |
|
||||
); |
|
||||
}; |
|
||||
|
|
||||
onRemoveSpot = () => { |
|
||||
|
|
||||
const { onRemoveSpot, info } = this.props; |
|
||||
if (onRemoveSpot) { |
|
||||
onRemoveSpot(info); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
renderHotspot = () => { |
|
||||
const { info, size } = this.props; |
|
||||
const { key, location, x, y, screenWidth, screenHeight } = info; |
|
||||
const { width, height } = size; |
|
||||
let style = { |
|
||||
position: 'absolute', |
|
||||
left: width * x / screenWidth, |
|
||||
top: height * y / screenHeight, |
|
||||
cursor: 'move' |
|
||||
}; |
|
||||
|
|
||||
return <span style={style}> |
|
||||
<Tooltip title={location}> |
|
||||
<div style={{ height: 24, width: 24, borderRadius: '100%', backgroundColor: 'rgba(16,142,233,0.2)', padding: '5px' }}> |
|
||||
<div style={{ height: 14, width: 14, borderRadius: '100%', backgroundColor: '#108ee9', boxShadow: '0 0 10px #108ee9' }}></div> |
|
||||
</div> |
|
||||
</Tooltip> |
|
||||
</span> |
|
||||
}; |
|
||||
|
|
||||
render() { |
|
||||
const { connectDragSource, size } = this.props; |
|
||||
return connectDragSource( |
|
||||
size ? this.renderHotspot() : this.renderTreeTitle() |
|
||||
); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
export default connect()(DragSource('stationSpot', stationSource, collect)(StationSpot)); |
|
@ -1,91 +0,0 @@ |
|||||
.station-tree-node-normal{ |
|
||||
margin-right: 6px; |
|
||||
padding: 0 4px; |
|
||||
height: 15px; |
|
||||
line-height: 15px; |
|
||||
background: #108ee9; |
|
||||
color: #fff; |
|
||||
font-size: 12px; |
|
||||
text-align: center; |
|
||||
} |
|
||||
|
|
||||
.icon .tip{ |
|
||||
margin-left:10px; |
|
||||
-webkit-transition:opacity 0.1s 0.2s; |
|
||||
opacity:0; |
|
||||
pointer-events:none; |
|
||||
} |
|
||||
.icon:hover .tip{ |
|
||||
-webkit-transition:opacity 0.2s; |
|
||||
opacity:1; |
|
||||
pointer-events:auto; |
|
||||
} |
|
||||
.icon .tip:hover{ |
|
||||
-webkit-transition:none; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
:global(.no-card-border>.ant-card-head){ |
|
||||
border: none; |
|
||||
} |
|
||||
|
|
||||
.cardCoverBox{ |
|
||||
position: absolute; |
|
||||
top: 50px; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
bottom: 0; |
|
||||
} |
|
||||
.cardCover{ |
|
||||
display: flex; |
|
||||
flex-direction: column; |
|
||||
justify-content: center; |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
left: 0; |
|
||||
right: 0; |
|
||||
bottom: 0; |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
background-color: rgba(240 , 240, 240, 0.9); |
|
||||
z-index: 2; |
|
||||
} |
|
||||
.cardCover .btnCell{ |
|
||||
text-align: center; |
|
||||
margin: 25px; |
|
||||
} |
|
||||
|
|
||||
.cardFootCover{ |
|
||||
display: flex; |
|
||||
justify-content: space-around; |
|
||||
align-items: center; |
|
||||
position: absolute; |
|
||||
top: 0; |
|
||||
width: 100%; |
|
||||
height: 100%; |
|
||||
background-color: rgba(255, 255, 255, 0.9); |
|
||||
z-index: 1; |
|
||||
opacity: 0; |
|
||||
} |
|
||||
.cardFootCover:hover{ |
|
||||
opacity: 1; |
|
||||
} |
|
||||
.deleteBox{ |
|
||||
margin: 0 40px; |
|
||||
} |
|
||||
.deleteBox h3{ |
|
||||
text-align: center; |
|
||||
margin-bottom: 5px; |
|
||||
} |
|
||||
.deleteBox .btnRow{ |
|
||||
display: flex; |
|
||||
justify-content: space-around; |
|
||||
margin-top: 10px; |
|
||||
width: 100%; |
|
||||
} |
|
||||
.loadingBox{ |
|
||||
width: 100%; |
|
||||
margin-bottom: 50px; |
|
||||
text-align: center; |
|
||||
padding: 50px 0; |
|
||||
} |
|
@ -1,219 +0,0 @@ |
|||||
import React, { useState } from 'react'; |
|
||||
import { Button, Form, Input, Modal, Select, DatePicker } from 'antd'; |
|
||||
import { EnvironmentTwoTone } from '@ant-design/icons'; |
|
||||
const { TextArea } = Input; |
|
||||
import { connect } from 'react-redux'; |
|
||||
import Uploads from '$components/Uploads'; |
|
||||
import { useEffect } from 'react'; |
|
||||
import moment from 'moment'; |
|
||||
|
|
||||
const ProjectAddModel = ({ dispatch, actions, user, modelData, close, success, qrCodeId, devices }) => { |
|
||||
|
|
||||
const { projectRegime } = actions |
|
||||
const [showBaiduMap, setShowBaiduMap] = useState(false) |
|
||||
const [form] = Form.useForm(); |
|
||||
|
|
||||
useEffect(() => { |
|
||||
if (modelData?.longitude && modelData?.latitude) { |
|
||||
form.setFieldValue('longitude', modelData?.longitude) |
|
||||
form.setFieldValue('latitude', modelData?.latitude) |
|
||||
} |
|
||||
var map = new AMap.Map('container', { |
|
||||
resizeEnable: true, //是否监控地图容器尺寸变化
|
|
||||
zoom: 11, //初始化地图层级
|
|
||||
center: [116.397428, 39.90923] //初始化地图中心点
|
|
||||
}); |
|
||||
|
|
||||
var autoOptions = { |
|
||||
input: "tipinput" |
|
||||
}; |
|
||||
|
|
||||
AMap.plugin(['AMap.PlaceSearch', 'AMap.AutoComplete', 'AMap.Geocoder'], () => { |
|
||||
var auto = new AMap.AutoComplete(autoOptions); |
|
||||
var placeSearch = new AMap.PlaceSearch({ |
|
||||
map: map |
|
||||
}); //构造地点查询类
|
|
||||
|
|
||||
function select(e) { |
|
||||
if (e) { |
|
||||
placeSearch.setCity(e.poi.adcode); |
|
||||
placeSearch.search(e.poi.name, function (status, result) { |
|
||||
form.setFieldValue('longitude', result.poiList.pois[0].location.lat) |
|
||||
form.setFieldValue('latitude', result.poiList.pois[0].location.lng) |
|
||||
}) //关键字查询查询
|
|
||||
} |
|
||||
} |
|
||||
auto.on("select", select);//注册监听,当选中某条记录时会触发
|
|
||||
map.on('click', function (e) { //点击地图获取经纬度
|
|
||||
form.setFieldValue('longitude', e.lnglat.lat) |
|
||||
form.setFieldValue('latitude', e.lnglat.lng) |
|
||||
}); |
|
||||
}); |
|
||||
|
|
||||
|
|
||||
}, []) |
|
||||
|
|
||||
|
|
||||
return ( |
|
||||
<Modal |
|
||||
title={modelData.id ? '编辑点位' : '新增点位'} |
|
||||
width={570} |
|
||||
open={true} |
|
||||
onOk={() => { |
|
||||
form.validateFields().then(r => { |
|
||||
dispatch(projectRegime.addPosition({ |
|
||||
...r, |
|
||||
id: modelData?.id, |
|
||||
projectId: qrCodeId, |
|
||||
latitude: r?.latitude ? r?.latitude : null, |
|
||||
longitude: r?.longitude ? r?.longitude : null, |
|
||||
img: r.img ? r.img.map(u => u.storageUrl) : [], |
|
||||
})).then(res => { |
|
||||
if (res.success) { |
|
||||
success() |
|
||||
} |
|
||||
}) |
|
||||
}) |
|
||||
}} |
|
||||
onCancel={() => { |
|
||||
close() |
|
||||
}} |
|
||||
> |
|
||||
<Form |
|
||||
style={{}} |
|
||||
form={form} |
|
||||
labelAlign='right' |
|
||||
labelCol={{ span: 6 }} wrapperCol={{ span: 18 }} |
|
||||
onFinish={r => { |
|
||||
|
|
||||
}} |
|
||||
initialValues={{ |
|
||||
img: (modelData.img || []).map(s => { |
|
||||
return { |
|
||||
storageUrl: s |
|
||||
} |
|
||||
}), |
|
||||
}} |
|
||||
> |
|
||||
<Form.Item label='点位名称' name="name" style={{}} |
|
||||
initialValue={modelData?.name} |
|
||||
rules={[{ required: true, message: '必填,名称不能包含 \\ / : * ? " < > | #', pattern: new RegExp('^[^\\\\/|:*?\"<>#]+$') },]} |
|
||||
> |
|
||||
<Input placeholder="请输入点位名称" allowClear /> |
|
||||
</Form.Item> |
|
||||
<div style={{ position: 'relative' }}> |
|
||||
{/* /^\d+$|^\d*\.\d+$/g */} |
|
||||
<Form.Item label="所在地区:" labelCol={{ span: 11 }} labelAlign='right' name="longitude" style={{ display: 'inline-block', width: 'calc(60% - 30px)', }} |
|
||||
rules={[{ required: false, message: '', }, { |
|
||||
validator: (rule, value, callback) => { |
|
||||
const sjh = /^\d+$|^\d*\.\d+$/g; |
|
||||
if (value) { |
|
||||
let valid = sjh.test(value); |
|
||||
if (!valid) { |
|
||||
return callback([new Error("横坐标填写错误")]); |
|
||||
} |
|
||||
callback(); |
|
||||
} |
|
||||
// return callback([new Error("请输入横坐标")]);
|
|
||||
return Promise.resolve(); |
|
||||
} |
|
||||
}]} |
|
||||
> |
|
||||
<Input placeholder="经度支持数字" /> |
|
||||
</Form.Item> |
|
||||
~ |
|
||||
<Form.Item name="latitude" style={{ display: 'inline-block', width: 'calc(40% + 15px)', }} |
|
||||
rules={[{ required: false, message: '', }, { |
|
||||
validator: (rule, value, callback) => { |
|
||||
const sjh = /^\d+$|^\d*\.\d+$/g; |
|
||||
if (value) { |
|
||||
let valid = sjh.test(value); |
|
||||
if (!valid) { |
|
||||
return callback([new Error("纵坐标填写错误")]); |
|
||||
} |
|
||||
callback(); |
|
||||
} |
|
||||
// return callback([new Error("请输入纵坐标")]);
|
|
||||
return Promise.resolve(); |
|
||||
} |
|
||||
}]} |
|
||||
> |
|
||||
<Input placeholder="维度支持数字" /> |
|
||||
</Form.Item> |
|
||||
<EnvironmentTwoTone style={{ position: 'absolute', top: 5, right: 27, fontSize: 22 }} onClick={() => { |
|
||||
setShowBaiduMap(!showBaiduMap) |
|
||||
}} /> |
|
||||
</div> |
|
||||
<Form.Item |
|
||||
label={"地址"} |
|
||||
name='location' |
|
||||
style={showBaiduMap ? { display: 'block' } : { display: 'none' }} |
|
||||
> |
|
||||
<Input id="tipinput" /> |
|
||||
</Form.Item> |
|
||||
<Form.Item |
|
||||
|
|
||||
label="地图" |
|
||||
name='map' |
|
||||
style={showBaiduMap ? { display: 'block' } : { display: 'none' }} |
|
||||
> |
|
||||
<div id="container" style={{ width: '100%', height: '425px', marginBottom: '15px' }}></div> |
|
||||
</Form.Item> |
|
||||
<Form.Item name='describe' label="描述" |
|
||||
initialValue={modelData?.describe} |
|
||||
rules={[{ required: true, message: '请输入描述内容', },]}> |
|
||||
<TextArea /> |
|
||||
</Form.Item> |
|
||||
<Form.Item label='设备编号' name="equipmentNo" style={{}} |
|
||||
initialValue={modelData?.equipmentNo}> |
|
||||
<Input placeholder="请输入设备编号" allowClear /> |
|
||||
</Form.Item> |
|
||||
<Form.Item label='设备型号' name="equipmentModel" style={{}} |
|
||||
initialValue={modelData?.equipmentModel}> |
|
||||
<Input placeholder="请输入设备型号" allowClear /> |
|
||||
</Form.Item> |
|
||||
<Form.Item label='设备绑定' name="devices" style={{}} |
|
||||
initialValue={modelData?.pointDevices?.map(s => s?.deviceId) || []}> |
|
||||
<Select mode="multiple" showSearch filterOption={(input, option) => (option?.children ?? '').toLowerCase().includes(input.toLowerCase())}> |
|
||||
{ |
|
||||
devices?.map(s => <Select.Option |
|
||||
disabled={s?.pointDevices?.length > 0 && !s?.pointDevices?.find(x => x.pointId == modelData?.id)} |
|
||||
value={s.id} >{s?.name}</Select.Option>) |
|
||||
} |
|
||||
</Select> |
|
||||
</Form.Item> |
|
||||
<Form.Item |
|
||||
label="点位图片" |
|
||||
name='img' |
|
||||
help={<div style={{ fontSize: 12 }}>说明:请上传png,jpg格式图片,图片大小不超过10M</div>} |
|
||||
> |
|
||||
<Uploads |
|
||||
listType='picture-card' |
|
||||
uploadType='project' |
|
||||
maxFilesNum={1} |
|
||||
maxFileSize={10} |
|
||||
isQiniu={true} |
|
||||
fileTypes={["png", "jpg"]} |
|
||||
defaultValue={(modelData.img || []).map(s => { |
|
||||
return { |
|
||||
storageUrl: s |
|
||||
} |
|
||||
})} |
|
||||
/> |
|
||||
</Form.Item> |
|
||||
</Form> |
|
||||
</Modal> |
|
||||
|
|
||||
); |
|
||||
}; |
|
||||
|
|
||||
|
|
||||
function mapStateToProps(state) { |
|
||||
const { auth, global } = state; |
|
||||
return { |
|
||||
user: auth.user, |
|
||||
actions: global.actions, |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
export default connect(mapStateToProps)(ProjectAddModel); |
|
@ -1,234 +0,0 @@ |
|||||
import React, { useState } from 'react'; |
|
||||
import { Form, Input, Modal, Select, Row, Col } from 'antd'; |
|
||||
// import { EnvironmentTwoTone } from '@ant-design/icons';
|
|
||||
const { TextArea } = Input; |
|
||||
import { connect } from 'react-redux'; |
|
||||
import Uploads from '$components/Uploads'; |
|
||||
import { useEffect } from 'react'; |
|
||||
// import moment from 'moment';
|
|
||||
const type_options = [ |
|
||||
{ value: '桥梁', label: '桥梁' }, |
|
||||
{ value: '隧道', label: '隧道' }, |
|
||||
{ value: '管廊', label: '管廊' }, |
|
||||
{ value: '地灾', label: '地灾' }, |
|
||||
] |
|
||||
const ProjectAddModel = ({ dispatch, actions, user, modelData, close, success, firmList }) => { |
|
||||
|
|
||||
const { projectRegime } = actions |
|
||||
const [showBaiduMap, setShowBaiduMap] = useState(false) |
|
||||
const [type, setType] = useState(modelData?.type || type_options[0]) |
|
||||
const [form] = Form.useForm(); |
|
||||
|
|
||||
useEffect(() => { |
|
||||
if (modelData?.longitude && modelData?.latitude) { |
|
||||
form.setFieldValue('longitude', modelData?.longitude) |
|
||||
form.setFieldValue('latitude', modelData?.latitude) |
|
||||
} |
|
||||
var map = new AMap.Map('container', { |
|
||||
resizeEnable: true, //是否监控地图容器尺寸变化
|
|
||||
zoom: 11, //初始化地图层级
|
|
||||
center: [116.397428, 39.90923] //初始化地图中心点
|
|
||||
}); |
|
||||
|
|
||||
var autoOptions = { |
|
||||
input: "tipinput" |
|
||||
}; |
|
||||
|
|
||||
AMap.plugin(['AMap.PlaceSearch', 'AMap.AutoComplete', 'AMap.Geocoder'], () => { |
|
||||
var auto = new AMap.AutoComplete(autoOptions); |
|
||||
var placeSearch = new AMap.PlaceSearch({ |
|
||||
map: map |
|
||||
}); //构造地点查询类
|
|
||||
|
|
||||
function select(e) { |
|
||||
if (e) { |
|
||||
placeSearch.setCity(e.poi.adcode); |
|
||||
placeSearch.search(e.poi.name, function (status, result) { |
|
||||
form.setFieldValue('longitude', result.poiList.pois[0].location.lng) |
|
||||
form.setFieldValue('latitude', result.poiList.pois[0].location.lat) |
|
||||
}) //关键字查询查询
|
|
||||
} |
|
||||
} |
|
||||
auto.on("select", select);//注册监听,当选中某条记录时会触发
|
|
||||
map.on('click', function (e) { //点击地图获取经纬度
|
|
||||
form.setFieldValue('longitude', e.lnglat.lng) |
|
||||
form.setFieldValue('latitude', e.lnglat.lat) |
|
||||
}); |
|
||||
}); |
|
||||
|
|
||||
}, []) |
|
||||
|
|
||||
|
|
||||
|
|
||||
return ( |
|
||||
<Modal |
|
||||
className="global-modal" |
|
||||
title={modelData?.id ? '编辑项目' : '新建项目'} |
|
||||
width={717} |
|
||||
open={true} |
|
||||
onOk={() => { |
|
||||
form.validateFields().then(v => { |
|
||||
dispatch(projectRegime.postAddProject({ |
|
||||
...v, |
|
||||
img: v.img ? v.img.map(u => u.storageUrl) : [], |
|
||||
id: modelData?.id |
|
||||
})).then(res => { |
|
||||
if (res.success) { |
|
||||
success() |
|
||||
} |
|
||||
}) |
|
||||
}) |
|
||||
}} |
|
||||
onCancel={() => close()} |
|
||||
> |
|
||||
<Form |
|
||||
style={{}} |
|
||||
form={form} |
|
||||
labelAlign='right' |
|
||||
labelCol={{ span: 4 }} wrapperCol={{ span: 18 }} |
|
||||
onFinish={r => { |
|
||||
}} |
|
||||
initialValues={{ |
|
||||
img: (modelData.img || []).map(s => { |
|
||||
return { |
|
||||
storageUrl: s |
|
||||
} |
|
||||
}), |
|
||||
describe: modelData?.describe, |
|
||||
}} |
|
||||
> |
|
||||
<div style={{ position: 'relative', display: 'flex' }}> |
|
||||
<Form.Item label='结构物名称' labelCol={{ span: 9 }} name="name" style={{ width: 369 }} |
|
||||
initialValue={modelData?.name} |
|
||||
rules={[{ required: true, message: '请输入结构物名称' },]} |
|
||||
> |
|
||||
<Input placeholder="请输入结构物名称" allowClear bordered={false} /> |
|
||||
</Form.Item> |
|
||||
<Form.Item label='结构物类型' labelCol={{ span: 9 }} name="type" style={{ width: 254 }} |
|
||||
initialValue={modelData?.type || '桥梁'} |
|
||||
// rules={[{ required: true, message: '请选择结构物类型' },]}
|
|
||||
> |
|
||||
<Select |
|
||||
onChange={value => { setType(value) }} |
|
||||
bordered={false} |
|
||||
allowClear |
|
||||
options={type_options} |
|
||||
/> |
|
||||
</Form.Item> |
|
||||
</div> |
|
||||
{type == '管廊' && <Form.Item label='子系统' name="subType" |
|
||||
initialValue={modelData?.subType || '指挥中心'} |
|
||||
rules={[{ required: true, message: '请选择子系统' }]} |
|
||||
> |
|
||||
<Select |
|
||||
bordered={false} |
|
||||
options={[ |
|
||||
{ value: '指挥中心', label: '指挥中心' }, |
|
||||
{ value: '管廊本体', label: '管廊本体' }, |
|
||||
{ value: '电梯系统', label: '电梯系统' }, |
|
||||
{ value: '供配电系统', label: '供配电系统' }, |
|
||||
{ value: '防雷与接地系统', label: '防雷与接地系统' }, |
|
||||
{ value: '燃气仓', label: '燃气仓' }, |
|
||||
{ value: '给水仓', label: '给水仓' }, |
|
||||
{ value: '电气仓', label: '电气仓' }, |
|
||||
{ value: '安防系统', label: '安防系统' }, |
|
||||
{ value: '高压电力仓', label: '高压电力仓' }, |
|
||||
]} |
|
||||
/> |
|
||||
</Form.Item>} |
|
||||
<div style={{ position: 'relative' }}> |
|
||||
<Form.Item label="所在地区:" labelCol={{ span: 9 }} labelAlign='right' name="longitude" style={{ display: 'inline-block', width: 'calc(60% - 50px)', }} |
|
||||
rules={[{ required: true, message: '', }, { |
|
||||
validator: (rule, value, callback) => { |
|
||||
const sjh = /^\d+$|^\d*\.\d+$/g; |
|
||||
if (value) { |
|
||||
let valid = sjh.test(value); |
|
||||
if (!valid) { |
|
||||
return callback([new Error("横坐标填写错误")]); |
|
||||
} |
|
||||
callback(); |
|
||||
} |
|
||||
return callback([new Error("请输入横坐标")]); |
|
||||
} |
|
||||
}]} |
|
||||
> |
|
||||
<Input placeholder="经度支持数字" bordered={false} /> |
|
||||
</Form.Item> |
|
||||
— |
|
||||
<Form.Item name="latitude" style={{ display: 'inline-block', width: 'calc(40% + 15px)', }} |
|
||||
rules={[{ required: true, message: '', }, { |
|
||||
validator: (rule, value, callback) => { |
|
||||
const sjh = /^\d+$|^\d*\.\d+$/g; |
|
||||
if (value) { |
|
||||
let valid = sjh.test(value); |
|
||||
if (!valid) { |
|
||||
return callback([new Error("纵坐标填写错误")]); |
|
||||
} |
|
||||
callback(); |
|
||||
} |
|
||||
return callback([new Error("请输入纵坐标")]); |
|
||||
} |
|
||||
}]} |
|
||||
> |
|
||||
<Input placeholder="维度支持数字" bordered={false} /> |
|
||||
</Form.Item> |
|
||||
<img src='/assets/images/show_map.svg' style={{ position: 'absolute', width: 28, top: 2, right: 47, cursor: 'pointer' }} onClick={() => { |
|
||||
setShowBaiduMap(!showBaiduMap) |
|
||||
}} /> |
|
||||
</div> |
|
||||
<Form.Item |
|
||||
label={"地址"} |
|
||||
name='location' |
|
||||
style={showBaiduMap ? { display: 'block' } : { display: 'none' }} |
|
||||
> |
|
||||
<Input id="tipinput" bordered={false} /> |
|
||||
</Form.Item> |
|
||||
<Form.Item |
|
||||
label="地图" |
|
||||
name='map' |
|
||||
style={showBaiduMap ? { display: 'block' } : { display: 'none' }} |
|
||||
> |
|
||||
<div id="container" style={{ width: '100%', height: '425px', marginBottom: '15px' }}></div> |
|
||||
</Form.Item> |
|
||||
<Form.Item name='describe' label="描述"> |
|
||||
<TextArea bordered={false} /> |
|
||||
</Form.Item> |
|
||||
<Form.Item |
|
||||
label="结构物图片" |
|
||||
name='img' |
|
||||
help={<div style={{ fontSize: 12 }}>说明:请上传png,jpg格式图片,图片大小不超过5M,建议图片宽高比16:9</div>} |
|
||||
// rules={[{ required: true, message: '请上传图片', },]}
|
|
||||
> |
|
||||
<Uploads |
|
||||
// className='upload'
|
|
||||
listType='picture-card' |
|
||||
uploadType='project' |
|
||||
maxFilesNum={1} |
|
||||
maxFileSize={5} |
|
||||
isQiniu={true} |
|
||||
// onChange={vsjunct}
|
|
||||
fileTypes={["png", "jpg"]} |
|
||||
// value={editUrl}
|
|
||||
defaultValue={(modelData.img || []).map(s => { |
|
||||
return { |
|
||||
storageUrl: s |
|
||||
} |
|
||||
})} |
|
||||
/> |
|
||||
</Form.Item> |
|
||||
</Form> |
|
||||
</Modal> |
|
||||
|
|
||||
); |
|
||||
}; |
|
||||
|
|
||||
|
|
||||
function mapStateToProps(state) { |
|
||||
const { auth, global } = state; |
|
||||
return { |
|
||||
user: auth.user, |
|
||||
actions: global.actions, |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
export default connect(mapStateToProps)(ProjectAddModel); |
|
@ -1,9 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
|
|
||||
import QrCode from './qrCode' |
|
||||
import Information from './information' |
|
||||
import Point from './point' |
|
||||
import PointDeploy from './pointDeploy/default' |
|
||||
|
|
||||
export { QrCode, Information, Point, PointDeploy }; |
|
@ -1,251 +0,0 @@ |
|||||
import React, { useEffect, useState } from 'react'; |
|
||||
import { connect } from 'react-redux'; |
|
||||
import { Form, Input, Button, Table, Modal, Popconfirm, Tooltip } from 'antd'; |
|
||||
import '../style.less'; |
|
||||
import { push } from 'react-router-redux'; |
|
||||
import ProjectAddModel from '../components/projectAddModel' |
|
||||
import './information.less'; |
|
||||
|
|
||||
|
|
||||
const Information = (props) => { |
|
||||
const { dispatch, actions, user, loading } = props |
|
||||
const { projectRegime } = actions |
|
||||
const [firmList, setFirmList] = useState([]) |
|
||||
const [tableList, settableList] = useState([]) |
|
||||
const [addModel, setAddModel] = useState(false) |
|
||||
const [modelData, setModelData] = useState({}) |
|
||||
const [query, setQuery] = useState({ limit: 10, page: 0 }) |
|
||||
const [limits, setLimits] = useState() |
|
||||
const [search, setSearch] = useState({}) |
|
||||
const [isPicture, setIsPicture] = useState(false) |
|
||||
const [pictureUrl, setPictureUrl] = useState() |
|
||||
const [companyID, setCompanyId] = useState('') |
|
||||
const [select, setSelect] = useState([]) |
|
||||
// var QRCode = require('qrcode')
|
|
||||
|
|
||||
useEffect(() => { |
|
||||
projectList(query) |
|
||||
}, []) |
|
||||
|
|
||||
const projectList = (obj) => { |
|
||||
const { limit, page, name } = obj |
|
||||
dispatch(projectRegime.getProjectList({ limit, page, name, })).then(res => { |
|
||||
// console.log(res)
|
|
||||
if (res.success) { |
|
||||
settableList(res.payload.data?.rows?.map(v => ({ ...v, key: v.id }))) |
|
||||
setLimits(res.payload.data?.count) |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
// const createQrCode = (name) => {
|
|
||||
// let url = ''
|
|
||||
// QRCode.toDataURL(name, {
|
|
||||
// errorCorrectionLevel: 'low',
|
|
||||
// type: 'image/png',
|
|
||||
// quality: 0.3,
|
|
||||
// margin: 2,
|
|
||||
// maskPattern: 9,
|
|
||||
// width: 400,
|
|
||||
// color: {
|
|
||||
// dark: "#000000ff",
|
|
||||
// light: "#ffffffff"
|
|
||||
// }
|
|
||||
// }, function (err, v) {
|
|
||||
// url = v
|
|
||||
// })
|
|
||||
// return url
|
|
||||
// }
|
|
||||
|
|
||||
const columns = [ |
|
||||
{ |
|
||||
title: '序号', |
|
||||
dataIndex: 'index', |
|
||||
key: 'index', |
|
||||
render: (text, record, index) => index + 1 |
|
||||
}, { |
|
||||
title: '结构物名称', |
|
||||
dataIndex: 'name', |
|
||||
key: 'name', |
|
||||
}, { |
|
||||
title: '所在地区', |
|
||||
dataIndex: 'type', |
|
||||
key: 'type', |
|
||||
render: (text, record, index) => { |
|
||||
return record.longitude && record.latitude ? <div style={{ width: 100 }}>{record.longitude},{record.latitude}</div> : "--" |
|
||||
} |
|
||||
}, { |
|
||||
title: '结构物类型', |
|
||||
dataIndex: 'type', |
|
||||
key: 'type', |
|
||||
render: (text, record, index) => record.type || '--' |
|
||||
}, { |
|
||||
title: '描述', |
|
||||
dataIndex: 'describe', |
|
||||
key: 'describe', |
|
||||
render: (text, record, index) => record.describe?.length>10?<Tooltip title={record.describe}><span> |
|
||||
{record?.describe.substring(0,10)}... |
|
||||
</span> |
|
||||
</Tooltip>: record.describe || '--' |
|
||||
}, { |
|
||||
title: '操作', |
|
||||
dataIndex: 'operation', |
|
||||
key: 'operation', |
|
||||
render: (text, record, index) => { |
|
||||
return ( |
|
||||
<div> |
|
||||
<Button type="link" onClick={() => { |
|
||||
setAddModel(true) |
|
||||
setModelData(record) |
|
||||
}} |
|
||||
>编辑</Button> |
|
||||
<Popconfirm |
|
||||
title={<div style={{ width: 180 }}>删除此结构物后,与结构物对应的点位、巡检计划、巡检记录也会删除,是否确认删除?</div>} |
|
||||
position='topLeft' |
|
||||
onConfirm={() => { |
|
||||
dispatch(projectRegime.delProject(record.id)).then(res => { |
|
||||
if (res.success) { |
|
||||
if ((limits > 11 && tableList.length > 1) || limits < 11) { |
|
||||
projectList({ ...query, ...search }) |
|
||||
} else { |
|
||||
projectList({ limit: query?.limit, page: query?.page - 1, ...search }) |
|
||||
setQuery({ limit: query?.limit, page: query?.page - 1 }); |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
}) |
|
||||
}} |
|
||||
> |
|
||||
<Button type="link" danger >删除</Button> |
|
||||
</Popconfirm> |
|
||||
{/* <Button type="link" danger >二维码生成</Button> */} |
|
||||
<Button type="link" onClick={() => { |
|
||||
dispatch(push(`/projectRegime/information/${record.id}/point`)); |
|
||||
}} >点位</Button> |
|
||||
<Button type="link" onClick={() => { |
|
||||
dispatch(push(`/projectRegime/information/${record.id}/deploy`)); |
|
||||
}} >布设</Button> |
|
||||
</div> |
|
||||
) |
|
||||
} |
|
||||
} |
|
||||
] |
|
||||
|
|
||||
return ( |
|
||||
<div className='global-main'> |
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}> |
|
||||
<div className='title'> |
|
||||
<span className='line'></span> |
|
||||
<span className='cn'>结构物</span> |
|
||||
<span className='en'> Structure</span> |
|
||||
</div> |
|
||||
<div className='flex-end'> |
|
||||
<Form |
|
||||
style={{ display: 'flex' }} |
|
||||
onFinish={r => { |
|
||||
projectList({ limit: 10, page: 0, ...r, companyId: companyID || r?.companyId }) |
|
||||
setQuery({ limit: 10, page: 0 }); |
|
||||
setSearch(r) |
|
||||
}} |
|
||||
> |
|
||||
<Form.Item |
|
||||
label='结构物名称' |
|
||||
name="name" |
|
||||
style={{ marginRight: 16, minWidth: 180 }} |
|
||||
> |
|
||||
<Input placeholder="请输入结构物名称" allowClear suffix={<img src='/assets/images/search.svg' style={{ width: 16 }} />} /> |
|
||||
</Form.Item> |
|
||||
<Form.Item wrapperCol={{}}> |
|
||||
<Button htmlType="submit"> |
|
||||
搜索 |
|
||||
</Button> |
|
||||
</Form.Item> |
|
||||
</Form> |
|
||||
<div style={{ display: 'flex', marginLeft: 20 }}> |
|
||||
<Button type="primary" onClick={() => { |
|
||||
setAddModel(true) |
|
||||
}}>新建结构物</Button> |
|
||||
{/* <Button type="primary" style={{ marginLeft: 20 }} onClick={() => { |
|
||||
console.log(45513); |
|
||||
setAddModel(true) |
|
||||
}}>一键生成二维码</Button> */} |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<Table |
|
||||
columns={columns} |
|
||||
dataSource={tableList} |
|
||||
pagination={{ |
|
||||
className: 'global-pagination', |
|
||||
current: query.page + 1, |
|
||||
total: limits, |
|
||||
showSizeChanger: true, |
|
||||
showQuickJumper: true, |
|
||||
pageSizeOptions: [10, 20, 50], |
|
||||
showTotal: (total) => { |
|
||||
return <span style={{ fontSize: 15 }}>{`共${Math.ceil(total / query?.limit)}页,${total}项`}</span> |
|
||||
}, |
|
||||
onChange: (page, pageSize) => { |
|
||||
setQuery({ limit: pageSize, page: page - 1 }); |
|
||||
projectList({ limit: pageSize, page: page - 1, ...search, companyId: companyID || search?.companyId }) |
|
||||
} |
|
||||
}} |
|
||||
rowSelection={{ |
|
||||
selectedRowKeys: select || [], |
|
||||
onChange: (selectedRowKeys, selectedRows) => { |
|
||||
setSelect(selectedRowKeys) |
|
||||
console.log(selectedRowKeys, selectedRows); |
|
||||
} |
|
||||
}} |
|
||||
rowClassName={(record, index) => { |
|
||||
let className = 'global-light-row'; |
|
||||
if (index % 2 === 1) className = 'global-dark-row'; |
|
||||
return className; |
|
||||
}} |
|
||||
// scroll={{ y: 590 }}
|
|
||||
/> |
|
||||
{ |
|
||||
<Modal |
|
||||
// title={ }
|
|
||||
width={570} |
|
||||
open={isPicture} |
|
||||
onOk={() => { }} |
|
||||
footer={null} |
|
||||
onCancel={() => { |
|
||||
setIsPicture(false) |
|
||||
setPictureUrl('') |
|
||||
}} |
|
||||
> |
|
||||
{pictureUrl && pictureUrl[0] ? <img src={`/_file-server/${pictureUrl}`} width={500} /> : "暂无图片"} |
|
||||
</Modal> |
|
||||
} |
|
||||
{ |
|
||||
addModel ? |
|
||||
<ProjectAddModel |
|
||||
firmList={firmList} |
|
||||
modelData={modelData} |
|
||||
close={() => { |
|
||||
setAddModel(false) |
|
||||
setModelData({}) |
|
||||
}} |
|
||||
success={() => { |
|
||||
setAddModel(false) |
|
||||
setModelData({}) |
|
||||
setQuery({ limit: 10, page: 0 }); |
|
||||
projectList({ limit: 10, page: 0, ...search, companyId: companyID || search?.companyId }) |
|
||||
}} |
|
||||
/> : "" |
|
||||
} |
|
||||
</div> |
|
||||
) |
|
||||
} |
|
||||
|
|
||||
function mapStateToProps(state) { |
|
||||
const { auth, global } = state; |
|
||||
return { |
|
||||
user: auth.user, |
|
||||
actions: global.actions, |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
export default connect(mapStateToProps)(Information); |
|
@ -1,30 +0,0 @@ |
|||||
.title { |
|
||||
background-color: #fff; |
|
||||
display: inline-block; |
|
||||
|
|
||||
.line { |
|
||||
display: inline-block; |
|
||||
width: 3px; |
|
||||
height: 20px; |
|
||||
background: #006BE3; |
|
||||
} |
|
||||
|
|
||||
.cn { |
|
||||
font-family: YouSheBiaoTiHei; |
|
||||
font-size: 24px; |
|
||||
color: #101531; |
|
||||
margin-left: 11px; |
|
||||
} |
|
||||
|
|
||||
.en { |
|
||||
font-family: D-DINExp-Italic; |
|
||||
font-weight: Italic; |
|
||||
font-size: 12px; |
|
||||
color: #969799; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.flex-end { |
|
||||
display: flex; |
|
||||
justify-content: flex-end; |
|
||||
} |
|
@ -1,196 +0,0 @@ |
|||||
import React, { useEffect, useState } from 'react'; |
|
||||
import { connect } from 'react-redux'; |
|
||||
import { Button, Table, Popconfirm, Input } from 'antd'; |
|
||||
import '../style.less'; |
|
||||
import PointModel from '../components/pointModel' |
|
||||
|
|
||||
const Information = (props) => { |
|
||||
const { dispatch, actions, devices } = props |
|
||||
const { projectRegime } = actions |
|
||||
const [tableList, settableList] = useState([]) |
|
||||
const [addModel, setAddModel] = useState(false) |
|
||||
const [modelData, setModelData] = useState({}) |
|
||||
const [query, setQuery] = useState({ limit: 10, page: 0 }) |
|
||||
const [limits, setLimits] = useState() |
|
||||
const [search, setSearch] = useState({}) |
|
||||
const [companyID, setCompanyId] = useState('') |
|
||||
const [select, setSelect] = useState([]) |
|
||||
const [selec, setSelec] = useState() |
|
||||
const [qrCodeingIds, setQrCodeingIds] = useState(null) |
|
||||
const [searchTableList, setSearchTableList] = useState([]) |
|
||||
const [name, setName] = useState('') |
|
||||
|
|
||||
const qrCodeId = props?.match?.params?.id |
|
||||
|
|
||||
useEffect(() => { |
|
||||
projectList(query) |
|
||||
}, []) |
|
||||
|
|
||||
const projectList = (obj) => { |
|
||||
const { limit, page } = obj |
|
||||
dispatch(actions.deviceManage.getDeviceList()); |
|
||||
dispatch(projectRegime.positionList({ limit, page: 0, projectId: qrCodeId })).then(res => { |
|
||||
if (res.success) { |
|
||||
let data = [] |
|
||||
res.payload.data?.rows?.map(v => { |
|
||||
v.points?.map(r => { |
|
||||
data?.push(r) |
|
||||
}) |
|
||||
}) |
|
||||
settableList(data?.map(v => ({ ...v, key: v.id }))) |
|
||||
setSearchTableList(data?.map(v => ({ ...v, key: v.id }))) |
|
||||
setLimits(res.payload.data?.count) |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
const columns = [ |
|
||||
{ |
|
||||
title: '序号', |
|
||||
dataIndex: 'index', |
|
||||
key: 'index', |
|
||||
render: (text, record, index) => index + 1 |
|
||||
}, { |
|
||||
title: '点位名称', |
|
||||
dataIndex: 'name', |
|
||||
key: 'name', |
|
||||
}, { |
|
||||
title: '所在地区', |
|
||||
dataIndex: 'position', |
|
||||
key: 'position', |
|
||||
render: (text, record, index) => { |
|
||||
return record.longitude && record.latitude ? <div style={{ width: 100 }}>{record.longitude},{record.latitude}</div> : "--" |
|
||||
} |
|
||||
}, { |
|
||||
title: '描述', |
|
||||
dataIndex: 'describe', |
|
||||
key: 'describe', |
|
||||
render: (text, record, index) => record.describe || '--' |
|
||||
}, { |
|
||||
title: '操作', |
|
||||
dataIndex: 'operation', |
|
||||
key: 'operation', |
|
||||
render: (text, record, index) => { |
|
||||
return ( |
|
||||
<> |
|
||||
<Button type="link" onClick={() => { |
|
||||
setAddModel(true) |
|
||||
setModelData(record) |
|
||||
}}>编辑</Button> |
|
||||
<Popconfirm |
|
||||
title={<div style={{ width: 184 }}>删除该点位后,与巡检计划关联的点位删除,对应的巡检记录删除,是否确认删除?</div>} |
|
||||
position='topLeft' |
|
||||
onConfirm={() => { |
|
||||
dispatch(projectRegime.delPosition(record.id)).then(res => { |
|
||||
if (res.success) { |
|
||||
if ((limits > 11 && tableList.length > 1) || limits < 11) { |
|
||||
projectList({ ...query, ...search }) |
|
||||
} else { |
|
||||
projectList({ limit: query?.limit, page: query?.page - 1, ...search }) |
|
||||
setQuery({ limit: query?.limit, page: query?.page - 1 }); |
|
||||
} |
|
||||
} |
|
||||
}) |
|
||||
}} |
|
||||
> |
|
||||
<Button type="link" danger >删除</Button> |
|
||||
</Popconfirm> |
|
||||
<Button type="link" onClick={() => { |
|
||||
setQrCodeingIds([record.id]) |
|
||||
dispatch(projectRegime.addPosition({ |
|
||||
qrCode: true, |
|
||||
id: record.id, |
|
||||
}, true)).then(() => { |
|
||||
setQrCodeingIds(null) |
|
||||
}) |
|
||||
}} loading={qrCodeingIds?.includes(record.id)}>二维码生成</Button> |
|
||||
</> |
|
||||
) |
|
||||
} |
|
||||
} |
|
||||
] |
|
||||
|
|
||||
return ( |
|
||||
<> |
|
||||
<img src={selec} /> |
|
||||
<div style={{ display: 'flex', marginBottom: 10 }}> |
|
||||
<Button type="primary" onClick={() => { |
|
||||
setAddModel(true) |
|
||||
}}>新建点位</Button> |
|
||||
<Button type="primary" style={{ marginLeft: 20 }} onClick={() => { |
|
||||
if (select.length) { |
|
||||
setQrCodeingIds(select.map(s => s.id)); |
|
||||
select?.map((v, i) => { |
|
||||
dispatch(projectRegime.addPosition({ |
|
||||
qrCode: true, |
|
||||
id: v.id, |
|
||||
}, true)).then(() => { |
|
||||
if (i === select.length - 1) { |
|
||||
setQrCodeingIds(null); |
|
||||
} |
|
||||
}) |
|
||||
}) |
|
||||
} |
|
||||
}} disabled={qrCodeingIds?.length}>一键生成二维码</Button> |
|
||||
<Input style={{ width: 300, margin: '0px 20px' }} placeholder="请输入点位名称" onChange={(e) => { setName(e.target.value) }} /> |
|
||||
<Button type="primary" onClick={() => { |
|
||||
setSearchTableList(tableList?.filter(l => l.name?.includes(name))) |
|
||||
}}>搜索</Button> |
|
||||
</div> |
|
||||
|
|
||||
<Table |
|
||||
columns={columns} |
|
||||
dataSource={searchTableList} |
|
||||
pagination={{ |
|
||||
// current: query.page + 1,
|
|
||||
// total: limits,
|
|
||||
showSizeChanger: true, |
|
||||
showQuickJumper: true, |
|
||||
pageSizeOptions: [10, 20, 50], |
|
||||
showTotal: (total) => { |
|
||||
return <span style={{ fontSize: 15 }}>{`共${Math.ceil(total / query?.limit)}页,${total}项`}</span> |
|
||||
}, |
|
||||
onChange: (page, pageSize) => { |
|
||||
setQuery({ limit: pageSize, page: page - 1 }); |
|
||||
projectList({ limit: pageSize, page: page - 1, ...search, companyId: companyID || search?.companyId }) |
|
||||
} |
|
||||
}} |
|
||||
rowSelection={{ |
|
||||
selectedRowKeys: select?.map(v => v.id) || [], |
|
||||
onChange: (selectedRowKeys, selectedRows) => { |
|
||||
setSelect(selectedRows) |
|
||||
} |
|
||||
}} |
|
||||
/> |
|
||||
{ |
|
||||
addModel ? |
|
||||
<PointModel |
|
||||
modelData={modelData} |
|
||||
qrCodeId={qrCodeId} |
|
||||
devices={devices} |
|
||||
close={() => { |
|
||||
setAddModel(false) |
|
||||
setModelData({}) |
|
||||
}} |
|
||||
success={() => { |
|
||||
setAddModel(false) |
|
||||
setModelData({}) |
|
||||
setQuery({ limit: 10, page: 0 }); |
|
||||
projectList({ limit: 10, page: 0 }) |
|
||||
}} |
|
||||
/> : "" |
|
||||
} |
|
||||
</> |
|
||||
) |
|
||||
} |
|
||||
|
|
||||
function mapStateToProps(state) { |
|
||||
const { auth, global, device } = state; |
|
||||
return { |
|
||||
user: auth.user, |
|
||||
actions: global.actions, |
|
||||
devices: device?.data?.rows || [] |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
export default connect(mapStateToProps)(Information); |
|
@ -1,404 +0,0 @@ |
|||||
'use strict' |
|
||||
|
|
||||
import React, { Component } from 'react'; |
|
||||
import { connect } from 'react-redux'; |
|
||||
import { findDOMNode } from 'react-dom'; |
|
||||
import Heatmap from '../../components/pointDeploy/heatmap'; |
|
||||
import { DragDropContext } from 'react-dnd'; |
|
||||
import HTML5Backend from 'react-dnd-html5-backend'; |
|
||||
import { Layout, Tree, Button, Input, Popconfirm, message, Spin } from 'antd' |
|
||||
const { Content, Sider } = Layout; |
|
||||
const Search = Input.Search; |
|
||||
const TreeNode = Tree.TreeNode; |
|
||||
import StationSpot from '../../components/pointDeploy/station-spot'; |
|
||||
import './deploy-style.less'; |
|
||||
import { getProjectGraph, deleteGraph, getProjectPoints, getDeployPoints, setDeployPoints } from '../../actions/graph'; |
|
||||
import UploadImgModal from './upload-img-modal'; |
|
||||
import PerfectScrollbar from 'perfect-scrollbar'; |
|
||||
|
|
||||
class ConfigPlanarGraph extends Component { |
|
||||
constructor(props) { |
|
||||
super(props); |
|
||||
this.ps = null; |
|
||||
this.state = { |
|
||||
uploadImgModal: '', |
|
||||
searchValue: '', |
|
||||
deployState: -1, //0未布,1已布,-1全部
|
|
||||
filteredSpots: [], |
|
||||
spots: [], |
|
||||
dataHasChanged: false, |
|
||||
} |
|
||||
this.projectId = props?.match?.params?.id |
|
||||
} |
|
||||
|
|
||||
componentDidUpdate() { |
|
||||
let ele = document.getElementById('security-spots-scroller'); |
|
||||
if (ele) { |
|
||||
this.ps = new PerfectScrollbar(ele); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
componentDidMount() { |
|
||||
this.props.dispatch(getProjectPoints(this.projectId));//获取所有点位列表
|
|
||||
this.getData(); |
|
||||
} |
|
||||
|
|
||||
getData = () => { |
|
||||
this.props.dispatch(getProjectGraph(this.projectId)).then(_ => { |
|
||||
if (_.success) { |
|
||||
let graph = _.payload.data; |
|
||||
if (graph) {//有图片
|
|
||||
this.props.dispatch(getDeployPoints(graph.id));//获取平面图点位分布
|
|
||||
} |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
componentWillReceiveProps(nextProps) { |
|
||||
const { allPoints, projectDeployPoints } = nextProps; |
|
||||
if (projectDeployPoints && projectDeployPoints != this.props.projectDeployPoints) { |
|
||||
this.setSpotsState(allPoints, projectDeployPoints); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
setSpotsState = (allPoints, projectDeployPoints) => { |
|
||||
const { searchValue } = this.state; |
|
||||
let deployedSpotsMap = new Map(); |
|
||||
projectDeployPoints?.forEach(s => { |
|
||||
deployedSpotsMap.set(s.pointId, s); |
|
||||
}); |
|
||||
let tempData = []; |
|
||||
allPoints?.map(m => { |
|
||||
let x = null, y = null, screenH = null, screenW = null; |
|
||||
let deployed = false; |
|
||||
let station = deployedSpotsMap.get(m.id); |
|
||||
if (station) { |
|
||||
let p = JSON.parse(station.position); |
|
||||
x = p.x; |
|
||||
y = p.y; |
|
||||
screenH = p.screenHeight; |
|
||||
screenW = p.screenWidth; |
|
||||
deployed = true; |
|
||||
} |
|
||||
tempData.push({ |
|
||||
groupId: 1, |
|
||||
groupName: '全部', |
|
||||
pointId: m.id, |
|
||||
location: m.name, |
|
||||
x: x, |
|
||||
y: y, |
|
||||
screenHeight: screenH, |
|
||||
screenWidth: screenW, |
|
||||
deployed: deployed, |
|
||||
}) |
|
||||
}); |
|
||||
|
|
||||
let searchSpots = tempData; |
|
||||
if (searchValue.trim().length > 0) { |
|
||||
searchSpots = tempData.filter(s => s.location.indexOf(searchValue) >= 0); |
|
||||
} |
|
||||
|
|
||||
this.setState({ |
|
||||
spots: tempData, |
|
||||
filteredSpots: searchSpots, |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
onAddImgClick = () => { |
|
||||
this.openPcrModal(null) |
|
||||
}; |
|
||||
|
|
||||
editHandler = (heatmap) => { |
|
||||
this.openPcrModal(heatmap) |
|
||||
}; |
|
||||
|
|
||||
openPcrModal = (heatmap) => { |
|
||||
const { dispatch } = this.props; |
|
||||
this.setState({ |
|
||||
uploadImgModal: <UploadImgModal |
|
||||
dispatch={dispatch} |
|
||||
projectId={this.projectId} |
|
||||
pictureInfo={heatmap} |
|
||||
onCancel={this.closeUploadPointsImgModal} |
|
||||
getData={this.getData} |
|
||||
/>, |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
closeUploadPointsImgModal = () => { |
|
||||
this.setState({ uploadImgModal: '' }) |
|
||||
}; |
|
||||
|
|
||||
onDeploySpot = (spot) => { |
|
||||
const { pictureInfo, clientHeight, clientWidth } = this.props; |
|
||||
const { spots, deployState, searchValue, partsSpots } = this.state; |
|
||||
const that = this; |
|
||||
let h = clientHeight / 1.3; |
|
||||
let w = clientWidth / 1.4; |
|
||||
function dealPosition(spot, item) { |
|
||||
if (spot.deployed) { |
|
||||
item.x = spot.rect.x + spot.move.x; |
|
||||
item.y = spot.rect.y + spot.move.y; |
|
||||
item.screenHeight = h; |
|
||||
item.screenWidth = w; |
|
||||
} else { |
|
||||
const boundingClientRect = findDOMNode(that.refs.heatmapComponent).getBoundingClientRect(); |
|
||||
item.x = spot.spotInlist.x + spot.move.x - boundingClientRect.left; |
|
||||
item.y = spot.spotInlist.y + spot.move.y - boundingClientRect.top; |
|
||||
item.screenHeight = h; |
|
||||
item.screenWidth = w; |
|
||||
item.deployed = true; |
|
||||
} |
|
||||
} |
|
||||
if (pictureInfo) { |
|
||||
let tempSpots = Object.assign([], spots); |
|
||||
if (spot.info.pointId) { |
|
||||
tempSpots.forEach(item => { |
|
||||
if (item.pointId == spot.info.pointId) { |
|
||||
dealPosition(spot, item) |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
this.setState({ spots: tempSpots }); |
|
||||
this.filterSpots(deployState, searchValue); |
|
||||
this.setState({ changedTreeNodeKey: spot.info.key, dataHasChanged: true }); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
filterSpots = (deployState, searchValue) => { |
|
||||
let deploySpots = this.state.spots; |
|
||||
if (deployState != -1) { |
|
||||
deploySpots = this.state.spots.filter(s => s.deployed == (deployState == 1 ? true : false)); |
|
||||
} |
|
||||
|
|
||||
let searchSpots = deploySpots; |
|
||||
if (searchValue.trim().length > 0) { |
|
||||
searchSpots = deploySpots.filter(s => s.location.indexOf(searchValue) >= 0); |
|
||||
} |
|
||||
|
|
||||
this.setState({ |
|
||||
searchValue, |
|
||||
deployState, |
|
||||
filteredSpots: searchSpots |
|
||||
}); |
|
||||
}; |
|
||||
|
|
||||
onSearch = (searchValue) => { |
|
||||
this.filterSpots(this.state.deployState, searchValue); |
|
||||
}; |
|
||||
handleStateChange = (deployState) => { |
|
||||
this.filterSpots(deployState, this.state.searchValue); |
|
||||
}; |
|
||||
|
|
||||
onRemoveSpot = (spot) => { |
|
||||
const { pictureInfo } = this.props; |
|
||||
const { spots, deployState, searchValue, partsSpots } = this.state; |
|
||||
if (pictureInfo) { |
|
||||
let tempSpots; |
|
||||
if (spot.pointId) { |
|
||||
tempSpots = Object.assign([], spots); |
|
||||
tempSpots.forEach(item => { |
|
||||
if (item.pointId == spot.pointId) { |
|
||||
item.x = null; |
|
||||
item.y = null; |
|
||||
item.screenWidth = null; |
|
||||
item.screenHeight = null; |
|
||||
item.deployed = false; |
|
||||
} |
|
||||
}); |
|
||||
tempSpots = tempSpots.concat(partsSpots) |
|
||||
} else { |
|
||||
tempSpots = Object.assign([], partsSpots); |
|
||||
tempSpots.forEach(item => { |
|
||||
if (item.partId == spot.partId) { |
|
||||
item.x = null; |
|
||||
item.y = null; |
|
||||
item.screenWidth = null; |
|
||||
item.screenHeight = null; |
|
||||
item.deployed = false; |
|
||||
} |
|
||||
}); |
|
||||
tempSpots = tempSpots.concat(spots) |
|
||||
} |
|
||||
this.filterSpots(deployState, searchValue); |
|
||||
this.setState({ changedTreeNodeKey: spot.key, dataHasChanged: true }); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
loop = (data) => { |
|
||||
if (!data || data.length == 0) return; |
|
||||
|
|
||||
const treeNodes = []; |
|
||||
data.forEach((item) => { |
|
||||
let title = <StationSpot info={item} children={item.children} />; |
|
||||
if (item.children) { |
|
||||
treeNodes.push( |
|
||||
<TreeNode key={item.key} title={title}> |
|
||||
{this.loop(item.children)} |
|
||||
</TreeNode> |
|
||||
); |
|
||||
} else { |
|
||||
let titleProps = { |
|
||||
info: item, |
|
||||
children: item.children, |
|
||||
onRemoveSpot: this.onRemoveSpot, |
|
||||
}; |
|
||||
//性能优化,减少组件渲染
|
|
||||
if (this.state.changedTreeNodeKey == item.key) titleProps.key = Math.random(); |
|
||||
let nodeTitle = <StationSpot {...titleProps} />; |
|
||||
treeNodes.push(<TreeNode key={item.key} title={nodeTitle} />); |
|
||||
} |
|
||||
}); |
|
||||
return treeNodes; |
|
||||
}; |
|
||||
|
|
||||
formatTreeSource = (data) => { |
|
||||
if (!data || data.length == 0) return; |
|
||||
let tempGroups = new Map(); |
|
||||
data.map(item => { |
|
||||
if (tempGroups.has(item.groupId)) { |
|
||||
let groupChildren = tempGroups.get(item.groupId).children; |
|
||||
item.key = `0-${item.groupId}-${item.pointId}`; |
|
||||
groupChildren.set(item.pointId, item); |
|
||||
} else { |
|
||||
tempGroups.set(item.groupId, { |
|
||||
'key': `0-${item.groupId}`, |
|
||||
'location': item.groupName, |
|
||||
'groupId': item.groupId, |
|
||||
'children': new Map(), |
|
||||
}); |
|
||||
let groupChildren = tempGroups.get(item.groupId).children; |
|
||||
item.key = `0-${item.groupId}-${item.pointId}`; |
|
||||
groupChildren.set(item.pointId, item); |
|
||||
} |
|
||||
}); |
|
||||
return tempGroups; |
|
||||
}; |
|
||||
|
|
||||
onSaveClick = () => { |
|
||||
this.saveHotspots(this.state.spots); |
|
||||
}; |
|
||||
|
|
||||
saveHotspots = (data) => { |
|
||||
const { pictureInfo } = this.props; |
|
||||
let postData = data.filter(s => s.x != null && s.y != null).map(item => { |
|
||||
const { x, y, screenWidth, screenHeight } = item; |
|
||||
let relativeX = parseFloat((x / screenWidth).toFixed(4)); |
|
||||
let relativeY = parseFloat((y / screenHeight).toFixed(4)); |
|
||||
if (item.pointId) { |
|
||||
return ({ |
|
||||
pointId: item.pointId, |
|
||||
position: { x, y, screenWidth, screenHeight, relativeX, relativeY } |
|
||||
}) |
|
||||
} |
|
||||
}); |
|
||||
this.props.dispatch(setDeployPoints(pictureInfo.id, { "spots": postData })).then(res => { |
|
||||
this.setState({ dataHasChanged: false, deployState: -1 }, () => { |
|
||||
this.props.dispatch(getDeployPoints(pictureInfo.id));//获取平面图点位分布
|
|
||||
}); |
|
||||
}); |
|
||||
}; |
|
||||
|
|
||||
render() { |
|
||||
const { pictureInfo, clientHeight, clientWidth, allPoints } = this.props; |
|
||||
const { deployState, spots, filteredSpots, dataHasChanged } = this.state; |
|
||||
const treeDataSource = this.formatTreeSource(filteredSpots); |
|
||||
let h = clientHeight / 1.3; |
|
||||
let w = clientWidth / 1.4; |
|
||||
return (<div className='patrolLayout'> |
|
||||
<header className='title' style={{ marginBottom: 10 }}> |
|
||||
<span className='line'></span> |
|
||||
<span className='cn'>布设信息</span> |
|
||||
<span className='en'> DEPLOYMENT INFORMATION</span> |
|
||||
</header> |
|
||||
<Layout> |
|
||||
<Sider width={'23%'} style={{ background: 'transparent' }}> |
|
||||
<div style={{ display: 'flex' }}> |
|
||||
<div style={{ display: 'flex', flexDirection: 'column' }}> |
|
||||
<Button className={deployState == -1 ? 'btn-spots-filter' : 'btn-default'} style={{ borderRadius: 0, margin: '0 20px 7px 0' }} onClick={() => this.handleStateChange(-1)}>全部</Button> |
|
||||
<Button className={deployState == 1 ? 'btn-spots-filter' : 'btn-default'} style={{ borderRadius: 0, margin: '0 20px 7px 0' }} onClick={() => this.handleStateChange(1)}>已布</Button> |
|
||||
<Button className={deployState == 0 ? 'btn-spots-filter' : 'btn-default'} style={{ borderRadius: 0, margin: '0 20px 7px 0' }} onClick={() => this.handleStateChange(0)}>未布</Button> |
|
||||
</div> |
|
||||
<div className='PingFangSC-Regular'>点位:</div> |
|
||||
<div> |
|
||||
<div className='search-panel'> |
|
||||
<div style={{ marginTop: -1 }}> |
|
||||
<Search |
|
||||
placeholder={"请输入名称关键字搜索"} |
|
||||
style={{ borderRadius: 0 }} |
|
||||
onChange={e => this.onSearch(e.target.value)} |
|
||||
/> |
|
||||
</div> |
|
||||
</div> |
|
||||
{ |
|
||||
treeDataSource ? |
|
||||
<div id='security-spots-scroller' style={{ position: 'relative', height: h - 63 }}> |
|
||||
<Tree className='equip-tree' showLine defaultExpandAll={true}> |
|
||||
{this.loop(treeDataSource)} |
|
||||
</Tree> </div> : <div style={{ textAlign: 'center' }}>暂无点位</div> |
|
||||
} |
|
||||
</div> |
|
||||
</div> |
|
||||
</Sider> |
|
||||
<Layout> |
|
||||
<Content className='spots-opr-content' style={{ width: w }}> |
|
||||
{spots && pictureInfo?.graph ? |
|
||||
<Heatmap key={Math.random()} |
|
||||
ref="heatmapComponent" |
|
||||
height={h} |
|
||||
width={w} |
|
||||
image={pictureInfo?.graph} |
|
||||
spots={spots.filter(s => s.deployed == true)} |
|
||||
onRemoveSpot={this.onRemoveSpot} |
|
||||
onDeploySpot={this.onDeploySpot} |
|
||||
/> |
|
||||
: <div style={{ border: '1px dashed #999', width: w, height: h, paddingTop: h * 0.3, textAlign: 'center' }}> |
|
||||
<img className='no-deploy-img' src='/assets/images/no_deploy.svg'></img> |
|
||||
<div className='PingFangSC-Regular'>暂无热点图~</div> |
|
||||
</div> |
|
||||
} |
|
||||
<div className='opr-tip-row'> |
|
||||
<div className='PingFangSC-Regular'>说明:拖拽点位进行布设,拖出画布移除点位。</div> |
|
||||
{ |
|
||||
pictureInfo ? |
|
||||
<div className='opr-button'> |
|
||||
<Popconfirm |
|
||||
title='确认删除该结构物布设图?(已布点位将同步删除)' |
|
||||
position='top' |
|
||||
onConfirm={() => { |
|
||||
this.props.dispatch(deleteGraph(pictureInfo.id)).then(_ => { |
|
||||
this.getData(); |
|
||||
this.setSpotsState(allPoints, []) |
|
||||
}) |
|
||||
}}> |
|
||||
<Button className='graph-cfg-btn'>删除图片</Button> |
|
||||
</Popconfirm> |
|
||||
<Button className='graph-cfg-btn' onClick={() => this.editHandler(pictureInfo)} style={{ marginLeft: 15 }}>修改图片</Button> |
|
||||
<Button className='graph-cfg-btn' type='primary' onClick={this.onSaveClick} disabled={!dataHasChanged} style={{ marginLeft: 15 }}>完成</Button> |
|
||||
</div> |
|
||||
: |
|
||||
<div className='opr-button'> |
|
||||
<Button className='graph-cfg-btn' type='primary' onClick={this.onAddImgClick}>添加布设图</Button> |
|
||||
</div> |
|
||||
} |
|
||||
</div> |
|
||||
</Content> |
|
||||
</Layout> |
|
||||
</Layout> |
|
||||
{this.state.uploadImgModal} |
|
||||
</div>) |
|
||||
} |
|
||||
} |
|
||||
function mapStateToProps(state) { |
|
||||
const { global, projectGraph, projectDeployPoints, projectAllPoints } = state; |
|
||||
return { |
|
||||
pictureInfo: projectGraph.data, |
|
||||
projectDeployPoints: projectDeployPoints?.data || [], |
|
||||
clientHeight: global.clientHeight, |
|
||||
clientWidth: global.clientWidth, |
|
||||
allPoints: projectAllPoints?.data || [] |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
export default connect(mapStateToProps)(DragDropContext(HTML5Backend)(ConfigPlanarGraph)); |
|
@ -1,137 +0,0 @@ |
|||||
.spots-opr-content { |
|
||||
padding: 0; |
|
||||
margin: 0; |
|
||||
position: relative; |
|
||||
} |
|
||||
|
|
||||
.opr-tip-row { |
|
||||
display: flex; |
|
||||
margin-top: 10px; |
|
||||
justify-content: space-between; |
|
||||
} |
|
||||
|
|
||||
.opr-button { |
|
||||
|
|
||||
.ant-btn-disabled, |
|
||||
.ant-btn.disabled, |
|
||||
.ant-btn[disabled] { |
|
||||
//按钮 禁用 |
|
||||
background-color: #3198F7; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.graph-cfg-btn { |
|
||||
color: #fff; |
|
||||
background-color: #3198F7; |
|
||||
border-color: #3198F7; |
|
||||
} |
|
||||
|
|
||||
//蓝色按钮 鼠标悬浮 |
|
||||
.graph-cfg-btn:hover, |
|
||||
.graph-cfg-btn:focus { |
|
||||
//color: #fff; |
|
||||
background-color: #3198F7; |
|
||||
border-color: #3198F7; |
|
||||
} |
|
||||
|
|
||||
.patrolLayout { |
|
||||
margin-top: 20px; |
|
||||
background-color: #fff; |
|
||||
padding: 10px 16px; |
|
||||
|
|
||||
.ant-layout { |
|
||||
background-color: transparent; |
|
||||
} |
|
||||
|
|
||||
.ant-input:hover, |
|
||||
.ant-input:focus { |
|
||||
border-color: #fff; |
|
||||
} |
|
||||
|
|
||||
.search-panel { |
|
||||
text-align: center; |
|
||||
margin-bottom: 7px; |
|
||||
|
|
||||
.btn-spots-filter { |
|
||||
//选中的 |
|
||||
background-color: #3198F7; |
|
||||
border-color: #3198F7; |
|
||||
color: #fff; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.search-panel input { |
|
||||
-webkit-border-radius: 0; |
|
||||
-moz-border-radius: 0; |
|
||||
border-radius: 0; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.equip-tree { |
|
||||
|
|
||||
//测点 树结构 |
|
||||
.ant-tree.ant-tree-show-line li span.ant-tree-switcher { |
|
||||
//展开, 关闭按钮 |
|
||||
color: #fff; |
|
||||
} |
|
||||
|
|
||||
.ant-tree li .ant-tree-node-content-wrapper { |
|
||||
//文字白色 |
|
||||
color: #fff; |
|
||||
} |
|
||||
|
|
||||
.ant-tree.ant-tree-show-line li:not(:last-child)::before { |
|
||||
//不显示竖线 |
|
||||
width: 0px; |
|
||||
border: 0px; |
|
||||
} |
|
||||
|
|
||||
.ant-tree li .ant-tree-node-content-wrapper.ant-tree-node-selected { |
|
||||
background-color: #98e5f381; |
|
||||
} |
|
||||
|
|
||||
.ant-tree-node-content-wrapper:hover, |
|
||||
.ant-tree-node-content-wrapper:focus { |
|
||||
//文字鼠标悬浮 背景色 蓝色 |
|
||||
background-color: #3198F7 !important; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
//查询按钮 |
|
||||
.ant-input-group-addon { |
|
||||
background-color: transparent; |
|
||||
|
|
||||
.ant-btn { |
|
||||
background-color: transparent !important; |
|
||||
} |
|
||||
|
|
||||
.ant-btn-primary { |
|
||||
float: right; |
|
||||
width: 90px; |
|
||||
height: 45px; |
|
||||
margin: 5px 0px 0px 10px; |
|
||||
background-color: #3198f7; |
|
||||
border-color: #3198f7; |
|
||||
} |
|
||||
|
|
||||
.ant-btn-primary:hover { |
|
||||
border-color: #3198f7; |
|
||||
} |
|
||||
|
|
||||
.ant-btn-primary:focus { |
|
||||
border-color: #3198f7; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.PingFangSC-Regular { |
|
||||
font-family: PingFangSC-Regular; |
|
||||
font-weight: 400; |
|
||||
font-size: 14px; |
|
||||
color: #4A4A4A; |
|
||||
line-height: 30px; |
|
||||
} |
|
||||
|
|
||||
.no-deploy-img { |
|
||||
width: 289px; |
|
||||
height: 216px; |
|
||||
} |
|
@ -1,94 +0,0 @@ |
|||||
import React, { useEffect, useState } from 'react'; |
|
||||
import { connect } from 'react-redux'; |
|
||||
import Uploads from '$components/Uploads'; |
|
||||
import { Input, Modal, Form, Button, message, Select } from 'antd'; |
|
||||
import { getProjectGraph, createGraph, updateGraph } from '../../actions/graph'; |
|
||||
|
|
||||
const DisclosureModal = (props) => { |
|
||||
const { dispatch, onCancel, projectId, pictureInfo, getData } = props; |
|
||||
let files = pictureInfo ? [{ storageUrl: pictureInfo.graph }] : [] |
|
||||
const [form] = Form.useForm(); |
|
||||
const [editUrl, setEditUrl] = useState(files); |
|
||||
//初始化表单数据
|
|
||||
const getinitialValues = () => { |
|
||||
if (pictureInfo) { |
|
||||
return { files: 1 }; |
|
||||
} |
|
||||
return {} |
|
||||
}; |
|
||||
|
|
||||
useEffect(() => { |
|
||||
}, []); |
|
||||
|
|
||||
const handleOk = () => { |
|
||||
form.validateFields().then(values => { |
|
||||
let data = { |
|
||||
projectId: projectId, |
|
||||
graph: editUrl[0]?.storageUrl, |
|
||||
} |
|
||||
if (pictureInfo) {//更新
|
|
||||
dispatch(updateGraph(pictureInfo.id, data)).then(_ => { |
|
||||
getData() |
|
||||
}); |
|
||||
} else {//新增
|
|
||||
dispatch(createGraph(data)).then(_ => { |
|
||||
getData(); |
|
||||
}); |
|
||||
} |
|
||||
onCancel() |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
const vsjunct = (params) => { |
|
||||
if (params.length) { |
|
||||
let appendix = [] |
|
||||
for (let p of params) { |
|
||||
appendix.push({ |
|
||||
fName: p.name, |
|
||||
size: p.size, |
|
||||
fileSize: p.size, |
|
||||
storageUrl: p.storageUrl,//必须有storageUrl
|
|
||||
}) |
|
||||
} |
|
||||
setEditUrl(appendix) |
|
||||
} else { |
|
||||
setEditUrl([]) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return ( |
|
||||
<Modal title='添加布设图' visible={true} destroyOnClose |
|
||||
onCancel={onCancel} onOk={handleOk}> |
|
||||
<Form form={form} labelCol={{ span: 6 }} wrapperCol={{ span: 17 }} initialValues={getinitialValues()}> |
|
||||
<Form.Item label="布设图" name='files' |
|
||||
rules={[{ required: true, message: '请上传布设图' }]}> |
|
||||
<Uploads |
|
||||
className='upload' |
|
||||
listType='card' |
|
||||
uploadType='project' |
|
||||
maxFilesNum={1} |
|
||||
maxFileSize={10} |
|
||||
isQiniu={true} |
|
||||
onChange={vsjunct} |
|
||||
fileTypes={["png", "jpeg", "jpg"]} |
|
||||
value={editUrl} |
|
||||
defaultValue={editUrl} |
|
||||
/> |
|
||||
</Form.Item> |
|
||||
<Form.Item style={{ paddingLeft: '17%' }}> |
|
||||
<div style={{ color: '#999', width: 460 }}>说明:附件格式为png、jpeg、jpg,大小不超过10MB</div> |
|
||||
</Form.Item> |
|
||||
</Form> |
|
||||
</Modal> |
|
||||
) |
|
||||
} |
|
||||
|
|
||||
function mapStateToProps(state) { |
|
||||
const { auth, global } = state; |
|
||||
return { |
|
||||
user: auth.user, |
|
||||
actions: global.actions, |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
export default connect(mapStateToProps)(DisclosureModal); |
|
@ -1,173 +0,0 @@ |
|||||
import React, { useEffect, useState } from 'react'; |
|
||||
import { connect } from 'react-redux'; |
|
||||
import { Form, Input, Select, Button, message } from 'antd'; |
|
||||
import JSZip from 'jszip'; |
|
||||
import './qrCode.less'; |
|
||||
|
|
||||
const QrCode = (props) => { |
|
||||
const { dispatch, actions } = props |
|
||||
const { projectRegime } = actions |
|
||||
const [firmList, setFirmList] = useState([]) |
|
||||
const [tableList, settableList] = useState([]) |
|
||||
const [downloading, setDownloading] = useState(false) |
|
||||
|
|
||||
useEffect(() => { |
|
||||
dispatch(projectRegime.getProjectList({ justStructure: true })).then(res => { |
|
||||
if (res.success) { |
|
||||
setFirmList(res.payload.data?.rows?.map(v => ({ value: v.id, label: v.name }))) |
|
||||
} |
|
||||
}) |
|
||||
projectList({}) |
|
||||
}, []) |
|
||||
|
|
||||
const projectList = (obj) => { |
|
||||
const { projectId, name } = obj |
|
||||
dispatch(projectRegime.qrCodeShow({ projectId, name })).then(res => { |
|
||||
if (res.success) { |
|
||||
settableList(res.payload.data?.rows) |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
|
|
||||
const imgError = (e) => { |
|
||||
const img = e.currentTarget; |
|
||||
img.src = '/assets/images/no_qcoder.png'; |
|
||||
img.onerror = null; |
|
||||
} |
|
||||
|
|
||||
const batchDownload = () => { |
|
||||
if (tableList.length === 0) { |
|
||||
message.warning('没有数据可以导出') |
|
||||
return |
|
||||
} |
|
||||
setDownloading(true) |
|
||||
let promiseArr = [], nameArr = [] |
|
||||
tableList.forEach(l => { |
|
||||
promiseArr.push( |
|
||||
window.fetch(`/_file-server/${l.qrCode}`, { |
|
||||
method: 'get', |
|
||||
headers: { |
|
||||
"Accept": "application/json", |
|
||||
"Content-Type": "application/json", |
|
||||
"X-Requested-With": "XMLHttpRequest", |
|
||||
}, |
|
||||
}) |
|
||||
) |
|
||||
nameArr.push(l.name + '.jpeg') |
|
||||
}) |
|
||||
try { |
|
||||
Promise.all(promiseArr).then(async resArr => { |
|
||||
const zip = new JSZip() |
|
||||
for (let i = 0; i < resArr.length; i++) { |
|
||||
const response = resArr[i] |
|
||||
const blob = await response.blob() |
|
||||
zip.file(nameArr[i], blob) |
|
||||
} |
|
||||
zip.generateAsync({ type: "blob" }).then(blob => { |
|
||||
const url = window.URL.createObjectURL(blob) |
|
||||
downloadFile(url, "点位二维码.zip") |
|
||||
setDownloading(false) |
|
||||
message.success('下载成功') |
|
||||
}); |
|
||||
}) |
|
||||
} catch (error) { |
|
||||
console.log(error) |
|
||||
setDownloading(false) |
|
||||
message.error('下载失败') |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return ( |
|
||||
<div className='global-main'> |
|
||||
<div className='top'> |
|
||||
<div className='title'> |
|
||||
<span className='line'></span> |
|
||||
<span className='cn'>二维码</span> |
|
||||
<span className='en'> QRCode</span> |
|
||||
</div> |
|
||||
<Form |
|
||||
style={{ display: 'flex', }} |
|
||||
onFinish={r => { |
|
||||
projectList(r) |
|
||||
}} |
|
||||
> |
|
||||
<Form.Item |
|
||||
label='结构物名称' |
|
||||
name="projectId" |
|
||||
style={{ marginRight: 16, width: 240 }} |
|
||||
// initialValue={firmList[0]?.name}
|
|
||||
> |
|
||||
<Select allowClear placeholder="请选择结构物名称" options={firmList} /> |
|
||||
</Form.Item> |
|
||||
<Form.Item |
|
||||
label='点位名称' |
|
||||
name="name" |
|
||||
style={{ marginRight: 16, width: 260 }} |
|
||||
> |
|
||||
<Input placeholder="请输入点位名称" allowClear /> |
|
||||
</Form.Item> |
|
||||
<Form.Item wrapperCol={{}}> |
|
||||
<Button htmlType="submit" style={{ marginRight: 16 }}>搜索</Button> |
|
||||
<Button type="primary" onClick={batchDownload} loading={downloading}>导出</Button> |
|
||||
</Form.Item> |
|
||||
</Form> |
|
||||
</div> |
|
||||
|
|
||||
<div> |
|
||||
{ |
|
||||
tableList?.map(v => { |
|
||||
return <div key={v.name + v.id} |
|
||||
style={{ |
|
||||
display: 'inline-block', |
|
||||
margin: '0 20px 20px 0', |
|
||||
border: '1px solid #3c383824', |
|
||||
borderRadius: '3px' |
|
||||
}} |
|
||||
> |
|
||||
<img src={`/_file-server/${v.qrCode}`} style={{ display: 'inline-block', width: 234 }} onError={imgError} /> |
|
||||
<div style={{ |
|
||||
display: 'flex', flexDirection: 'column', padding: '6px 0', |
|
||||
width: 220, alignItems: 'center' |
|
||||
}}> |
|
||||
<span className='stru-name'>{firmList?.filter(u => u.value == v.projectId)[0]?.label}</span> |
|
||||
<span className='point-name'>点位名称:{v.name}</span> |
|
||||
</div> |
|
||||
<div style={{ |
|
||||
width: 234, height: 60, display: 'flex', |
|
||||
justifyContent: 'center', alignItems: 'center', |
|
||||
}}> |
|
||||
<Button type="primary" onClick={() => { |
|
||||
const tempArr = v.qrCode.split('/') |
|
||||
const filename = tempArr[tempArr.length - 1] |
|
||||
downloadFile(`/_file-server/${v.qrCode}`, filename) |
|
||||
}}>下载二维码</Button> |
|
||||
</div> |
|
||||
</div> |
|
||||
} |
|
||||
) |
|
||||
} |
|
||||
</div> |
|
||||
|
|
||||
</div> |
|
||||
) |
|
||||
} |
|
||||
|
|
||||
function mapStateToProps(state) { |
|
||||
const { auth, global } = state; |
|
||||
return { |
|
||||
user: auth.user, |
|
||||
actions: global.actions, |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
export default connect(mapStateToProps)(QrCode); |
|
||||
|
|
||||
function downloadFile(url, fileName) { |
|
||||
const a = document.createElement('a'); |
|
||||
a.style.display = 'none'; |
|
||||
a.href = url; |
|
||||
a.download = fileName; |
|
||||
document.body.appendChild(a); |
|
||||
a.click(); |
|
||||
document.body.removeChild(a); |
|
||||
} |
|
@ -1,44 +0,0 @@ |
|||||
.top { |
|
||||
display: flex; |
|
||||
justify-content: space-between; |
|
||||
|
|
||||
.title { |
|
||||
background-color: #fff; |
|
||||
display: inline-block; |
|
||||
|
|
||||
.line { |
|
||||
display: inline-block; |
|
||||
width: 3px; |
|
||||
height: 20px; |
|
||||
background: #006BE3; |
|
||||
} |
|
||||
|
|
||||
.cn { |
|
||||
font-family: YouSheBiaoTiHei; |
|
||||
font-size: 24px; |
|
||||
color: #101531; |
|
||||
margin-left: 11px; |
|
||||
} |
|
||||
|
|
||||
.en { |
|
||||
font-family: D-DINExp-Italic; |
|
||||
font-weight: Italic; |
|
||||
font-size: 12px; |
|
||||
color: #969799; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
.stru-name { |
|
||||
font-family: PingFangSC-Medium; |
|
||||
font-weight: 500; |
|
||||
font-size: 16px; |
|
||||
color: #323233; |
|
||||
} |
|
||||
.point-name { |
|
||||
font-family: PingFangSC-Regular; |
|
||||
font-weight: 400; |
|
||||
font-size: 14px; |
|
||||
color: #646566; |
|
||||
line-height: 18px; |
|
||||
} |
|
@ -1,15 +0,0 @@ |
|||||
'use strict'; |
|
||||
|
|
||||
import reducers from './reducers'; |
|
||||
import routes from './routes'; |
|
||||
import actions from './actions'; |
|
||||
import { getNavItem } from './nav-item'; |
|
||||
|
|
||||
export default { |
|
||||
key: 'projectRegime', |
|
||||
name: '结构物管理', |
|
||||
reducers: reducers, |
|
||||
routes: routes, |
|
||||
actions: actions, |
|
||||
getNavItem: getNavItem |
|
||||
}; |
|
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue