diff --git a/api/app/lib/controllers/organization/user.js b/api/app/lib/controllers/organization/user.js index 14e0577..66c1c2b 100644 --- a/api/app/lib/controllers/organization/user.js +++ b/api/app/lib/controllers/organization/user.js @@ -172,7 +172,7 @@ async function getUser (ctx, next) { const models = ctx.fs.dc.models; const { depId } = ctx.params; let userRes = null; - if (depId !== 'null') { + if (depId !== 'undefined') { userRes = await models.User.findAll({ where: { departmentId: parseInt(depId), diff --git a/api/app/lib/controllers/patrolManage/yujingguanli.js b/api/app/lib/controllers/patrolManage/yujingguanli.js new file mode 100644 index 0000000..2b39b8b --- /dev/null +++ b/api/app/lib/controllers/patrolManage/yujingguanli.js @@ -0,0 +1,64 @@ +'use strict'; +async function varfiyCode(ctx) { + try { + const { models } = ctx.fs.dc; + const { pushBySms, pushByEmail } = ctx.app.fs.utils + const { phone, type ,email} = ctx.request.body + + // 伪造的请求可能由相同的sig参数组成 + // const checkSigUsed = await models.PhoneValidateCode.findOne({ + // where: { sig: sig } + // }); + // if (checkSigUsed) { + // throw '参数错误!' + // } + + // // 验证sig正确性 + // const checkSig = Hex.stringify(SHA1(phone + r)); + // if (!r || !sig || sig != checkSig) { + // throw '参数错误!' + // } + + let varifyCode = '' + for (let i = 0; i < 6; i++) { + varifyCode += Math.floor(Math.random() * 10) + } + + if(type.includes(1)){ + await pushBySms({ + phone: phone, + templateCode: 'SMS_261950020', + templateParam: { + code: varifyCode + }, + }) + } + if(type.includes(2)){ + await pushByEmail({ + email: email, + title: '测试', + text:'你知道吗' + }) + } + + // await models.PhoneValidateCode.create({ + // phone: phone, + // code: varifyCode, + // sig: sig, + // expired: moment().add(10, 'minutes').format('YYYY-MM-DD HH:mm:ss') + // }) + + ctx.status = 204; + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { + message: typeof error == 'string' ? error : '获取验证码失败' + } + } +} + + module.exports = { + varfiyCode, + // pushByEmail +} \ No newline at end of file diff --git a/api/app/lib/controllers/pointDeploy/index.js b/api/app/lib/controllers/pointDeploy/index.js new file mode 100644 index 0000000..49b6fec --- /dev/null +++ b/api/app/lib/controllers/pointDeploy/index.js @@ -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 +}; \ No newline at end of file diff --git a/api/app/lib/models/project_graph.js b/api/app/lib/models/project_graph.js new file mode 100644 index 0000000..8948a59 --- /dev/null +++ b/api/app/lib/models/project_graph.js @@ -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; +}; \ No newline at end of file diff --git a/api/app/lib/models/project_points_deploy.js b/api/app/lib/models/project_points_deploy.js new file mode 100644 index 0000000..a0e7f6e --- /dev/null +++ b/api/app/lib/models/project_points_deploy.js @@ -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; +}; \ No newline at end of file diff --git a/api/app/lib/routes/patrolManage/yujingguanli.js b/api/app/lib/routes/patrolManage/yujingguanli.js new file mode 100644 index 0000000..b968474 --- /dev/null +++ b/api/app/lib/routes/patrolManage/yujingguanli.js @@ -0,0 +1,11 @@ +'use strict'; + +const yujingguanli = require('../../controllers/patrolManage/yujingguanli'); + +module.exports = function (app, router, opts) { + + + app.fs.api.logAttr['POST/yujingguanli'] = { content: '下发预警邮件', visible: true }; + router.post('/yujingguanli', yujingguanli.varfiyCode); + +}; \ No newline at end of file diff --git a/api/app/lib/routes/pointDeploy/index.js b/api/app/lib/routes/pointDeploy/index.js new file mode 100644 index 0000000..87d06a6 --- /dev/null +++ b/api/app/lib/routes/pointDeploy/index.js @@ -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); +}; \ No newline at end of file diff --git a/api/config.js b/api/config.js index b752ec8..3aa9876 100644 --- a/api/config.js +++ b/api/config.js @@ -94,7 +94,7 @@ const product = { host: 'smtp.exmail.qq.com', port: 465, sender: { - name: '中鼎服务', + name: '运维服务', address: 'fsiot@free-sun.com.cn', password: 'Fs2689' } diff --git a/script/1.0.4/schema/4.updata_patrol_record_issue__handle.sql b/script/1.0.4/schema/4.updata_patrol_record_issue__handle.sql index d5ac8f5..e10d398 100644 --- a/script/1.0.4/schema/4.updata_patrol_record_issue__handle.sql +++ b/script/1.0.4/schema/4.updata_patrol_record_issue__handle.sql @@ -1,4 +1,5 @@ ALTER TABLE patrol_record_issue_handle ADD yanshoushijian timestamp(6); ALTER TABLE patrol_record_issue_handle ADD yanshoucishu integer; ALTER TABLE patrol_record_issue_handle ADD yujingshijian timestamp(6); +ALTER TABLE patrol_record_issue_handle ADD yujingafchishu integer; ALTER TABLE patrol_record_issue_handle ADD isgaojing bool; diff --git a/script/1.0.5/schema/4.project_graph_point_deploy.sql b/script/1.0.5/schema/4.project_graph_point_deploy.sql new file mode 100644 index 0000000..9e819d3 --- /dev/null +++ b/script/1.0.5/schema/4.project_graph_point_deploy.sql @@ -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); \ No newline at end of file diff --git a/web/client/src/app.js b/web/client/src/app.js index e737fac..1541740 100644 --- a/web/client/src/app.js +++ b/web/client/src/app.js @@ -8,6 +8,7 @@ import ProjectRegime from './sections/projectRegime'; import Organization from './sections/organization'; import PatrolManage from './sections/patrolManage'; import IssueHandle from './sections/issueHandle' +import Shouye from './sections/shouye'; import { Func } from '$utils'; const App = props => { const { projectName } = props @@ -19,7 +20,7 @@ const App = props => { return ( ) diff --git a/web/client/src/sections/auth/containers/login.js b/web/client/src/sections/auth/containers/login.js index 5ca98ad..0fbb02b 100644 --- a/web/client/src/sections/auth/containers/login.js +++ b/web/client/src/sections/auth/containers/login.js @@ -31,6 +31,7 @@ const Login = props => { const [form] = Form.useForm(); const tourl = () => { + return '/shouye' if (Func.isAuthorized("STRU_INFO_CONFIG")) { return '/projectRegime/information' } diff --git a/web/client/src/sections/patrolManage/actions/index.js b/web/client/src/sections/patrolManage/actions/index.js index ad713eb..690f08c 100644 --- a/web/client/src/sections/patrolManage/actions/index.js +++ b/web/client/src/sections/patrolManage/actions/index.js @@ -5,6 +5,7 @@ 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' export default { ...plan, @@ -12,4 +13,5 @@ export default { ...report, ...template, ...checkItems, + ...yujingguanli } \ No newline at end of file diff --git a/web/client/src/sections/patrolManage/actions/yujingguanli.js b/web/client/src/sections/patrolManage/actions/yujingguanli.js new file mode 100644 index 0000000..2ed6a3f --- /dev/null +++ b/web/client/src/sections/patrolManage/actions/yujingguanli.js @@ -0,0 +1,13 @@ +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: '发送信息' }, + }); +} \ No newline at end of file diff --git a/web/client/src/sections/patrolManage/components/xiafagaojin.js b/web/client/src/sections/patrolManage/components/xiafagaojin.js index 1d4b1cd..f9a177c 100644 --- a/web/client/src/sections/patrolManage/components/xiafagaojin.js +++ b/web/client/src/sections/patrolManage/components/xiafagaojin.js @@ -2,15 +2,17 @@ import { Button, Form, Input, Modal, Select, DatePicker,Checkbox } from 'antd'; import React, { useState, useEffect } from 'react'; import { connect } from 'react-redux'; import { createPatrolTemplate, delPatrolTemplate, updatePatrolTemplate, getPatrolTemplate } from '../actions/template'; +import {putxinxi} from '../actions/yujingguanli' import moment from 'moment'; const { RangePicker } = DatePicker; const { TextArea } = Input; -const PlanModal = ({ visible, onCancel, dispatch, type, curRecord, tableRef, checkItemsGroup }) => { +const PlanModal = ({ visible, onCancel, dispatch, type, curRecord, tableRef, checkItemsGroup,userlist }) => { const [form] = Form.useForm(); const shigutypes = [{value:1,label: '邮件告警'}, {value:2,label:'短信告警'}] + console.log(userlist,'userlist') return ( { - 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(); - } - }) - } + 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})).then(res=>{ + console.log(res,'res') + }) + console.log(params,'params') }) .catch((info) => { console.log('Validate Failed:', info); @@ -60,22 +47,20 @@ const PlanModal = ({ visible, onCancel, dispatch, type, curRecord, tableRef, che form={form} // layout="vertical" name="form_in_modal" - initialValues={{ - ...curRecord, - checkItems: curRecord?.checkItems?.map(c => c.id) - }} - labelCol={{ span: 5 }} wrapperCol={{ span: 19 }} offe + + labelCol={{ span: 5 }} wrapperCol={{ span: 19 }} > - + - + diff --git a/web/client/src/sections/patrolManage/containers/yujingguanli.js b/web/client/src/sections/patrolManage/containers/yujingguanli.js index 97e9774..8abfafd 100644 --- a/web/client/src/sections/patrolManage/containers/yujingguanli.js +++ b/web/client/src/sections/patrolManage/containers/yujingguanli.js @@ -3,11 +3,12 @@ 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 } = props; + const { dispatch, user,actions,depUser} = props; const tableRef = useRef(); const format = 'YYYY-MM-DD HH:mm:ss' const { patrolManage } = actions @@ -35,29 +36,30 @@ function YujingGuanli (props) { if (res.success) { console.log(res,'水平') let obj = {} - 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 + // 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 } + // // }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(obj,'obj') + // }) } }) } + console.log(depUser,'depUser') useEffect(() => { // dispatch(patrolManage.records(`patrolRecord/all/null/null/true/null`)).then(res=>{ // let obj = {} @@ -81,7 +83,7 @@ function YujingGuanli (props) { // console.log(obj,'obj') // console.log(res,'res') // }) - + dispatch(getDepUser()) queryData() dispatch(getCheckItemsGroup()) }, []) @@ -187,11 +189,12 @@ console.log(tableList,'tablist') ]} /> { - visible ? + visible &&depUser.filter(i=>i.username&&i.email).length!==0 ? i.username&&i.email)} onCancel={() => { setVisible(false); setCurRecord({}) @@ -204,10 +207,11 @@ console.log(tableList,'tablist') } function mapStateToProps (state) { - const { auth, global } = state + const { auth, global ,depUser} = state return { user: auth.user, actions: global.actions, + depUser: depUser.data || [], } } export default connect(mapStateToProps)(YujingGuanli); diff --git a/web/client/src/sections/patrolManage/nav-item.js b/web/client/src/sections/patrolManage/nav-item.js index 69580d9..8dc3592 100644 --- a/web/client/src/sections/patrolManage/nav-item.js +++ b/web/client/src/sections/patrolManage/nav-item.js @@ -26,9 +26,9 @@ export function getNavItem (user, dispatch) { {Func.isAuthorized('CHECKMOULD') && 巡检模板 } - {/* { + { 预警管理 - } */} + } ); } \ No newline at end of file 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/components/pointModel.js b/web/client/src/sections/projectRegime/components/pointModel.js index ade7c55..da2aa37 100644 --- a/web/client/src/sections/projectRegime/components/pointModel.js +++ b/web/client/src/sections/projectRegime/components/pointModel.js @@ -164,14 +164,14 @@ const ProjectAddModel = ({ dispatch, actions, user, modelData, close, success, q rules={[{ required: true, message: '请输入描述内容', },]}>