Compare commits
3 Commits
91fbc45086
...
03b2e0bc85
Author | SHA1 | Date |
---|---|---|
wuqun | 03b2e0bc85 | 2 years ago |
wuqun | 8aae0a4408 | 2 years ago |
wuqun | 17e0ee80c6 | 2 years ago |
19 changed files with 1324 additions and 12 deletions
@ -0,0 +1,209 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
async function findSingleGraph(ctx, next) { |
||||
|
let error = { name: 'FindSingleError', message: '查询单一数据失败' }; |
||||
|
let rslt = null; |
||||
|
const { projectId } = ctx.params; |
||||
|
try { |
||||
|
rslt = await ctx.fs.dc.models.ProjectGraph.findOne({ |
||||
|
where: { projectId: projectId } |
||||
|
}); |
||||
|
error = null; |
||||
|
} catch (err) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${err}`); |
||||
|
} |
||||
|
if (error) { |
||||
|
ctx.status = 400; |
||||
|
ctx.body = error; |
||||
|
} else { |
||||
|
ctx.status = 200; |
||||
|
ctx.body = rslt; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async function createGraph(ctx, next) { |
||||
|
let error = { name: 'AddError', message: '添加数据失败' }; |
||||
|
let graphId = null; |
||||
|
try { |
||||
|
const data = ctx.request.body; |
||||
|
let dataToSave = { |
||||
|
projectId: data.projectId, |
||||
|
graph: data.graph, |
||||
|
} |
||||
|
const t = await ctx.fs.dc.orm.transaction(); |
||||
|
try { |
||||
|
let planarGraph = await ctx.fs.dc.models.ProjectGraph.create(dataToSave); |
||||
|
graphId = planarGraph.id; |
||||
|
await t.commit(); |
||||
|
} catch (e) { |
||||
|
await t.rollback(); |
||||
|
throw e; |
||||
|
} |
||||
|
error = null; |
||||
|
// 日志信息
|
||||
|
ctx.fs.api = ctx.fs.api || {}; |
||||
|
ctx.fs.api.actionParameter = JSON.stringify(data); |
||||
|
ctx.fs.api.actionParameterShow = `新增graphId:${graphId}`; |
||||
|
} catch (err) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${err}`); |
||||
|
} |
||||
|
if (error) { |
||||
|
ctx.status = 400; |
||||
|
ctx.body = error; |
||||
|
} else { |
||||
|
ctx.status = 200; |
||||
|
ctx.body = { id: graphId }; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async function updateGraph(ctx, next) { |
||||
|
let error = { name: 'UpdateError', message: '修改数据失败' }; |
||||
|
const { id } = ctx.params; |
||||
|
const data = ctx.request.body; |
||||
|
if (id) { |
||||
|
if (data && Object.keys(data).length) { |
||||
|
try { |
||||
|
const models = ctx.fs.dc.models; |
||||
|
let planarGraph = await models.ProjectGraph.findOne({ where: { id: id } }); |
||||
|
const dataToSave = {}; |
||||
|
if (planarGraph) { |
||||
|
const { projectId, graph } = data; |
||||
|
if (projectId && !(projectId == planarGraph.projectId)) |
||||
|
dataToSave.projectId = projectId; |
||||
|
if (graph && !(graph == planarGraph.graph)) |
||||
|
dataToSave.graph = graph; |
||||
|
} |
||||
|
dataToSave.id = planarGraph.id; |
||||
|
if (Object.keys(dataToSave).length) { |
||||
|
await models.ProjectGraph.update(dataToSave, { where: { id: planarGraph.id } }); |
||||
|
} |
||||
|
error = null; |
||||
|
// 日志信息
|
||||
|
ctx.fs.api = ctx.fs.api || {}; |
||||
|
ctx.fs.api.actionParameter = JSON.stringify(data); |
||||
|
ctx.fs.api.actionParameterShow = `结构物平面图id:${data.id}`; |
||||
|
} catch (err) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${err}`); |
||||
|
} |
||||
|
} |
||||
|
} else { |
||||
|
error = { name: 'UpdateError', message: `不存在{id=${id}}的结构物平面图` }; |
||||
|
} |
||||
|
if (error) { |
||||
|
ctx.status = 400; |
||||
|
ctx.body = error; |
||||
|
} else { |
||||
|
ctx.status = 200; |
||||
|
ctx.body = { message: "结构物平面图修改成功" }; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async function delProjectGraph(ctx) { |
||||
|
try { |
||||
|
const { id } = ctx.params; |
||||
|
const models = ctx.fs.dc.models; |
||||
|
let info = await models.ProjectGraph.findOne({ where: { id: id } }); |
||||
|
if (info) { |
||||
|
await models.ProjectPointsDeploy.destroy({ where: { graphId: id } }); |
||||
|
await models.ProjectGraph.destroy({ where: { id } }) |
||||
|
ctx.status = 204; |
||||
|
} else { |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { message: '数据不存在' } |
||||
|
} |
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
"message": "删除结构物布设图失败" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async function getDeployPoints(ctx) { |
||||
|
try { |
||||
|
const pictureId = ctx.params.pictureId; |
||||
|
const models = ctx.fs.dc.models; |
||||
|
const heatmap = await models.ProjectGraph.findOne({ where: { id: pictureId } }) |
||||
|
if (heatmap) { |
||||
|
let allPoints = await models.Point.findAll({ |
||||
|
attributes: ['id', 'name'], |
||||
|
where: { projectId: heatmap.dataValues.projectId } |
||||
|
}) |
||||
|
let setedPoints = await models.ProjectPointsDeploy.findAll({ |
||||
|
where: { graphId: pictureId } |
||||
|
}) |
||||
|
ctx.status = 200; |
||||
|
ctx.body = { |
||||
|
allPoints, |
||||
|
setedPoints |
||||
|
}; |
||||
|
} else { |
||||
|
throw new Error('pictureId not found'); |
||||
|
} |
||||
|
} catch (err) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${err}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
name: 'FindError', |
||||
|
message: '获取结构物平面图测点布设失败' |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async function setDeployPoints(ctx) { |
||||
|
const pictureId = ctx.params.pictureId; |
||||
|
const req = ctx.request.body; |
||||
|
const models = ctx.fs.dc.models; |
||||
|
const orm = ctx.fs.dc.orm; |
||||
|
|
||||
|
try { |
||||
|
ctx.fs.api = ctx.fs.api || {}; |
||||
|
ctx.fs.api.actionParameter = req; |
||||
|
ctx.fs.api.actionParameterShow = '结构物平面图测点部署: ' + JSON.stringify(req); |
||||
|
|
||||
|
const t = await orm.transaction(); |
||||
|
|
||||
|
try { |
||||
|
await models.ProjectPointsDeploy.destroy({ where: { graphId: pictureId }, transaction: t }); |
||||
|
|
||||
|
const layout = req.spots.map((hotspot, index) => { |
||||
|
let msg = { |
||||
|
graphId: pictureId, |
||||
|
pointId: hotspot.pointId, |
||||
|
position: JSON.stringify(hotspot.position) |
||||
|
} |
||||
|
return msg; |
||||
|
}); |
||||
|
|
||||
|
await models.ProjectPointsDeploy.bulkCreate(layout, { transaction: t }); |
||||
|
|
||||
|
await t.commit(); |
||||
|
} catch (e) { |
||||
|
await t.rollback(); |
||||
|
throw e; |
||||
|
} |
||||
|
ctx.status = 200; |
||||
|
ctx.body = { |
||||
|
name: "CreateSuccess", |
||||
|
message: "结构物平面图测点部署成功" |
||||
|
}; |
||||
|
|
||||
|
} catch (err) { |
||||
|
ctx.fs.logger.error(err); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
name: 'CreateError', |
||||
|
message: "结构物平面图测点部署失败" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
module.exports = { |
||||
|
findSingleGraph, |
||||
|
createGraph, |
||||
|
updateGraph, |
||||
|
delProjectGraph, |
||||
|
getDeployPoints, |
||||
|
setDeployPoints |
||||
|
}; |
@ -0,0 +1,44 @@ |
|||||
|
/* eslint-disable*/ |
||||
|
|
||||
|
'use strict'; |
||||
|
|
||||
|
module.exports = dc => { |
||||
|
const DataTypes = dc.ORM; |
||||
|
const sequelize = dc.orm; |
||||
|
const ProjectGraph = sequelize.define("projectGraph", { |
||||
|
id: { |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: true, |
||||
|
field: "id", |
||||
|
autoIncrement: true, |
||||
|
unique: "project_graph_id_uindex" |
||||
|
}, |
||||
|
projectId: { |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "project_id", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
graph: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "graph", |
||||
|
autoIncrement: false |
||||
|
} |
||||
|
}, { |
||||
|
tableName: "project_graph", |
||||
|
comment: "", |
||||
|
indexes: [] |
||||
|
}); |
||||
|
dc.models.ProjectGraph = ProjectGraph; |
||||
|
return ProjectGraph; |
||||
|
}; |
@ -0,0 +1,53 @@ |
|||||
|
/* eslint-disable*/ |
||||
|
|
||||
|
'use strict'; |
||||
|
|
||||
|
module.exports = dc => { |
||||
|
const DataTypes = dc.ORM; |
||||
|
const sequelize = dc.orm; |
||||
|
const ProjectPointsDeploy = sequelize.define("projectPointsDeploy", { |
||||
|
id: { |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: true, |
||||
|
field: "id", |
||||
|
autoIncrement: true, |
||||
|
unique: "project_points_deploy_id_uindex" |
||||
|
}, |
||||
|
pointId: { |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "point_id", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
graphId: { |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "graph_id", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
position: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "position", |
||||
|
autoIncrement: false |
||||
|
} |
||||
|
}, { |
||||
|
tableName: "project_points_deploy", |
||||
|
comment: "", |
||||
|
indexes: [] |
||||
|
}); |
||||
|
dc.models.ProjectPointsDeploy = ProjectPointsDeploy; |
||||
|
return ProjectPointsDeploy; |
||||
|
}; |
@ -0,0 +1,23 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
const pointDeploy = require('../../controllers/pointDeploy'); |
||||
|
|
||||
|
module.exports = function (app, router, opts) { |
||||
|
app.fs.api.logAttr['GET/project/:projectId/planarGraph'] = { content: '获取结构物平面图数据', visible: false }; |
||||
|
router.get('/project/:projectId/planarGraph', pointDeploy.findSingleGraph); |
||||
|
|
||||
|
app.fs.api.logAttr['POST/planarGraph/add'] = { content: '新增结构物平面图', visible: true }; |
||||
|
router.post('/planarGraph/add', pointDeploy.createGraph); |
||||
|
|
||||
|
app.fs.api.logAttr['PUT/planarGraph/:id/modify'] = { content: '修改结构物平面图', visible: true }; |
||||
|
router.post('/planarGraph/:id/modify', pointDeploy.updateGraph); |
||||
|
|
||||
|
app.fs.api.logAttr['DEL/project/graph/:id'] = { content: '删除结构物布设图', visible: false }; |
||||
|
router.del('/project/graph/:id', pointDeploy.delProjectGraph); |
||||
|
|
||||
|
app.fs.api.logAttr['GET/picture/:pictureId/deploy/points'] = { content: '获取点位布设信息', visible: false }; |
||||
|
router.get('/picture/:pictureId/deploy/points', pointDeploy.getDeployPoints); |
||||
|
|
||||
|
app.fs.api.logAttr['POST/set/picture/:pictureId/deploy/points'] = { content: '点位布设', visible: true }; |
||||
|
router.post('/set/picture/:pictureId/deploy/points', pointDeploy.setDeployPoints); |
||||
|
}; |
@ -0,0 +1,33 @@ |
|||||
|
/*结构物布设图表*/ |
||||
|
create table project_graph |
||||
|
( |
||||
|
id serial not null, |
||||
|
project_id int not null, |
||||
|
graph varchar(255) not null |
||||
|
); |
||||
|
|
||||
|
create unique index project_graph_id_uindex |
||||
|
on project_graph (id); |
||||
|
|
||||
|
alter table project_graph |
||||
|
add constraint project_graph_pk |
||||
|
primary key (id); |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
/*点位布设表*/ |
||||
|
create table project_points_deploy |
||||
|
( |
||||
|
id serial not null, |
||||
|
point_id int not null, |
||||
|
graph_id int not null, |
||||
|
position varchar(1000) not null |
||||
|
); |
||||
|
|
||||
|
create unique index project_points_deploy_id_uindex |
||||
|
on project_points_deploy (id); |
||||
|
|
||||
|
alter table project_points_deploy |
||||
|
add constraint project_points_deploy_pk |
||||
|
primary key (id); |
@ -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: '结构物平面图点位布设' }, |
||||
|
}); |
||||
|
} |
@ -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 => <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); |
||||
|
|
@ -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 ( |
||||
|
<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)); |
@ -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; |
||||
|
} |
@ -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: <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.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 = <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 => { |
||||
|
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 (<div className='patrolLayout'> |
||||
|
<Layout> |
||||
|
<Sider width={230} style={{ background: 'transparent', height: 400 }}> |
||||
|
<div className='search-panel'> |
||||
|
<Button className={deployState == -1 ? 'btn-spots-filter' : 'btn-default'} style={{ borderRadius: 0 }} onClick={() => this.handleStateChange(-1)}>全部</Button> |
||||
|
<Button className={deployState == 1 ? 'btn-spots-filter' : 'btn-default'} style={{ borderRadius: 0 }} onClick={() => this.handleStateChange(1)}>已布</Button> |
||||
|
<Button className={deployState == 0 ? 'btn-spots-filter' : 'btn-default'} style={{ borderRadius: 0 }} onClick={() => this.handleStateChange(0)}>未布</Button> |
||||
|
<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: 600 }}> |
||||
|
<Tree className='equip-tree' showLine defaultExpandAll={true}> |
||||
|
{this.loop(treeDataSource)} |
||||
|
</Tree> </div> : <div style={{ textAlign: 'center' }}>暂无点位</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: clientHeight * 0.4, textAlign: 'center' }}> |
||||
|
暂无热点图 |
||||
|
</div> |
||||
|
} |
||||
|
<div className='opr-tip-row'> |
||||
|
<div>说明:拖拽点位进行布设,拖出画布移除点位。</div> |
||||
|
{ |
||||
|
pictureInfo ? |
||||
|
<div className='opr-button'> |
||||
|
<Popconfirm |
||||
|
title='确认删除该结构物布设图?(已布点位将同步删除)' |
||||
|
position='top' |
||||
|
onConfirm={() => { |
||||
|
this.props.dispatch(deleteGraph(pictureInfo.id)).then(_ => { |
||||
|
this.getData(); |
||||
|
}) |
||||
|
}}> |
||||
|
<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 } = state; |
||||
|
return { |
||||
|
pictureInfo: projectGraph.data, |
||||
|
projectDeployPoints: projectDeployPoints.data, |
||||
|
clientHeight: global.clientHeight, |
||||
|
clientWidth: global.clientWidth |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
export default connect(mapStateToProps)(DragDropContext(HTML5Backend)(ConfigPlanarGraph)); |
@ -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; |
||||
|
} |
||||
|
} |
@ -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 ( |
||||
|
<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); |
Loading…
Reference in new issue