diff --git a/api/app/lib/controllers/organization/user.js b/api/app/lib/controllers/organization/user.js index aa7e2e9..8aaf88b 100644 --- a/api/app/lib/controllers/organization/user.js +++ b/api/app/lib/controllers/organization/user.js @@ -170,15 +170,31 @@ async function delDept(ctx, next) { async function getUser(ctx, next) { try { const models = ctx.fs.dc.models; - const { depId } = ctx.params - const userRes = await models.User.findAll({ - where: { - departmentId: parseInt(depId), - delete: false - }, - attributes: { exclude: ['password'] }, - order: [['id', 'asc']], - }) + const { depId } = ctx.params; + let userRes = null; + if (depId !== 'null') { + userRes = await models.User.findAll({ + where: { + departmentId: parseInt(depId), + delete: false + }, + attributes: { exclude: ['password'] }, + order: [['id', 'asc']], + }) + } else { + userRes = await models.User.findAll({ + where: { + delete: false + }, + attributes: { exclude: ['password'] }, + order: [['id', 'asc']], + include: [{ + required: true, + model: models.Department, + attributes: ['id', 'name'], + }] + }) + } ctx.status = 200; ctx.body = userRes diff --git a/api/app/lib/controllers/patrolPlan/patrolPlan.js b/api/app/lib/controllers/patrolPlan/patrolPlan.js new file mode 100644 index 0000000..6de5a45 --- /dev/null +++ b/api/app/lib/controllers/patrolPlan/patrolPlan.js @@ -0,0 +1,113 @@ +'use strict'; + +async function getPatrolPlan(ctx, next) { + try { + const models = ctx.fs.dc.models; + const { limit, page } = ctx.query; + let options = { + include: [{ + required: true, + model: models.User, + attributes: ['id', 'name'], + include: [{ + required: true, + model: models.Department, + attributes: ['id', 'name'], + }] + }, { + required: true, + model: models.Project, + attributes: ['id', 'name'], + }] + }; + if (limit) { + options.limit = Number(limit); + } + if (page && limit) { + options.offset = Number(page) * Number(limit); + } + let res = await models.PatrolPlan.findAndCountAll(options); + ctx.status = 200; + ctx.body = res; + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { + "message": "获取巡检计划失败" + } + } +} + +async function createPatrolPlan(ctx, next) { + try { + const models = ctx.fs.dc.models; + const data = ctx.request.body; + const { name, way, structureId, startTime, endTime, frequency, points, userId } = data; + + let plan = { name, way, structureId, startTime, endTime, frequency, points, userId }; + + await models.PatrolPlan.create(plan); + + ctx.status = 204; + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { + "message": '新增巡检计划失败' + } + } +} + +async function updatePatrolPlan(ctx, next) { + try { + let errMsg = '修改巡检计划失败'; + const models = ctx.fs.dc.models; + const data = ctx.request.body; + const { name, startTime, endTime, frequency, patrolPerson } = data; + + let plan = { name, startTime, endTime, frequency, patrolPerson }; + + if (data && data.id) { + await models.PatrolPlan.update(plan, { + where: { id: data.id } + }) + } else { + errMsg = '请传入巡检计划id'; + throw errMsg; + } + + ctx.status = 204; + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { + "message": errMsg + } + } +} + +async function delPatrolPlan(ctx, next) { + try { + const models = ctx.fs.dc.models; + const { id } = ctx.params; + + await models.PatrolPlan.destroy({ + where: { id } + }) + + ctx.status = 204; + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { + "message": '删除巡检计划失败' + } + } +} + +module.exports = { + getPatrolPlan, + createPatrolPlan, + updatePatrolPlan, + delPatrolPlan, +} \ No newline at end of file diff --git a/api/app/lib/index.js b/api/app/lib/index.js index 2cc3d93..5cb7374 100644 --- a/api/app/lib/index.js +++ b/api/app/lib/index.js @@ -53,8 +53,7 @@ module.exports.models = function (dc) { // dc = { orm: Sequelize对象, ORM: Seq require(`./models/${filename}`)(dc) }); - const { Camera, Company, Department, Post, RoleGroup, Role, RoleResource, User, UserDepartment, UserPost, Site, ProjectDisclosure, ProjectDisclosureFiles, Coordinate, ProblemReport, ProblemReportFile, Worker, WorkerAttendance, - RiskReport, Metting, HideDangerRectify, HideDangerRectifySites, HideDangerDispose, UserResource, Resource, Project, Point + const { Department, User, UserResource, Resource, Project, Point, PatrolPlan } = dc.models; UserResource.belongsTo(User, { foreignKey: 'userId', targetKey: 'id' }); @@ -69,4 +68,10 @@ module.exports.models = function (dc) { // dc = { orm: Sequelize对象, ORM: Seq Point.belongsTo(Project, { foreignKey: 'projectId', targetKey: 'id' }); Project.hasMany(Point, { foreignKey: 'projectId', sourceKey: 'id' }); + + PatrolPlan.belongsTo(Project, { foreignKey: 'structureId', targetKey: 'id' }); + Project.hasMany(PatrolPlan, { foreignKey: 'structureId', sourceKey: 'id' }); + + PatrolPlan.belongsTo(User, { foreignKey: 'userId', targetKey: 'id' }); + User.hasMany(PatrolPlan, { foreignKey: 'userId', sourceKey: 'id' }); }; diff --git a/api/app/lib/models/patrol_plan.js b/api/app/lib/models/patrol_plan.js new file mode 100644 index 0000000..91e5ddd --- /dev/null +++ b/api/app/lib/models/patrol_plan.js @@ -0,0 +1,105 @@ +/* eslint-disable*/ +'use strict'; + +module.exports = dc => { + const DataTypes = dc.ORM; + const sequelize = dc.orm; + const PatrolPlan = sequelize.define("PatrolPlan", { + id: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: null, + comment: null, + primaryKey: true, + field: "id", + autoIncrement: true, + unique: "patrol_plan_id_uindex" + }, + name: { + type: DataTypes.STRING, + allowNull: false, + defaultValue: null, + comment: null, + primaryKey: false, + field: "name", + autoIncrement: false + }, + way: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: null, + primaryKey: false, + field: "way", + autoIncrement: false + }, + structureId: { + type: DataTypes.INTEGER, + allowNull: true, + defaultValue: null, + comment: null, + primaryKey: false, + field: "structure_id", + autoIncrement: false + }, + startTime: { + type: DataTypes.DATE, + allowNull: true, + defaultValue: null, + comment: null, + primaryKey: false, + field: "start_time", + autoIncrement: false + }, + endTime: { + type: DataTypes.DATE, + allowNull: true, + defaultValue: null, + comment: null, + primaryKey: false, + field: "end_time", + autoIncrement: false + }, + frequency: { + type: DataTypes.STRING, + allowNull: true, + defaultValue: null, + comment: null, + primaryKey: false, + field: "frequency", + autoIncrement: false + }, + points: { + type: DataTypes.JSONB, + allowNull: true, + defaultValue: null, + comment: null, + primaryKey: false, + field: "points", + autoIncrement: false + }, + userId: { + type: DataTypes.INTEGER, + allowNull: true, + comment: null, + primaryKey: false, + field: "user_id", + autoIncrement: false, + }, + patrolCount: { + type: DataTypes.INTEGER, + allowNull: false, + defaultValue: 0, + comment: null, + primaryKey: false, + field: "patrol_count", + autoIncrement: false + }, + }, { + tableName: "patrol_plan", + comment: "", + indexes: [] + }); + dc.models.PatrolPlan = PatrolPlan; + return PatrolPlan; +}; \ No newline at end of file diff --git a/api/app/lib/routes/patrolPlan/patrolPlan.js b/api/app/lib/routes/patrolPlan/patrolPlan.js new file mode 100644 index 0000000..5f0e455 --- /dev/null +++ b/api/app/lib/routes/patrolPlan/patrolPlan.js @@ -0,0 +1,17 @@ +'use strict'; + +const patrolPlan = require('../../controllers/patrolPlan/patrolPlan'); + +module.exports = function (app, router, opts) { + app.fs.api.logAttr['GET/patrolPlan'] = { content: '获取巡检计划', visible: false }; + router.get('/patrolPlan', patrolPlan.getPatrolPlan); + + app.fs.api.logAttr['POST/patrolPlan'] = { content: '新增巡检计划', visible: true }; + router.post('/patrolPlan', patrolPlan.createPatrolPlan); + + app.fs.api.logAttr['PUT/patrolPlan'] = { content: '修改巡检计划', visible: true }; + router.put('/patrolPlan', patrolPlan.updatePatrolPlan); + + app.fs.api.logAttr['DELETE/patrolPlan/:id'] = { content: '删除巡检计划', visible: true }; + router.del('/patrolPlan/:id', patrolPlan.delPatrolPlan); +}; \ No newline at end of file diff --git a/web/client/src/sections/patrolManage/actions/plan.js b/web/client/src/sections/patrolManage/actions/plan.js index cf3d5f8..6b94bca 100644 --- a/web/client/src/sections/patrolManage/actions/plan.js +++ b/web/client/src/sections/patrolManage/actions/plan.js @@ -43,4 +43,38 @@ export function updatePatrolPlan(data) { url: ApiTable.patrolPlan, msg: { error: '修改巡检计划失败' }, }); +} + +export function getUserList() { + return dispatch => basicAction({ + type: 'get', + dispatch: dispatch, + actionType: 'GET_USER_LIST', + url: ApiTable.getDepUser.replace('{depId}', null), + msg: { error: '获取人员列表失败' }, + reducer: { name: 'userList' } + }); +} + +export function getProjectList(query) { + return (dispatch) => basicAction({ + type: 'get', + query, + dispatch, + actionType: 'GET_PROJEECT_LIST', + url: ApiTable.getProjectList, + msg: { error: '获取结构物列表失败', }, + reducer: { name: 'structureList' } + }); +} + +export function positionList(query) { + return (dispatch) => basicAction({ + type: 'get', + query, + dispatch, + actionType: 'POSITION_LIST', + url: ApiTable.position, + msg: { error: '获取点位列表失败', }, + }); } \ No newline at end of file diff --git a/web/client/src/sections/patrolManage/components/planModal.js b/web/client/src/sections/patrolManage/components/planModal.js new file mode 100644 index 0000000..6cf9e39 --- /dev/null +++ b/web/client/src/sections/patrolManage/components/planModal.js @@ -0,0 +1,177 @@ +import { Button, Form, Input, Modal, Select, DatePicker } from 'antd'; +import React, { useState, useEffect } from 'react'; +import { connect } from 'react-redux'; +import { getUserList, getProjectList, positionList } from '../actions/plan'; + +const { RangePicker } = DatePicker; + +const PlanModal = ({ visible, onCreate, onCancel, dispatch, userLoading, userList, structureList, struLoading }) => { + const [userOpt, setUserOpt] = useState(); + const [struOpt, setStruOpt] = useState(); + const [pointOpt, setPointOpt] = useState(); + const [unit, setUnit] = useState('次/天'); + const [form] = Form.useForm(); + + useEffect(() => { + dispatch(getUserList()) + dispatch(getProjectList()) + }, []) + + useEffect(() => { + if (userList.length) { + setUserOpt(userList.map(u => ({ label: u.name, value: u.id }))) + } + }, [userList]) + + useEffect(() => { + if (structureList?.rows?.length) { + setStruOpt(structureList?.rows?.map(s => ({ label: s.name, value: s.id }))) + } + }, [structureList]) + + const selectAfter = ( + + ); + return ( + { + form.resetFields(); + onCancel(); + }} + onOk={() => { + form + .validateFields() + .then((values) => { + form.resetFields(); + const params = { + frequency: values.frequency + unit, + startTime: values.time[0], + endTime: values.time[1], + points: pointOpt.filter(p => p.id == values.points), + ...values + } + onCreate(params); + }) + .catch((info) => { + console.log('Validate Failed:', info); + }); + }} + > +
+ + + + + + + + + + + { + const curUser = userList.filter(u => u.id == value) + if (curUser.length) { + form.setFieldsValue({ + userDept: curUser[0].department.name + }); + } + }} /> + + + + +
+
+ ); +}; + +function mapStateToProps(state) { + const { auth, userList, structureList } = state + return { + user: auth.user, + userList: userList.data || [], + structureList: structureList.data || [], + userLoading: userList.isRequesting, + struLoading: structureList.isRequesting + } +} +export default connect(mapStateToProps)(PlanModal); \ No newline at end of file diff --git a/web/client/src/sections/patrolManage/components/userModal.js b/web/client/src/sections/patrolManage/components/userModal.js deleted file mode 100644 index f527e73..0000000 --- a/web/client/src/sections/patrolManage/components/userModal.js +++ /dev/null @@ -1,72 +0,0 @@ -import { Button, Form, Input, Modal } from 'antd'; -import React, { useState } from 'react'; - -const UserModal = ({ visible, onCreate, onCancel }) => { - const [form] = Form.useForm(); - const reg_tel = /^1([358][0-9]|4[579]|66|7[0135678]|9[89])[0-9]{8}$/; - return ( - { - form.resetFields(); - onCancel(); - }} - onOk={() => { - form - .validateFields() - .then((values) => { - form.resetFields(); - onCreate(values); - }) - .catch((info) => { - console.log('Validate Failed:', info); - }); - }} - > -
- - - - - - - - - -
-
- ); -}; - -export default UserModal; \ No newline at end of file diff --git a/web/client/src/sections/patrolManage/containers/patrolPlan.js b/web/client/src/sections/patrolManage/containers/patrolPlan.js index 2c20320..45e5805 100644 --- a/web/client/src/sections/patrolManage/containers/patrolPlan.js +++ b/web/client/src/sections/patrolManage/containers/patrolPlan.js @@ -2,7 +2,7 @@ import React, { useState, useRef } from 'react'; import { connect } from 'react-redux'; import { Button, Popconfirm } from 'antd'; import ProTable from '@ant-design/pro-table'; -import UserModal from '../components/userModal'; +import PlanModal from '../components/planModal'; import { createPatrolPlan, delPatrolPlan, updatePatrolPlan, getPatrolPlan } from '../actions/plan'; function PatrolPlan(props) { @@ -13,12 +13,12 @@ function PatrolPlan(props) { const onCreate = (values) => { console.log(values, 'values') - // dispatch(createEarthquakeUser(values)).then(res => { - // if (res.success) { - // tableRef.current.reload(); - // } - // }) - // setVisible(false); + dispatch(createPatrolPlan(values)).then(res => { + if (res.success) { + tableRef.current.reload(); + } + }) + setVisible(false); }; const columns = [{ @@ -98,7 +98,6 @@ function PatrolPlan(props) { search={false} request={async (params = {}) => { const res = await dispatch(getPatrolPlan(params)); - console.log(res, 'res') setDataSource(res?.payload.data?.rows); return { ...res }; }} @@ -111,13 +110,16 @@ function PatrolPlan(props) { >新增巡检计划 ]} /> - { - setVisible(false); - }} - /> + { + visible ? + { + setVisible(false); + }} + /> : null + } ) }