diff --git a/web/client/src/sections/projectRegime/actions/graph.js b/web/client/src/sections/projectRegime/actions/graph.js new file mode 100644 index 0000000..6a8e2f5 --- /dev/null +++ b/web/client/src/sections/projectRegime/actions/graph.js @@ -0,0 +1,72 @@ +'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 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: '结构物平面图点位布设' }, + }); +} \ No newline at end of file diff --git a/web/client/src/sections/projectRegime/actions/index.js b/web/client/src/sections/projectRegime/actions/index.js index 4e50055..8e9388b 100644 --- a/web/client/src/sections/projectRegime/actions/index.js +++ b/web/client/src/sections/projectRegime/actions/index.js @@ -2,8 +2,9 @@ import * as projectSituation from './projectSituation' +import * as projectGraph from './graph' export default { ...projectSituation, - + ...projectGraph } \ No newline at end of file diff --git a/web/client/src/sections/projectRegime/actions/projectSituation.js b/web/client/src/sections/projectRegime/actions/projectSituation.js index ab045b8..f159551 100644 --- a/web/client/src/sections/projectRegime/actions/projectSituation.js +++ b/web/client/src/sections/projectRegime/actions/projectSituation.js @@ -60,6 +60,7 @@ export function positionList (query) { actionType: 'POSITION_LIST', url: ApiTable.position, msg: { error: '获取点位列表失败', }, + reducer: { name: 'projectPoints' } }); } diff --git a/web/client/src/sections/projectRegime/components/pointDeploy/heatmap.js b/web/client/src/sections/projectRegime/components/pointDeploy/heatmap.js new file mode 100644 index 0000000..33545ac --- /dev/null +++ b/web/client/src/sections/projectRegime/components/pointDeploy/heatmap.js @@ -0,0 +1,57 @@ +'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 => ); + } + + 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( +
+ {this.renderSpots()} +
+ ) + } +} + +export default DropTarget('stationSpot', heatmapTarget, collect)(Heatmap); + diff --git a/web/client/src/sections/projectRegime/components/pointDeploy/station-spot.js b/web/client/src/sections/projectRegime/components/pointDeploy/station-spot.js new file mode 100644 index 0000000..a92412d --- /dev/null +++ b/web/client/src/sections/projectRegime/components/pointDeploy/station-spot.js @@ -0,0 +1,114 @@ +/** + * 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 ( + + + + {location.length >= 12 ? location.substring(0, 12) + "..." : location} + + {deployed ? : null} + + + ); + }; + + 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 + +
+
+
+
+
+ }; + + render() { + const { connectDragSource, size } = this.props; + return connectDragSource( + size ? this.renderHotspot() : this.renderTreeTitle() + ); + } +} + +export default connect()(DragSource('stationSpot', stationSource, collect)(StationSpot)); diff --git a/web/client/src/sections/projectRegime/components/pointDeploy/style.css b/web/client/src/sections/projectRegime/components/pointDeploy/style.css new file mode 100644 index 0000000..f93610e --- /dev/null +++ b/web/client/src/sections/projectRegime/components/pointDeploy/style.css @@ -0,0 +1,91 @@ +.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; +} diff --git a/web/client/src/sections/projectRegime/containers/index.js b/web/client/src/sections/projectRegime/containers/index.js index 8dee879..4393996 100644 --- a/web/client/src/sections/projectRegime/containers/index.js +++ b/web/client/src/sections/projectRegime/containers/index.js @@ -4,6 +4,6 @@ import QrCode from './qrCode' import Information from './information' import Point from './point' +import PointDeploy from './pointDeploy/default' - -export { QrCode, Information, Point }; +export { QrCode, Information, Point, PointDeploy }; \ No newline at end of file diff --git a/web/client/src/sections/projectRegime/containers/information.js b/web/client/src/sections/projectRegime/containers/information.js index f5936b0..aa9eea0 100644 --- a/web/client/src/sections/projectRegime/containers/information.js +++ b/web/client/src/sections/projectRegime/containers/information.js @@ -95,7 +95,7 @@ const Information = (props) => { key: 'operation', render: (text, record, index) => { return ( -
+
*/} +
) } @@ -228,7 +231,7 @@ const Information = (props) => { ) } -function mapStateToProps (state) { +function mapStateToProps(state) { const { auth, global } = state; return { user: auth.user, diff --git a/web/client/src/sections/projectRegime/containers/pointDeploy/default.js b/web/client/src/sections/projectRegime/containers/pointDeploy/default.js new file mode 100644 index 0000000..fa3f90f --- /dev/null +++ b/web/client/src/sections/projectRegime/containers/pointDeploy/default.js @@ -0,0 +1,384 @@ +'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, 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.getData(); + } + + getData = () => { + this.props.dispatch(getProjectGraph(this.projectId)).then(_ => { + if (_.success) { + let graph = _.payload.data; + if (graph) {//有图片 + this.props.dispatch(getDeployPoints(graph.id));//获取平面图点位分布 + } else { + this.setSpotsState([]); + } + } + }); + } + + componentWillReceiveProps(nextProps) { + const { projectDeployPoints } = nextProps; + if (projectDeployPoints && projectDeployPoints != this.props.projectDeployPoints) { + this.setSpotsState(projectDeployPoints); + } + } + + setSpotsState = (projectDeployPoints) => { + let deployedSpotsMap = new Map(); + projectDeployPoints.setedPoints?.forEach(s => { + deployedSpotsMap.set(s.pointId, s); + }); + let tempData = []; + projectDeployPoints.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, + }) + }); + this.setState({ + spots: tempData, + filteredSpots: tempData, + }); + } + + onAddImgClick = () => { + this.openPcrModal(null) + }; + + editHandler = (heatmap) => { + this.openPcrModal(heatmap) + }; + + openPcrModal = (heatmap) => { + const { dispatch } = this.props; + this.setState({ + uploadImgModal: , + }) + } + + 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.3; + 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 = ; + if (item.children) { + treeNodes.push( + + {this.loop(item.children)} + + ); + } else { + let titleProps = { + info: item, + children: item.children, + onRemoveSpot: this.onRemoveSpot, + }; + //性能优化,减少组件渲染 + if (this.state.changedTreeNodeKey == item.key) titleProps.key = Math.random(); + let nodeTitle = ; + treeNodes.push(); + } + }); + 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 => { + message.success(res.payload.message); + this.setState({ dataHasChanged: false, deployState: -1 }, () => { + this.props.dispatch(getDeployPoints(pictureInfo.id));//获取平面图点位分布 + }); + }); + }; + + render() { + const { pictureInfo, clientHeight, clientWidth } = this.props; + const { deployState, spots, filteredSpots, dataHasChanged } = this.state; + const treeDataSource = this.formatTreeSource(filteredSpots); + let h = clientHeight / 1.3; + let w = clientWidth / 1.3; + return (
+ + +
+ + + +
+ this.onSearch(e.target.value)} + /> +
+
+ { + treeDataSource ? +
+ + {this.loop(treeDataSource)} +
:
暂无点位
+ } +
+ + + {spots && pictureInfo?.graph ? + s.deployed == true)} + onRemoveSpot={this.onRemoveSpot} + onDeploySpot={this.onDeploySpot} + /> + :
+ 暂无热点图 +
+ } +
+
说明:拖拽点位进行布设,拖出画布移除点位。
+ { + pictureInfo ? +
+ { + this.props.dispatch(deleteGraph(pictureInfo.id)).then(_ => { + this.getData(); + }) + }}> + + + + +
+ : +
+ +
+ } +
+
+
+
+ {this.state.uploadImgModal} +
) + } +} +function mapStateToProps(state) { + const { global, projectGraph, projectDeployPoints } = state; + return { + pictureInfo: projectGraph.data, + projectDeployPoints: projectDeployPoints.data, + clientHeight: global.clientHeight, + clientWidth: global.clientWidth + }; +} + +export default connect(mapStateToProps)(DragDropContext(HTML5Backend)(ConfigPlanarGraph)); \ No newline at end of file diff --git a/web/client/src/sections/projectRegime/containers/pointDeploy/deploy-style.less b/web/client/src/sections/projectRegime/containers/pointDeploy/deploy-style.less new file mode 100644 index 0000000..c61a5f1 --- /dev/null +++ b/web/client/src/sections/projectRegime/containers/pointDeploy/deploy-style.less @@ -0,0 +1,114 @@ +.search-panel { + text-align: center; +} + +.search-panel input { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 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; + + .ant-layout { + background-color: transparent; + } + + .ant-input:hover, + .ant-input:focus { + border-color: #fff; + } +} + +.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; + } +} \ No newline at end of file diff --git a/web/client/src/sections/projectRegime/containers/pointDeploy/upload-img-modal.js b/web/client/src/sections/projectRegime/containers/pointDeploy/upload-img-modal.js new file mode 100644 index 0000000..8917fe4 --- /dev/null +++ b/web/client/src/sections/projectRegime/containers/pointDeploy/upload-img-modal.js @@ -0,0 +1,94 @@ +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 ( + +
+ + + + +
说明:附件格式为png、jpeg、jpg,大小不超过10MB
+
+
+
+ ) +} + +function mapStateToProps(state) { + const { auth, global } = state; + return { + user: auth.user, + actions: global.actions, + } +} + +export default connect(mapStateToProps)(DisclosureModal); \ No newline at end of file diff --git a/web/client/src/sections/projectRegime/routes.js b/web/client/src/sections/projectRegime/routes.js index e722522..d553570 100644 --- a/web/client/src/sections/projectRegime/routes.js +++ b/web/client/src/sections/projectRegime/routes.js @@ -1,5 +1,5 @@ 'use strict'; -import { Information, QrCode, Point } from './containers'; +import { Information, QrCode, Point, PointDeploy } from './containers'; export default [{ type: 'inner', @@ -13,13 +13,23 @@ export default [{ key: 'information', breadcrumb: '结构物基础信息管理', component: Information, - childRoutes: [ { - path: '/:id', - key: ':id', + childRoutes: [{ + path: '/:id', + key: ':id', + //component: null, + breadcrumb: '结构物', + childRoutes: [{ + path: '/point', + key: 'point', component: Point, breadcrumb: '点位', - }, - ] + }, { + path: '/deploy', + key: 'deploy', + component: PointDeploy, + breadcrumb: '布设', + }] + }] }, { path: '/qrCode', key: 'qrCode', diff --git a/web/client/src/utils/webapi.js b/web/client/src/utils/webapi.js index 8232b71..79ad0a1 100644 --- a/web/client/src/utils/webapi.js +++ b/web/client/src/utils/webapi.js @@ -129,6 +129,13 @@ export const ApiTable = { //项目状态配置 editProjectStatus: 'project/status', + //工地平面图 + getProjectGraph: 'project/{projectId}/planarGraph', + createGraph: 'planarGraph/add', + updateGraph: 'planarGraph/{id}/modify', + deleteGraph: 'project/graph/{id}', + getDeployPoints: 'picture/{pictureId}/deploy/points', + setDeployPoints: 'set/picture/{pictureId}/deploy/points', }; export const RouteTable = { diff --git a/web/package.json b/web/package.json index 1899540..2cd6963 100644 --- a/web/package.json +++ b/web/package.json @@ -95,6 +95,8 @@ "npm": "^7.20.6", "qrcode": "^1.5.1", "qs": "^6.10.1", + "react-dnd": "^7", + "react-dnd-html5-backend": "^7", "react-color": "^2.19.3", "react-router-breadcrumbs-hoc": "^4.0.1", "react-sortable-hoc": "^2.0.0",