diff --git a/api/app/lib/controllers/report/index.js b/api/app/lib/controllers/report/index.js index 3ad56cf2..ba499024 100644 --- a/api/app/lib/controllers/report/index.js +++ b/api/app/lib/controllers/report/index.js @@ -3,22 +3,24 @@ const { QueryTypes } = require('sequelize'); const moment = require('moment'); const xlsxDownload = require('../../../../utils/xlsxDownload.js'); const fs = require('fs'); +const XLSX = require('xlsx') +const path = require('path') async function reportList (ctx) { - try { - const models = ctx.fs.dc.models; - const { limit, page, startTime, endTime, keyword, userId, reportType, isTop, asc, projectType, handleState = '', performerId = '', codeRoad } = ctx.query - const { userInfo } = ctx.fs.api - const sequelize = ctx.fs.dc.orm; - - let findUsers = [] - if ( - userInfo.loginSource == 'wx' - && userInfo.isAdmin - && userInfo.phone != 'SuperAdmin' - && (!performerId && !handleState) - ) { - // 是管理员但不是超管 查自己部门及下级部门的所有用户的信息 - const sqlStr = ` + try { + const models = ctx.fs.dc.models; + const { limit, page, startTime, endTime, keyword, userId, reportType, isTop, asc, projectType, handleState = '', performerId = '', codeRoad } = ctx.query + const { userInfo } = ctx.fs.api + const sequelize = ctx.fs.dc.orm; + + let findUsers = [] + if ( + userInfo.loginSource == 'wx' + && userInfo.isAdmin + && userInfo.phone != 'SuperAdmin' + && (!performerId && !handleState) + ) { + // 是管理员但不是超管 查自己部门及下级部门的所有用户的信息 + const sqlStr = ` WITH RECURSIVE sub_departments AS ( SELECT id, dependence FROM department @@ -34,295 +36,295 @@ async function reportList (ctx) { WHERE u.delete = false; ` - const res = await sequelize.query(sqlStr, { type: QueryTypes.SELECT }) - findUsers = res.map(item => { - return item.id - }) - findUsers.push(-1) - } - - let findOption = { - where: { - - }, - attributes: ['id', 'road', 'time', 'projectType', 'roadSectionStart', 'performerId', 'roadSectionEnd', 'reportType', 'address', - 'content', 'longitude', 'latitude', 'projectName', 'handleState', 'codeRoad', 'handleContent', 'handlePic', 'videoUrl', - 'scenePic'], - include: [{ - model: models.User, - attributes: ['name'] - }], - //order: [['time', asc ? 'ASC' : 'DESC']], - order: [['time', 'DESC']], - - } - if (limit) { - findOption.limit = limit - } - if (page && limit) { - findOption.offset = page * limit - } - if (startTime && endTime) { - findOption.where = { - time: { - '$between': [startTime, endTime] - } + const res = await sequelize.query(sqlStr, { type: QueryTypes.SELECT }) + findUsers = res.map(item => { + return item.id + }) + findUsers.push(-1) + } + + let findOption = { + where: { + + }, + attributes: ['id', 'road', 'time', 'projectType', 'roadSectionStart', 'performerId', 'roadSectionEnd', 'reportType', 'address', + 'content', 'longitude', 'latitude', 'projectName', 'handleState', 'codeRoad', 'handleContent', 'handlePic', 'videoUrl', + 'scenePic'], + include: [{ + model: models.User, + attributes: ['name'] + }], + //order: [['time', asc ? 'ASC' : 'DESC']], + order: [['time', 'DESC']], + + } + if (limit) { + findOption.limit = limit + } + if (page && limit) { + findOption.offset = page * limit + } + if (startTime && endTime) { + findOption.where = { + time: { + '$between': [startTime, endTime] } - } - if (keyword) { - if (reportType == 'road') { - findOption.where.projectName = { - '$like': `%${keyword}%` - } - } else { - findOption.where.road = { - '$like': `%${keyword}%` - } + } + } + if (keyword) { + if (reportType == 'road') { + findOption.where.projectName = { + '$like': `%${keyword}%` + } + } else { + findOption.where.road = { + '$like': `%${keyword}%` } - } - if (userId) { - findOption.where.userId = { $in: userId.split(',').map(Number) } - } - if (findUsers.length) { - findOption.where.userId = { $in: findUsers } - } - if (reportType) { - findOption.where.reportType = reportType - } - if (projectType) { - findOption.where.projectType = projectType - } - if (performerId) { - let performerIds = performerId.split(',') - findOption.where.performerId = { $in: performerIds } - } - if (handleState) { - let handleStates = handleState.split(',') - findOption.where.handleState = { $in: handleStates } - } - if (codeRoad) { - findOption.where.codeRoad = codeRoad - } - - let reportRes = null; - - if (isTop) { - const sqlStr = ` + } + } + if (userId) { + findOption.where.userId = { $in: userId.split(',').map(Number) } + } + if (findUsers.length) { + findOption.where.userId = { $in: findUsers } + } + if (reportType) { + findOption.where.reportType = reportType + } + if (projectType) { + findOption.where.projectType = projectType + } + if (performerId) { + let performerIds = performerId.split(',') + findOption.where.performerId = { $in: performerIds } + } + if (handleState) { + let handleStates = handleState.split(',') + findOption.where.handleState = { $in: handleStates } + } + if (codeRoad) { + findOption.where.codeRoad = codeRoad + } + + let reportRes = null; + + if (isTop) { + const sqlStr = ` select NR.*, "user".name as user_name from (SELECT R.*, "row_number"() OVER (PARTITION BY R.user_id ORDER BY R."time" DESC) AS NEWINDEX FROM report AS R ${reportType ? ` where report_type = '${reportType}' `: '' - } + } ) AS NR left join "user" on "user".id = NR.user_id WHERE NEWINDEX = 1 order by id desc; ` - reportRes = await sequelize.query(sqlStr, { type: QueryTypes.SELECT }); - if (reportType == 'road') { - const projectNameArr = reportRes.map(item => item.project_name).filter(item => item) - const projectRes = projectNameArr.length ? await models.Project.findAll({ - where: { - entryName: { $in: projectNameArr } - } - }) : [] - for (let r of reportRes) { - let corProject = projectRes.find(item => item.entryName == r.project_name) - if (corProject) { - r.project = corProject.dataValues - } - } + reportRes = await sequelize.query(sqlStr, { type: QueryTypes.SELECT }); + if (reportType == 'road') { + const projectNameArr = reportRes.map(item => item.project_name).filter(item => item) + const projectRes = projectNameArr.length ? await models.Project.findAll({ + where: { + entryName: { $in: projectNameArr } + } + }) : [] + for (let r of reportRes) { + let corProject = projectRes.find(item => item.entryName == r.project_name) + if (corProject) { + r.project = corProject.dataValues + } } - } else { - reportRes = await models.Report.findAll(findOption) - } - - ctx.status = 200; - ctx.body = reportRes - } catch (error) { - ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); - ctx.status = 400; - ctx.body = { - message: typeof error == 'string' ? error : undefined - } - } + } + } else { + reportRes = await models.Report.findAll(findOption) + } + + ctx.status = 200; + ctx.body = reportRes + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { + message: typeof error == 'string' ? error : undefined + } + } } async function reportPosition (ctx) { - try { - const models = ctx.fs.dc.models; - const { startTime, endTime, userId, reportType } = ctx.query - const sequelize = ctx.fs.dc.ORM; - - let findMxTimeOption = { - attributes: [ - 'userId', - [sequelize.fn('MAX', sequelize.col('time')), 'maxTime'], - ], - where: { - - }, - group: ['report.user_id'], - } - - if (startTime && endTime) { - findMxTimeOption.where = { - time: { - '$between': [startTime, endTime] - } + try { + const models = ctx.fs.dc.models; + const { startTime, endTime, userId, reportType } = ctx.query + const sequelize = ctx.fs.dc.ORM; + + let findMxTimeOption = { + attributes: [ + 'userId', + [sequelize.fn('MAX', sequelize.col('time')), 'maxTime'], + ], + where: { + + }, + group: ['report.user_id'], + } + + if (startTime && endTime) { + findMxTimeOption.where = { + time: { + '$between': [startTime, endTime] } - } - - if (userId) { - findMxTimeOption.where.userId = userId - } - if (reportType) { - findMxTimeOption.where.reportType = reportType - } - - const reportMaxTimeRes = await models.Report.findAll(findMxTimeOption) - const timeArr = reportMaxTimeRes.map(item => item.dataValues.maxTime) - const reportRes = await models.Report.findAll({ - where: { - time: { '$in': timeArr } - } - }) - ctx.status = 200; - ctx.body = reportRes - } catch (error) { - ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); - ctx.status = 400; - ctx.body = { - message: typeof error == 'string' ? error : undefined - } - } + } + } + + if (userId) { + findMxTimeOption.where.userId = userId + } + if (reportType) { + findMxTimeOption.where.reportType = reportType + } + + const reportMaxTimeRes = await models.Report.findAll(findMxTimeOption) + const timeArr = reportMaxTimeRes.map(item => item.dataValues.maxTime) + const reportRes = await models.Report.findAll({ + where: { + time: { '$in': timeArr } + } + }) + ctx.status = 200; + ctx.body = reportRes + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { + message: typeof error == 'string' ? error : undefined + } + } } async function reportDetail (ctx) { - try { - const models = ctx.fs.dc.models; - const { reportId } = ctx.params - - const reportRes = await models.Report.findOne({ + try { + const models = ctx.fs.dc.models; + const { reportId } = ctx.params + + const reportRes = await models.Report.findOne({ + where: { + id: reportId + }, + include: [{ + model: models.Road, where: { - id: reportId + del: false }, - include: [{ - model: models.Road, - where: { - del: false - }, - as: 'road_', - }], - }) - - ctx.status = 200; - ctx.body = reportRes - } catch (error) { - ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); - ctx.status = 400; - ctx.body = { - message: typeof error == 'string' ? error : undefined - } - } + as: 'road_', + }], + }) + + ctx.status = 200; + ctx.body = reportRes + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { + message: typeof error == 'string' ? error : undefined + } + } } async function reportHandle (ctx) { - try { - const { models } = ctx.fs.dc; - - const { reportId } = ctx.params - const { handleState } = ctx.request.body - const data = ctx.request.body - /** - * data = { - * handleState, - * handleContent, - * handlePic - * } - */ - await models.Report.update(data, { - where: { - id: reportId - } - }) - - ctx.status = 200; - } catch (error) { - ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); - ctx.status = 400; - ctx.body = { - message: typeof error == 'string' ? error : undefined - } - } + try { + const { models } = ctx.fs.dc; + + const { reportId } = ctx.params + const { handleState } = ctx.request.body + const data = ctx.request.body + /** + * data = { + * handleState, + * handleContent, + * handlePic + * } + */ + await models.Report.update(data, { + where: { + id: reportId + } + }) + + ctx.status = 200; + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { + message: typeof error == 'string' ? error : undefined + } + } } async function createReport (ctx) { - try { - const { userId } = ctx.fs.api - const models = ctx.fs.dc.models; - const data = ctx.request.body; - - await models.Report.create({ - ...data, - userId, - time: new Date(), - }) - - ctx.status = 204 - } catch (error) { - ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); - ctx.status = 400; - ctx.body = { - message: typeof error == 'string' ? error : undefined - } - } + try { + const { userId } = ctx.fs.api + const models = ctx.fs.dc.models; + const data = ctx.request.body; + + await models.Report.create({ + ...data, + userId, + time: new Date(), + }) + + ctx.status = 204 + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { + message: typeof error == 'string' ? error : undefined + } + } } async function deleteReport (ctx) { - try { - const models = ctx.fs.dc.models; - const { reportId } = ctx.params; - - await models.Report.destroy({ - where: { - id: reportId - } - }) - - ctx.status = 204 - } catch (error) { - ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); - ctx.status = 400; - ctx.body = { - message: typeof error == 'string' ? error : undefined - } - } + try { + const models = ctx.fs.dc.models; + const { reportId } = ctx.params; + + await models.Report.destroy({ + where: { + id: reportId + } + }) + + ctx.status = 204 + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { + message: typeof error == 'string' ? error : undefined + } + } } // TODO 小程序填写道路名称的时候的道路筛选 是一起都返回 还是不断传关键字搜索返回 async function spotPrepare (ctx) { - try { - const { models } = ctx.fs.dc; - const sequelize = ctx.fs.dc.orm; - const { percentage } = ctx.request.body; - const departmentIdRes = await models.Department.findAll({ - attributes: ['id', 'name'], - where: { - dependence: null, - delete: false, - } - }) - let lukyDepartment = '' - if (departmentIdRes.length) { - lukyDepartment = departmentIdRes[(Math.round(Math.random() * departmentIdRes.length) || 1) - 1] - } else { - throw `暂无乡镇信息` - } - - const sqlStr = ` + try { + const { models } = ctx.fs.dc; + const sequelize = ctx.fs.dc.orm; + const { percentage } = ctx.request.body; + const departmentIdRes = await models.Department.findAll({ + attributes: ['id', 'name'], + where: { + dependence: null, + delete: false, + } + }) + let lukyDepartment = '' + if (departmentIdRes.length) { + lukyDepartment = departmentIdRes[(Math.round(Math.random() * departmentIdRes.length) || 1) - 1] + } else { + throw `暂无乡镇信息` + } + + const sqlStr = ` WITH RECURSIVE sub_departments AS ( SELECT id, dependence FROM department @@ -338,60 +340,60 @@ async function spotPrepare (ctx) { WHERE u.delete = false; ` - const userRes = await sequelize.query(sqlStr, { type: QueryTypes.SELECT }) - let findUsers = [] - findUsers = userRes.map(item => { - return item.id - }) - - const reportCount = findUsers.length ? await models.Report.count({ - where: { - reportType: 'conserve', - userId: { $in: findUsers } - } - }) : 0 - - const previewRes = await models.ReportSpotCheckPreview.create({ - percentage: percentage, - departmentId: lukyDepartment.id, - date: moment().format(), - reportCount: reportCount, - checked: false, - }) - - - ctx.status = 200; - ctx.body = { - lukyDepartment, - reportCount, - previewId: previewRes.id - } - } catch (error) { - ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); - ctx.status = 400; - ctx.body = { - message: typeof error == 'string' ? error : undefined - } - } + const userRes = await sequelize.query(sqlStr, { type: QueryTypes.SELECT }) + let findUsers = [] + findUsers = userRes.map(item => { + return item.id + }) + + const reportCount = findUsers.length ? await models.Report.count({ + where: { + reportType: 'conserve', + userId: { $in: findUsers } + } + }) : 0 + + const previewRes = await models.ReportSpotCheckPreview.create({ + percentage: percentage, + departmentId: lukyDepartment.id, + date: moment().format(), + reportCount: reportCount, + checked: false, + }) + + + ctx.status = 200; + ctx.body = { + lukyDepartment, + reportCount, + previewId: previewRes.id + } + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { + message: typeof error == 'string' ? error : undefined + } + } } async function spotCheck (ctx) { - const transaction = await ctx.fs.dc.orm.transaction(); - try { - const { models } = ctx.fs.dc; - const sequelize = ctx.fs.dc.orm; - const { previewId } = ctx.query - if (!previewId) { - throw '参数错误' - } - - const prepareRes = await models.ReportSpotCheckPreview.findOne({ - where: { - id: previewId - } - }) - - const sqlStr = ` + const transaction = await ctx.fs.dc.orm.transaction(); + try { + const { models } = ctx.fs.dc; + const sequelize = ctx.fs.dc.orm; + const { previewId } = ctx.query + if (!previewId) { + throw '参数错误' + } + + const prepareRes = await models.ReportSpotCheckPreview.findOne({ + where: { + id: previewId + } + }) + + const sqlStr = ` WITH RECURSIVE sub_departments AS ( SELECT id, dependence FROM department @@ -407,195 +409,195 @@ async function spotCheck (ctx) { WHERE u.delete = false; ` - const userRes = await sequelize.query(sqlStr, { type: QueryTypes.SELECT }) - let findUsers = [] - findUsers = userRes.map(item => { - return item.id - }) - let checkCount = Math.ceil(prepareRes.reportCount * (prepareRes.percentage / 100)) - - const reportRes = await findUsers.length && checkCount ? await models.Report.findAll({ - where: { - reportType: 'conserve', - userId: { $in: findUsers }, - }, - include: [{ - model: models.User, - attributes: ['name'] - }], - order: sequelize.random(), // 随机排序 - limit: checkCount, // 限制返回的记录数 - }) : [] - - await models.ReportSpotCheckPreview.update({ - checked: true - }, { - where: { - id: previewId + const userRes = await sequelize.query(sqlStr, { type: QueryTypes.SELECT }) + let findUsers = [] + findUsers = userRes.map(item => { + return item.id + }) + let checkCount = Math.ceil(prepareRes.reportCount * (prepareRes.percentage / 100)) + + const reportRes = await findUsers.length && checkCount ? await models.Report.findAll({ + where: { + reportType: 'conserve', + userId: { $in: findUsers }, + }, + include: [{ + model: models.User, + attributes: ['name'] + }], + order: sequelize.random(), // 随机排序 + limit: checkCount, // 限制返回的记录数 + }) : [] + + await models.ReportSpotCheckPreview.update({ + checked: true + }, { + where: { + id: previewId + } + }) + if (reportRes.length) { + let spotDate = moment().format('YYYY-MM-DD') + await models.ReportSpotCheck.bulkCreate(reportRes.map(r => { + return { + reportId: r.id, + spotDate: spotDate, + prepareId: previewId } - }) - if (reportRes.length) { - let spotDate = moment().format('YYYY-MM-DD') - await models.ReportSpotCheck.bulkCreate(reportRes.map(r => { - return { - reportId: r.id, - spotDate: spotDate, - prepareId: previewId - } - })) - } - const rslt = findUsers.length && checkCount ? await models.ReportSpotCheckPreview.findAll({ - where: { - checked: 'true', - id: previewId - }, + })) + } + const rslt = findUsers.length && checkCount ? await models.ReportSpotCheckPreview.findAll({ + where: { + checked: 'true', + id: previewId + }, + include: [{ + model: models.Department, + attributes: ['name'] + }, { + model: models.ReportSpotCheck, include: [{ - model: models.Department, - attributes: ['name'] - }, { - model: models.ReportSpotCheck, - include: [{ - model: models.Report, - include: [{ - model: models.User, - attributes: ['name'] - }], - }] - } - ], - }) : [] - - await transaction.commit(); - ctx.status = 200; - ctx.body = rslt - } catch (error) { - await transaction.rollback(); - ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); - ctx.status = 400; - ctx.body = { - message: typeof error == 'string' ? error : undefined - } - } + model: models.Report, + include: [{ + model: models.User, + attributes: ['name'] + }], + }] + } + ], + }) : [] + + await transaction.commit(); + ctx.status = 200; + ctx.body = rslt + } catch (error) { + await transaction.rollback(); + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { + message: typeof error == 'string' ? error : undefined + } + } } async function spotCheckDetail (ctx) { - const { models } = ctx.fs.dc - const { startTime, endTime } = ctx.query - try { - const res = await models.ReportSpotCheckPreview.findAll({ - where: { - checked: 'true' - }, - order: [['date', 'DESC']], + const { models } = ctx.fs.dc + const { startTime, endTime } = ctx.query + try { + const res = await models.ReportSpotCheckPreview.findAll({ + where: { + checked: 'true' + }, + order: [['date', 'DESC']], + include: [{ + model: models.Department, + attributes: ['name'] + }, { + model: models.ReportSpotCheck, + where: { spotDate: { $between: [moment(startTime).format('YYYY-MM-DD'), moment(endTime).format('YYYY-MM-DD')] } }, + order: [['spot_date', 'DESC']], include: [{ - model: models.Department, - attributes: ['name'] - }, { - model: models.ReportSpotCheck, - where: { spotDate: { $between: [moment(startTime).format('YYYY-MM-DD'), moment(endTime).format('YYYY-MM-DD')] } }, - order: [['spot_date', 'DESC']], - include: [{ - model: models.Report, - order: [['date', 'DESC']], - include: [{ - model: models.User, - attributes: ['name'] - }], - }] - } - ], - }) - ctx.body = res - ctx.status = 200 - } catch (error) { - ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`) - ctx.status = 400 - ctx.body = { - message: typeof error == 'string' ? error : undefined - } - } + model: models.Report, + order: [['date', 'DESC']], + include: [{ + model: models.User, + attributes: ['name'] + }], + }] + } + ], + }) + ctx.body = res + ctx.status = 200 + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`) + ctx.status = 400 + ctx.body = { + message: typeof error == 'string' ? error : undefined + } + } } async function roadSpotPrepare (ctx) { - try { - const { models } = ctx.fs.dc; - const sequelize = ctx.fs.dc.orm; - const { countyPercentage } = ctx.request.body; + try { + const { models } = ctx.fs.dc; + const sequelize = ctx.fs.dc.orm; + const { countyPercentage } = ctx.request.body; - const lastSpotRes = await models.RoadSpotCheckPreview.findOne({ + const lastSpotRes = await models.RoadSpotCheckPreview.findOne({ + where: { + checked: true + }, + // attributes: ['id', 'countyPercentage', 'date',], + order: [['date', 'DESC']], + // include: [{ + // model: models.RoadSpotCheck, + // include: [{ + // model: models.Road, + // // attributes: ['id', 'name'] + // }] + // }] + }) + + let lastCountyPercentage = 0 // 最后一次的县道百分比 + + let lastCountyRoadIds = [] // 上次查得的县道id + let lastTownRoadIds = [] // 上次查得的乡镇道id + let lastVillageRoadRoadIds = [] // 上次查得的村道id + let lastVillageIds = [] + + if (lastSpotRes) { + lastCountyPercentage = lastSpotRes.countyPercentage + lastCountyRoadIds = lastSpotRes.countyRoadId || [] + + let lastCounty = await models.RoadSpotCheckPreview.findAll({ where: { - checked: true + checked: true, + id: { $lt: lastSpotRes.id } }, - // attributes: ['id', 'countyPercentage', 'date',], + limit: 3, order: [['date', 'DESC']], - // include: [{ - // model: models.RoadSpotCheck, - // include: [{ - // model: models.Road, - // // attributes: ['id', 'name'] - // }] - // }] - }) - - let lastCountyPercentage = 0 // 最后一次的县道百分比 - - let lastCountyRoadIds = [] // 上次查得的县道id - let lastTownRoadIds = [] // 上次查得的乡镇道id - let lastVillageRoadRoadIds = [] // 上次查得的村道id - let lastVillageIds = [] - - if (lastSpotRes) { - lastCountyPercentage = lastSpotRes.countyPercentage - lastCountyRoadIds = lastSpotRes.countyRoadId || [] - - let lastCounty = await models.RoadSpotCheckPreview.findAll({ - where: { - checked: true, - id: { $lt: lastSpotRes.id } - }, - limit: 3, - order: [['date', 'DESC']], - }) + }) - if (lastCounty) { - lastCounty.forEach(d => { - lastTownRoadIds = lastTownRoadIds.concat(d.townshipRoadId) || [] - - }) - } + if (lastCounty) { + lastCounty.forEach(d => { + lastTownRoadIds = lastTownRoadIds.concat(d.townshipRoadId) || [] - let lastVillage = await models.RoadSpotCheckPreview.findAll({ - where: { - checked: true, - id: { $lt: lastSpotRes.id } - }, - limit: 9, - order: [['date', 'DESC']], }) + } - if (lastVillage) { - lastVillage.forEach(d => { - lastVillageRoadRoadIds = lastVillageRoadRoadIds.concat(d.villageRoadId) || [] - lastVillageIds = lastVillageIds.concat(d.villageId) || [] + let lastVillage = await models.RoadSpotCheckPreview.findAll({ + where: { + checked: true, + id: { $lt: lastSpotRes.id } + }, + limit: 9, + order: [['date', 'DESC']], + }) - }) - } + if (lastVillage) { + lastVillage.forEach(d => { + lastVillageRoadRoadIds = lastVillageRoadRoadIds.concat(d.villageRoadId) || [] + lastVillageIds = lastVillageIds.concat(d.villageId) || [] + }) + } - // lastTownRoadIds = lastSpotRes.townshipRoadId || [] - // lastVillageRoadRoadIds = lastSpotRes.villageRoadId || [] - // lastVillageIds = lastSpotRes.villageId || [] - } - // 先查上次没查的范围内的 然后比较百分比 如果重叠 再查上次查过的 + // lastTownRoadIds = lastSpotRes.townshipRoadId || [] + // lastVillageRoadRoadIds = lastSpotRes.villageRoadId || [] + // lastVillageIds = lastSpotRes.villageId || [] + } - let keyMap = { - '县': `route_code LIKE 'X%'`, - '乡': `route_code LIKE 'Y%'`, - '村': `route_code LIKE 'C%'` - } - async function getRoadTotalMileage (key, otherWhere = []) { - let res = await sequelize.query(` + // 先查上次没查的范围内的 然后比较百分比 如果重叠 再查上次查过的 + + let keyMap = { + '县': `route_code LIKE 'X%'`, + '乡': `route_code LIKE 'Y%'`, + '村': `route_code LIKE 'C%'` + } + async function getRoadTotalMileage (key, otherWhere = []) { + let res = await sequelize.query(` SELECT SUM(COALESCE(CAST(chainage_mileage AS DOUBLE PRECISION), 0)) AS total_mileage FROM road @@ -603,97 +605,97 @@ async function roadSpotPrepare (ctx) { AND spot = true AND ${keyMap[key]} ${otherWhere.length ? `AND ${otherWhere.join(' AND ')}` : ''} `) - return res[0][0].total_mileage - } - - async function getRoadSpot (key, lastRoadIds = [], inOrNot, otherWhere = []) { - if (!lastRoadIds.length && !inOrNot) { - return [] - } - return await sequelize.query(` + return res[0][0].total_mileage + } + + async function getRoadSpot (key, lastRoadIds = [], inOrNot, otherWhere = []) { + if (!lastRoadIds.length && !inOrNot) { + return [] + } + return await sequelize.query(` SELECT id, chainage_mileage FROM road WHERE del = false AND spot = true AND ${keyMap[key]} ${lastRoadIds.length ? - `AND id ${inOrNot ? 'IN' : 'NOT IN'} ( + `AND id ${inOrNot ? 'IN' : 'NOT IN'} ( ${lastRoadIds.map(item => `'${item}'`).join(',')},-1 )` : '' - } + } AND chainage_mileage IS NOT NULL ${otherWhere.length ? `AND ${otherWhere.join(' AND ')}` : ''} ORDER BY RANDOM() `, { type: QueryTypes.SELECT }); - } - - async function spotRoadId (key, lastRoadIds, targetMileage, otherWhere = [], villageIdList = []) { - let spotRoadIds = [] - let accumulationMileage = 0 - - async function filterRoad (otherWhere, getRepeat = true) { - - if (key == '村' && getRepeat == true) { - - } else { - let roadUnSpotedRes = await getRoadSpot(key, lastRoadIds, false, otherWhere) - - for (let r of roadUnSpotedRes) { - spotRoadIds.push(r.id) - accumulationMileage += parseFloat(r.chainage_mileage) - if (accumulationMileage >= targetMileage) { - break; - } - } - } - - if (accumulationMileage < targetMileage && getRepeat) { - // 还小于 说明没取够 - let roadUnSpotedRepeatRes = await getRoadSpot( - key, - lastRoadIds, - true, - otherWhere - ) - for (let r of roadUnSpotedRepeatRes) { - spotRoadIds.push(r.id) - accumulationMileage += parseFloat(r.chainage_mileage) - if (accumulationMileage >= targetMileage) { - break; - } - } - } - } + } + + async function spotRoadId (key, lastRoadIds, targetMileage, otherWhere = [], villageIdList = []) { + let spotRoadIds = [] + let accumulationMileage = 0 + + async function filterRoad (otherWhere, getRepeat = true) { + + if (key == '村' && getRepeat == true) { - if (key == '村') { - for await (let villageId of villageIdList) { - await filterRoad([ - ...otherWhere, - `village_id=${villageId}` - ], false) - - spotVillageIds.push(villageId) - - if (accumulationMileage >= targetMileage) { - break; - } - } - if (accumulationMileage < targetMileage) { - // 还小于 说明没取够 - await filterRoad(otherWhere, true) - } } else { - await filterRoad(otherWhere, true) + let roadUnSpotedRes = await getRoadSpot(key, lastRoadIds, false, otherWhere) + + for (let r of roadUnSpotedRes) { + spotRoadIds.push(r.id) + accumulationMileage += parseFloat(r.chainage_mileage) + if (accumulationMileage >= targetMileage) { + break; + } + } } - return spotRoadIds - } + if (accumulationMileage < targetMileage && getRepeat) { + // 还小于 说明没取够 + let roadUnSpotedRepeatRes = await getRoadSpot( + key, + lastRoadIds, + true, + otherWhere + ) + for (let r of roadUnSpotedRepeatRes) { + spotRoadIds.push(r.id) + accumulationMileage += parseFloat(r.chainage_mileage) + if (accumulationMileage >= targetMileage) { + break; + } + } + } + } + + if (key == '村') { + for await (let villageId of villageIdList) { + await filterRoad([ + ...otherWhere, + `village_id=${villageId}` + ], false) - // 抽县 - const countryRoadTotalMileage = await getRoadTotalMileage('县') - const countryRoadNeedMileage = countryRoadTotalMileage * countyPercentage / 100 - let spotCountyRoadIds = await spotRoadId('县', lastCountyRoadIds, countryRoadNeedMileage, []) + spotVillageIds.push(villageId) - // 抽乡 - const allTownCodeRes = await sequelize.query(` + if (accumulationMileage >= targetMileage) { + break; + } + } + if (accumulationMileage < targetMileage) { + // 还小于 说明没取够 + await filterRoad(otherWhere, true) + } + } else { + await filterRoad(otherWhere, true) + } + + return spotRoadIds + } + + // 抽县 + const countryRoadTotalMileage = await getRoadTotalMileage('县') + const countryRoadNeedMileage = countryRoadTotalMileage * countyPercentage / 100 + let spotCountyRoadIds = await spotRoadId('县', lastCountyRoadIds, countryRoadNeedMileage, []) + + // 抽乡 + const allTownCodeRes = await sequelize.query(` SELECT DISTINCT township_code FROM road @@ -702,25 +704,25 @@ async function roadSpotPrepare (ctx) { AND township_code IS NOT NULL `, { type: QueryTypes.SELECT }); - let spotTownRoadIds = [] - let spotVillageRoadIds = [] - let spotVillageIds = [] - for await (let t of allTownCodeRes) { - // 遍历每个乡镇并抽取 - let otherWhere = [`township_code='${t.township_code}'`] - const townRoadTotalMileage = await getRoadTotalMileage('乡', otherWhere) - const townRoadNeedMileage = townRoadTotalMileage * 25 / 100 - - let spotTownRoadIds_ = await spotRoadId('乡', lastTownRoadIds, townRoadNeedMileage, otherWhere) - spotTownRoadIds = spotTownRoadIds.concat(spotTownRoadIds_) - - // 抽村 - const villageRoadTotalMileage = await getRoadTotalMileage('村', otherWhere) - const villageRoadNeedMileage = villageRoadTotalMileage * 10 / 100 - - let spotFirstVillageId = -1 - // 随机选取一个不在上次查过的村 - let villageRes = await sequelize.query(` + let spotTownRoadIds = [] + let spotVillageRoadIds = [] + let spotVillageIds = [] + for await (let t of allTownCodeRes) { + // 遍历每个乡镇并抽取 + let otherWhere = [`township_code='${t.township_code}'`] + const townRoadTotalMileage = await getRoadTotalMileage('乡', otherWhere) + const townRoadNeedMileage = townRoadTotalMileage * 25 / 100 + + let spotTownRoadIds_ = await spotRoadId('乡', lastTownRoadIds, townRoadNeedMileage, otherWhere) + spotTownRoadIds = spotTownRoadIds.concat(spotTownRoadIds_) + + // 抽村 + const villageRoadTotalMileage = await getRoadTotalMileage('村', otherWhere) + const villageRoadNeedMileage = villageRoadTotalMileage * 10 / 100 + + let spotFirstVillageId = -1 + // 随机选取一个不在上次查过的村 + let villageRes = await sequelize.query(` SELECT id FROM village WHERE township_code = '${t.township_code}' ${lastVillageIds.length ? `AND id NOT IN ( @@ -729,80 +731,80 @@ async function roadSpotPrepare (ctx) { ORDER BY RANDOM() LIMIT 1 `, { type: QueryTypes.SELECT }); - if (!villageRes.length) { - // 没有村了,随机选一个 - villageRes = await sequelize.query(` + if (!villageRes.length) { + // 没有村了,随机选一个 + villageRes = await sequelize.query(` SELECT id FROM village WHERE township_code = '${t.township_code}' ORDER BY RANDOM() LIMIT 1 `, { type: QueryTypes.SELECT }); - } - if (villageRes.length) { - spotVillageIds.push(villageRes[0].id) - spotFirstVillageId = villageRes[0].id - } else { - continue; - } - - const villageNearRes = await sequelize.query(` + } + if (villageRes.length) { + spotVillageIds.push(villageRes[0].id) + spotFirstVillageId = villageRes[0].id + } else { + continue; + } + + const villageNearRes = await sequelize.query(` SELECT id,calc_village,distance FROM village_distance WHERE origin_village = ${spotFirstVillageId} ORDER BY distance ASC `, { type: QueryTypes.SELECT }) - let villageCheckIdList = villageNearRes.map(item => item.calc_village) - villageCheckIdList.unshift(spotFirstVillageId) - villageCheckIdList = [...(new Set(villageCheckIdList))] - - let spotVillageRoadIds_ = await spotRoadId('村', lastVillageRoadRoadIds, villageRoadNeedMileage, otherWhere, villageCheckIdList) - spotVillageRoadIds = spotVillageRoadIds.concat(spotVillageRoadIds_) - } - - const previewRes = await models.RoadSpotCheckPreview.create({ - countyPercentage: countyPercentage, - date: moment().format(), - countyRoadId: spotCountyRoadIds, - townshipRoadId: spotTownRoadIds, - villageRoadId: spotVillageRoadIds, - villageId: spotVillageIds, - checked: false - }) - - ctx.status = 200; - ctx.body = { - previewId: previewRes.id, - spotCountyRoadCount: spotCountyRoadIds.length, - spotTownRoadCount: spotTownRoadIds.length, - spotVillageRoadCount: spotVillageRoadIds.length, - } - } catch (error) { - ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); - ctx.status = 400; - ctx.body = { - message: typeof error == 'string' ? error : undefined - } - } + let villageCheckIdList = villageNearRes.map(item => item.calc_village) + villageCheckIdList.unshift(spotFirstVillageId) + villageCheckIdList = [...(new Set(villageCheckIdList))] + + let spotVillageRoadIds_ = await spotRoadId('村', lastVillageRoadRoadIds, villageRoadNeedMileage, otherWhere, villageCheckIdList) + spotVillageRoadIds = spotVillageRoadIds.concat(spotVillageRoadIds_) + } + + const previewRes = await models.RoadSpotCheckPreview.create({ + countyPercentage: countyPercentage, + date: moment().format(), + countyRoadId: spotCountyRoadIds, + townshipRoadId: spotTownRoadIds, + villageRoadId: spotVillageRoadIds, + villageId: spotVillageIds, + checked: false + }) + + ctx.status = 200; + ctx.body = { + previewId: previewRes.id, + spotCountyRoadCount: spotCountyRoadIds.length, + spotTownRoadCount: spotTownRoadIds.length, + spotVillageRoadCount: spotVillageRoadIds.length, + } + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { + message: typeof error == 'string' ? error : undefined + } + } } async function confirmRoadSpot (ctx) { - const transaction = await ctx.fs.dc.orm.transaction(); - try { - const { models } = ctx.fs.dc; - const sequelize = ctx.fs.dc.orm; - const { previewId } = ctx.request.body - - const prepareRes = await models.RoadSpotCheckPreview.findOne({ - where: { - id: previewId - } - }) - let spotedRoadIds = [] - spotedRoadIds = spotedRoadIds.concat(prepareRes.dataValues.countyRoadId) - spotedRoadIds = spotedRoadIds.concat(prepareRes.dataValues.townshipRoadId) - spotedRoadIds = spotedRoadIds.concat(prepareRes.dataValues.villageRoadId) - - const conserveCountRes = await sequelize.query(` + const transaction = await ctx.fs.dc.orm.transaction(); + try { + const { models } = ctx.fs.dc; + const sequelize = ctx.fs.dc.orm; + const { previewId } = ctx.request.body + + const prepareRes = await models.RoadSpotCheckPreview.findOne({ + where: { + id: previewId + } + }) + let spotedRoadIds = [] + spotedRoadIds = spotedRoadIds.concat(prepareRes.dataValues.countyRoadId) + spotedRoadIds = spotedRoadIds.concat(prepareRes.dataValues.townshipRoadId) + spotedRoadIds = spotedRoadIds.concat(prepareRes.dataValues.villageRoadId) + + const conserveCountRes = await sequelize.query(` SELECT road_id, COUNT(road_id) as count FROM report WHERE road_id IN ( @@ -811,392 +813,393 @@ async function confirmRoadSpot (ctx) { GROUP BY road_id `, { type: QueryTypes.SELECT }) - let spotRslt = [] - for await (let item of spotedRoadIds) { - let corConserveCount = conserveCountRes.find(cc => cc.road_id == item) - spotRslt.push({ - roadId: item, - maintenanceCount: corConserveCount ? corConserveCount.count : 0, - prepareId: previewId - }) - } - - await models.RoadSpotCheck.bulkCreate(spotRslt, { - transaction - }) - await models.RoadSpotCheckPreview.update({ - checked: true - }, { - where: { - id: previewId - }, - transaction - }) - - await transaction.commit(); - ctx.status = 204; - } catch (error) { - await transaction.rollback(); - ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); - ctx.status = 400; - ctx.body = { - message: typeof error == 'string' ? error : undefined - } - } + let spotRslt = [] + for await (let item of spotedRoadIds) { + let corConserveCount = conserveCountRes.find(cc => cc.road_id == item) + spotRslt.push({ + roadId: item, + maintenanceCount: corConserveCount ? corConserveCount.count : 0, + prepareId: previewId + }) + } + + await models.RoadSpotCheck.bulkCreate(spotRslt, { + transaction + }) + await models.RoadSpotCheckPreview.update({ + checked: true + }, { + where: { + id: previewId + }, + transaction + }) + + await transaction.commit(); + ctx.status = 204; + } catch (error) { + await transaction.rollback(); + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { + message: typeof error == 'string' ? error : undefined + } + } } async function roadSpotList (ctx) { - try { - const { models } = ctx.fs.dc; - const { startTime, endTime, page, limit } = ctx.query + try { + const { models } = ctx.fs.dc; + const { startTime, endTime, page, limit } = ctx.query - let findOpt = { - order: [['id', 'DESC']], - where: { - checked: true - } - } - - if (startTime && endTime) { - findOpt.where.date = { - $between: [moment(startTime).startOf('day').format(), moment(endTime).endOf('day').format()] - } - - } - - if (page && limit) { - findOpt.offset = (page - 1) * limit - findOpt.limit = limit - } - - const listRes = await models.RoadSpotCheckPreview.findAll(findOpt) - - - - ctx.status = 200; - ctx.body = listRes.map(item => { - return { - id: item.id, - date: item.date, - countyPercentage: item.countyPercentage, - spotCountyRoadCount: item.countyRoadId ? item.countyRoadId.length : 0, - spotTownRoadCount: item.townshipRoadId ? item.townshipRoadId.length : 0, - spotVillageRoadCount: item.villageRoadId ? item.villageRoadId.length : 0, - countyRoadId: item.countyRoadId, - townshipRoadId: item.townshipRoadId, - villageRoadId: item.villageRoadId, - } - }) - } catch (error) { - ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); - ctx.status = 400; - ctx.body = { - message: typeof error == 'string' ? error : undefined - } - } + let findOpt = { + order: [['id', 'DESC']], + where: { + checked: true + } + } + + if (startTime && endTime) { + findOpt.where.date = { + $between: [moment(startTime).startOf('day').format(), moment(endTime).endOf('day').format()] + } + + } + + if (page && limit) { + findOpt.offset = (page - 1) * limit + findOpt.limit = limit + } + + const listRes = await models.RoadSpotCheckPreview.findAll(findOpt) + + + + ctx.status = 200; + ctx.body = listRes.map(item => { + return { + id: item.id, + date: item.date, + countyPercentage: item.countyPercentage, + spotCountyRoadCount: item.countyRoadId ? item.countyRoadId.length : 0, + spotTownRoadCount: item.townshipRoadId ? item.townshipRoadId.length : 0, + spotVillageRoadCount: item.villageRoadId ? item.villageRoadId.length : 0, + countyRoadId: item.countyRoadId, + townshipRoadId: item.townshipRoadId, + villageRoadId: item.villageRoadId, + } + }) + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { + message: typeof error == 'string' ? error : undefined + } + } } async function roadSpotDetail (ctx) { - try { - const { models } = ctx.fs.dc; - const { previewId, keyword } = ctx.query - - const listRes = await models.RoadSpotCheck.findAll({ + try { + const { models } = ctx.fs.dc; + const { previewId, keyword } = ctx.query + + const listRes = await models.RoadSpotCheck.findAll({ + where: { + prepareId: previewId, + }, + include: [{ + model: models.Road, where: { - prepareId: previewId, + ...(keyword ? { routeName: { $ilike: `%${keyword}%` } } : {}), + del: false, }, + }, { + model: models.RoadSpotCheckPreview, + attributes: ['id'], include: [{ - model: models.Road, - where: { - ...(keyword ? { routeName: { $ilike: `%${keyword}%` } } : {}), - del: false, - }, - }, { - model: models.RoadSpotCheckPreview, - attributes: ['id'], - include: [{ - model: models.RoadSpotCheckChangeLog, - attributes: ['id', 'changeRoadId'], - }] + model: models.RoadSpotCheckChangeLog, + attributes: ['id', 'changeRoadId'], }] - }) - - - ctx.status = 200; - ctx.body = listRes - } catch (error) { - ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); - ctx.status = 400; - ctx.body = { - message: typeof error == 'string' ? error : undefined - } - } + }] + }) + + + ctx.status = 200; + ctx.body = listRes + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { + message: typeof error == 'string' ? error : undefined + } + } } async function roadSpotChange (ctx) { - const transaction = await ctx.fs.dc.orm.transaction(); - try { - const { models } = ctx.fs.dc; - const sequelize = ctx.fs.dc.orm; - const { originRoadId, changeRoadId, previewId } = ctx.request.body - - if (originRoadId == changeRoadId) { - throw '原路段与目标路段不能相同' - } - - const previewRes = await models.RoadSpotCheckPreview.findOne({ - where: { - id: previewId - } - }) - - if (!previewRes) { - throw '预览数据不存在' - } - - let previewUpdated = false - async function updatePreview (key) { - if (previewUpdated) return - - if (previewRes[key] && previewRes[key].includes(originRoadId)) { - let originRoadIds = previewRes.dataValues[key] - let originRoadIdIndex = originRoadIds.indexOf(originRoadId) - - originRoadIds.splice(originRoadIdIndex, 1, changeRoadId) - - await models.RoadSpotCheckPreview.update({ - [key]: originRoadIds - }, { - where: { - id: previewId - }, - transaction - }) - previewUpdated = true - } - } - await updatePreview('countyRoadId') - await updatePreview('townshipRoadId') - await updatePreview('villageRoadId') - - if (!previewUpdated) { - throw '更改路段不在抽查范围内' - } - - const roadRes = await models.Road.findAll({ - where: { - id: { $in: [originRoadId, changeRoadId] }, - del: false, - } - }) - - if (roadRes.length != 2) { - throw '路段不存在' - } - - let content = '' - let curOriginRoad = roadRes.find(item => item.id == originRoadId) - let curChangeRoad = roadRes.find(item => item.id == changeRoadId) - - content = `将${curOriginRoad.routeName}从${curOriginRoad.startingPlaceName}到${curOriginRoad.stopPlaceName}改为${curChangeRoad.routeName}从${curChangeRoad.startingPlaceName}到${curChangeRoad.stopPlaceName}` - - const maintenanceCount = await sequelize.query(` + const transaction = await ctx.fs.dc.orm.transaction(); + try { + const { models } = ctx.fs.dc; + const sequelize = ctx.fs.dc.orm; + const { originRoadId, changeRoadId, previewId } = ctx.request.body + + if (originRoadId == changeRoadId) { + throw '原路段与目标路段不能相同' + } + + const previewRes = await models.RoadSpotCheckPreview.findOne({ + where: { + id: previewId + } + }) + + if (!previewRes) { + throw '预览数据不存在' + } + + let previewUpdated = false + async function updatePreview (key) { + if (previewUpdated) return + + if (previewRes[key] && previewRes[key].includes(originRoadId)) { + let originRoadIds = previewRes.dataValues[key] + let originRoadIdIndex = originRoadIds.indexOf(originRoadId) + + originRoadIds.splice(originRoadIdIndex, 1, changeRoadId) + + await models.RoadSpotCheckPreview.update({ + [key]: originRoadIds + }, { + where: { + id: previewId + }, + transaction + }) + previewUpdated = true + } + } + await updatePreview('countyRoadId') + await updatePreview('townshipRoadId') + await updatePreview('villageRoadId') + + if (!previewUpdated) { + throw '更改路段不在抽查范围内' + } + + const roadRes = await models.Road.findAll({ + where: { + id: { $in: [originRoadId, changeRoadId] }, + del: false, + } + }) + + if (roadRes.length != 2) { + throw '路段不存在' + } + + let content = '' + let curOriginRoad = roadRes.find(item => item.id == originRoadId) + let curChangeRoad = roadRes.find(item => item.id == changeRoadId) + + content = `将${curOriginRoad.routeName}从${curOriginRoad.startingPlaceName}到${curOriginRoad.stopPlaceName}改为${curChangeRoad.routeName}从${curChangeRoad.startingPlaceName}到${curChangeRoad.stopPlaceName}` + + const maintenanceCount = await sequelize.query(` SELECT COUNT(id) as count FROM report WHERE report_type = 'conserve' AND road_id=${changeRoadId} `, { type: QueryTypes.SELECT }) - await models.RoadSpotCheck.update({ - roadId: changeRoadId, - maintenanceCount: maintenanceCount[0].count - }, { - where: { - roadId: originRoadId, - prepareId: previewId - }, - transaction - }) - await models.RoadSpotCheckChangeLog.create({ - userId: ctx.fs.api.userId, - time: moment().format(), - originRoadId: originRoadId, - changeRoadId: changeRoadId, - content: content, + await models.RoadSpotCheck.update({ + roadId: changeRoadId, + maintenanceCount: maintenanceCount[0].count + }, { + where: { + roadId: originRoadId, prepareId: previewId - }, { - transaction - }) - - - await transaction.commit(); - ctx.status = 204; - } catch (error) { - await transaction.rollback(); - ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); - ctx.status = 400; - ctx.body = { - message: typeof error == 'string' ? error : undefined - } - } + }, + transaction + }) + await models.RoadSpotCheckChangeLog.create({ + userId: ctx.fs.api.userId, + time: moment().format(), + originRoadId: originRoadId, + changeRoadId: changeRoadId, + content: content, + prepareId: previewId + }, { + transaction + }) + + + await transaction.commit(); + ctx.status = 204; + } catch (error) { + await transaction.rollback(); + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { + message: typeof error == 'string' ? error : undefined + } + } } async function roadSpotChangList (ctx) { - try { - const { models } = ctx.fs.dc; - const { startTime, endTime, page, limit } = ctx.query - - let findOptPreview = { - where: { - checked: true, - }, - attributes: ['id', 'date'] - } - - if (startTime && endTime) { - findOptPreview.where = { - date: { - $between: [moment(startTime).startOf('day').format(), moment(endTime).endOf('day').format()] - } + try { + const { models } = ctx.fs.dc; + const { startTime, endTime, page, limit } = ctx.query + + let findOptPreview = { + where: { + checked: true, + }, + attributes: ['id', 'date'] + } + + if (startTime && endTime) { + findOptPreview.where = { + date: { + $between: [moment(startTime).startOf('day').format(), moment(endTime).endOf('day').format()] } - } - - let findOpt = { - order: [['id', 'DESC']], - where: { - - }, - include: [{ - model: models.RoadSpotCheckPreview, - ...findOptPreview, - required: true, - }, { - model: models.User, - attributes: ['name'] - }] - } - - if (page && limit) { - findOpt.offset = (page - 1) * limit - findOpt.limit = limit - } - - const listRes = await models.RoadSpotCheckChangeLog.findAll(findOpt) - - ctx.status = 200; - ctx.body = listRes - } catch (error) { - ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); - ctx.status = 400; - ctx.body = { - message: typeof error == 'string' ? error : undefined - } - } + } + } + + let findOpt = { + order: [['id', 'DESC']], + where: { + + }, + include: [{ + model: models.RoadSpotCheckPreview, + ...findOptPreview, + required: true, + }, { + model: models.User, + attributes: ['name'] + }] + } + + if (page && limit) { + findOpt.offset = (page - 1) * limit + findOpt.limit = limit + } + + const listRes = await models.RoadSpotCheckChangeLog.findAll(findOpt) + + ctx.status = 200; + ctx.body = listRes + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { + message: typeof error == 'string' ? error : undefined + } + } } async function exportSpotRode (ctx) { - try { - const { models } = ctx.fs.dc; - const { previewId } = ctx.query - - const previewRes = await models.RoadSpotCheckPreview.findOne({ - where: { - id: previewId - } - }) - - const listRes = await models.RoadSpotCheck.findAll({ + try { + const { models } = ctx.fs.dc; + const { previewId } = ctx.query + + const previewRes = await models.RoadSpotCheckPreview.findOne({ + where: { + id: previewId + } + }) + + const listRes = await models.RoadSpotCheck.findAll({ + where: { + prepareId: previewId + }, + include: [{ + model: models.Road, + // required: false, where: { - prepareId: previewId - }, - include: [{ - model: models.Road, - // required: false, - where: { - del: false, - } - }] - }) - - const header = [{ - key: 'level', - title: '道路类型', - }, { - key: 'routeName', - title: '路线名称', - }, { - key: 'routeCode', - title: '路线代码', - }, { - key: 'sectionNo', - title: '路段序号', - }, { - key: 'startingPlaceName', - title: '起点名称', - }, { - key: 'stopPlaceName', - title: '止点名称', - }, { - key: 'chainageMileage', - title: '里程', - }, { - key: 'maintenanceCount', - title: '养护次数(次)', - },] - - function judgeLevel (routeCode) { - if (routeCode) { - if (routeCode.startsWith('X')) { - return '县道' - } else if (routeCode.startsWith('Y')) { - return '乡道' - } else if (routeCode.startsWith('C')) { - return '村道' - } - return '' - } else { - return '' + del: false, } - } - - let exportData = listRes.map(({ dataValues: item }) => { - let road = item.road.dataValues - return { - level: - judgeLevel(road.routeCode) - , - routeName: road.routeName, - routeCode: road.routeCode, - sectionNo: road.sectionNo, - startingPlaceName: road.startingPlaceName, - stopPlaceName: road.stopPlaceName, - chainageMileage: road.chainageMileage, - maintenanceCount: item.maintenanceCount, + }] + }) + + const header = [{ + key: 'level', + title: '道路类型', + }, { + key: 'routeName', + title: '路线名称', + }, { + key: 'routeCode', + title: '路线代码', + }, { + key: 'sectionNo', + title: '路段序号', + }, { + key: 'startingPlaceName', + title: '起点名称', + }, { + key: 'stopPlaceName', + title: '止点名称', + }, { + key: 'chainageMileage', + title: '里程', + }, { + key: 'maintenanceCount', + title: '养护次数(次)', + },] + + function judgeLevel (routeCode) { + if (routeCode) { + if (routeCode.startsWith('X')) { + return '县道' + } else if (routeCode.startsWith('Y')) { + return '乡道' + } else if (routeCode.startsWith('C')) { + return '村道' } - }) - - const fileName = `${moment(previewRes.date).format('YYYY年MM月DD日HH时mm分')}道路抽查记录` + '.csv' - const filePath = await xlsxDownload.simpleExcelDown({ - data: exportData, header, fileName: fileName - }) - const fileData = fs.readFileSync(filePath); - - ctx.status = 200; - ctx.set('Content-Type', 'application/x-xls'); - ctx.set('Content-disposition', 'attachment; filename=' + encodeURI(fileName)); - ctx.body = fileData; - } catch (error) { - ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); - ctx.status = 400; - ctx.body = { - message: typeof error == 'string' ? error : undefined - } - } + return '' + } else { + return '' + } + } + + let exportData = listRes.map(({ dataValues: item }) => { + let road = item.road && item.road.dataValues || {} + return { + level: + judgeLevel(road.routeCode) + , + routeName: road.routeName, + routeCode: road.routeCode, + sectionNo: road.sectionNo, + startingPlaceName: road.startingPlaceName, + stopPlaceName: road.stopPlaceName, + chainageMileage: road.chainageMileage, + maintenanceCount: item.maintenanceCount, + } + }) + + const fileName = `${moment(previewRes.date).format('YYYY年MM月DD日HH时mm分')}道路抽查记录` + '.csv' + const filePath = await xlsxDownload.simpleExcelDown({ + data: exportData, header, fileName: fileName, gather:{data: exportData, header} + }) + const fileData = fs.readFileSync(filePath); + + + ctx.status = 200; + ctx.set('Content-Type', 'application/x-xls'); + ctx.set('Content-disposition', 'attachment; filename=' + encodeURI(fileName)); + ctx.body = fileData + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); + ctx.status = 400; + ctx.body = { + message: typeof error == 'string' ? error : undefined + } + } } module.exports = { - reportList, - reportPosition, - reportDetail, createReport, deleteReport, reportHandle, - spotPrepare, spotCheck, spotCheckDetail, - roadSpotPrepare, confirmRoadSpot, roadSpotList, roadSpotDetail, roadSpotChange, roadSpotChangList, exportSpotRode + reportList, + reportPosition, + reportDetail, createReport, deleteReport, reportHandle, + spotPrepare, spotCheck, spotCheckDetail, + roadSpotPrepare, confirmRoadSpot, roadSpotList, roadSpotDetail, roadSpotChange, roadSpotChangList, exportSpotRode }; \ No newline at end of file diff --git a/api/utils/xlsxDownload.js b/api/utils/xlsxDownload.js index a8dc0c2f..4db50d5c 100644 --- a/api/utils/xlsxDownload.js +++ b/api/utils/xlsxDownload.js @@ -6,99 +6,209 @@ const moment = require('moment') //递归创建目录 同步方法 async function makeDir (dir) { - if (!fs.existsSync(dir)) { - makeDir(path.dirname(dir)) - fs.mkdirSync(dir, function (err) { - if (err) { - throw err - } - }); - } + if (!fs.existsSync(dir)) { + makeDir(path.dirname(dir)) + fs.mkdirSync(dir, function (err) { + if (err) { + throw err + } + }); + } } -async function simpleExcelDown ({ data = [], header = [], fileName = moment().format('YYYY-MM-DD HH:mm:ss'), exp } = {}) { - const fileDirPath = path.join(__dirname, `../../downloadFiles`) - makeDir(fileDirPath) - const file = new xlsx.File(); - const sheet_1 = file.addSheet('sheet_1'); - - // header - const headerStyle = new xlsx.Style(); - headerStyle.align.h = 'center'; - headerStyle.align.v = 'center'; - headerStyle.border.right = 'thin'; - headerStyle.border.rightColor = '#000000'; - headerStyle.border.bottom = 'thin'; - headerStyle.border.bottomColor = '#000000'; - - const headerRow = sheet_1.addRow(); - const indexCell = headerRow.addCell(); - indexCell.value = '序号' - indexCell.style = headerStyle - for (let h of header) { - const cell = headerRow.addCell(); - cell.value = h.title; - cell.style = headerStyle - } - - // data - const style = new xlsx.Style(); - style.align.h = 'left'; - style.align.v = 'center'; - style.border.right = 'thin'; - style.border.rightColor = '#000000'; - style.border.bottom = 'thin'; - style.border.bottomColor = '#000000'; - for (let i = 0; i < data.length; i++) { - const row = sheet_1.addRow(); - const indexCell = row.addCell(); - indexCell.value = i + 1 - indexCell.style = headerStyle - for (let h of header) { - const cell = row.addCell(); - cell.value = data[i][h.key]; - - if (exp == 'patrol' || exp == 'maintenance') { - if (h.key == 'projectType') { - let type = data[i][h.key] - if (type == 'road') { - cell.value = '道路' - } else if (type == 'bridge') { - cell.value = '桥梁' - } else if (type == 'culvert') { - cell.value = '涵洞' - } else if (type == 'other') { - cell.value = '其他' - } - continue - } - - if (h.key == 'reportType') { - let type = data[i][h.key] - if (type == 'patrol') { - cell.value = '巡查' - } else if (type == 'conserve') { - cell.value = '养护' - } - continue - } +async function gatherSheet ({ sheet_2, data = [] }) { + + // header + const headerStyle = new xlsx.Style(); + headerStyle.align.h = 'center'; + headerStyle.align.v = 'center'; + headerStyle.border.right = 'thin'; + headerStyle.border.rightColor = '#000000'; + headerStyle.border.bottom = 'thin'; + headerStyle.border.bottomColor = '#000000'; + + const headerRow1 = sheet_2.addRow(); + const indexCell1 = headerRow1.addCell(); + indexCell1.value = '南昌县农村公路养护管理暨用地范围内环境整治提升工程 考核汇总表' + indexCell1.style = headerStyle + indexCell1.hMerge = 12 + + const headerRow2 = sheet_2.addRow(); + const indexCell2 = headerRow2.addCell(); + indexCell2.value = '责任单位' + indexCell2.style = headerStyle + indexCell2.vMerge = 1 + + + for (let h of ['县道', '', '', '', '乡道', '', '', '', '村道', '', '', '',]) { + const cell = headerRow2.addCell(); + + cell.value = h; + cell.style = headerStyle + if(h){ + cell.hMerge = 3 + + } + } + + const header = [{ + key: '', + title: '', + },{ + key: 'county', + title: '总里程', + }, { + key: 'countyParticipate', + title: '纳入考核里程', + }, { + key: 'countyPresent', + title: '本次考核里程', + }, { + key: 'county', + title: '实际抽取比原计划多', + }, { + key: 'township', + title: '总里程', + }, { + key: 'townshipParticipate', + title: '纳入考核里程', + }, { + key: 'townshipPresent', + title: '本次考核里程', + }, { + key: 'township', + title: '实际抽取比原计划多', + }, { + key: 'village', + title: '总里程', + }, { + key: 'villageParticipate', + title: '纳入考核里程', + }, { + key: 'villagePresent', + title: '本次考核里程', + }, { + key: 'village', + title: '实际抽取比原计划多', + },] + + const headerRow3 = sheet_2.addRow(); + for (let h of header) { + const cell = headerRow3.addCell(); + cell.value = h.title; + cell.style = headerStyle + } + + // data + // const style = new xlsx.Style(); + // style.align.h = 'left'; + // style.align.v = 'center'; + // style.border.right = 'thin'; + // style.border.rightColor = '#000000'; + // style.border.bottom = 'thin'; + // style.border.bottomColor = '#000000'; + // for (let i = 0; i < data.length; i++) { + // const row = sheet_2.addRow(); + // const indexCell = row.addCell(); + // indexCell.value = i + 1 + // indexCell.style = headerStyle + // for (let h of header) { + // const cell = row.addCell(); + // cell.value = data[i][h.key]; + // cell.style = style + // } + // } +} + +async function simpleExcelDown ({ data = [], header = [], fileName = moment().format('YYYY-MM-DD HH:mm:ss'), exp, gather } = {}) { + const fileDirPath = path.join(__dirname, `../../downloadFiles`) + makeDir(fileDirPath) + const file = new xlsx.File(); + const sheet_1 = file.addSheet('sheet_1'); + if (gather) { + const sheet_2 = file.addSheet('sheet_2'); + await gatherSheet({ sheet_2, ...gather }) + } + + // header + const headerStyle = new xlsx.Style(); + headerStyle.align.h = 'center'; + headerStyle.align.v = 'center'; + headerStyle.border.right = 'thin'; + headerStyle.border.rightColor = '#000000'; + headerStyle.border.bottom = 'thin'; + headerStyle.border.bottomColor = '#000000'; + + const headerRow = sheet_1.addRow(); + const indexCell = headerRow.addCell(); + indexCell.value = '序号' + indexCell.style = headerStyle + for (let h of header) { + const cell = headerRow.addCell(); + cell.value = h.title; + cell.style = headerStyle + } + + // data + const style = new xlsx.Style(); + style.align.h = 'left'; + style.align.v = 'center'; + style.border.right = 'thin'; + style.border.rightColor = '#000000'; + style.border.bottom = 'thin'; + style.border.bottomColor = '#000000'; + for (let i = 0; i < data.length; i++) { + const row = sheet_1.addRow(); + const indexCell = row.addCell(); + indexCell.value = i + 1 + indexCell.style = headerStyle + for (let h of header) { + const cell = row.addCell(); + cell.value = data[i][h.key]; + + if (exp == 'patrol' || exp == 'maintenance') { + if (h.key == 'projectType') { + let type = data[i][h.key] + if (type == 'road') { + cell.value = '道路' + } else if (type == 'bridge') { + cell.value = '桥梁' + } else if (type == 'culvert') { + cell.value = '涵洞' + } else if (type == 'other') { + cell.value = '其他' + } + continue } - cell.style = style - } - } - - const savePath = path.join(fileDirPath, fileName) - await new Promise(function (resolve, reject) { - file.saveAs() - .pipe(fs.createWriteStream(savePath)) - .on('finish', () => { - resolve() - }); - }) - return savePath + if (h.key == 'reportType') { + let type = data[i][h.key] + if (type == 'patrol') { + cell.value = '巡查' + } else if (type == 'conserve') { + cell.value = '养护' + } + continue + } + } + + cell.style = style + } + } + + const savePath = path.join(fileDirPath, fileName) + await new Promise(function (resolve, reject) { + file.saveAs() + .pipe(fs.createWriteStream(savePath)) + .on('finish', () => { + resolve() + }); + }) + return savePath } + + module.exports = { - simpleExcelDown + simpleExcelDown } \ No newline at end of file