'use strict'; const { QueryTypes } = require('sequelize'); const moment = require('moment'); const xlsxDownload = require('../../../../utils/xlsxDownload.js'); const fs = require('fs'); const data = require('../../routes/data/index.js'); 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 = ` WITH RECURSIVE sub_departments AS ( SELECT id, dependence FROM department WHERE id = ${userInfo.departmentId} UNION ALL SELECT d.id, d.dependence FROM sub_departments sd JOIN department d ON sd.id = d.dependence ) SELECT u.id FROM "user" AS u JOIN sub_departments sd ON u.department_id = sd.id 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] } } } 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 = ` 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 } } } } 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] } } } 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({ where: { id: reportId }, 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 } } } 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 } } } 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 } } } 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 } } } // 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 = ` WITH RECURSIVE sub_departments AS ( SELECT id, dependence FROM department WHERE id = ${lukyDepartment.id} UNION ALL SELECT d.id, d.dependence FROM sub_departments sd JOIN department d ON sd.id = d.dependence ) SELECT u.id FROM "user" AS u JOIN sub_departments sd ON u.department_id = sd.id 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 } } } 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 = ` WITH RECURSIVE sub_departments AS ( SELECT id, dependence FROM department WHERE id = ${prepareRes.departmentId} UNION ALL SELECT d.id, d.dependence FROM sub_departments sd JOIN department d ON sd.id = d.dependence ) SELECT u.id FROM "user" AS u JOIN sub_departments sd ON u.department_id = sd.id 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 } }) 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 }, 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 } } } 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']], 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 } } } // async function roadSpotPrepare (ctx) { // try { // const { models } = ctx.fs.dc; // const sequelize = ctx.fs.dc.orm; // const { countyPercentage } = ctx.request.body; // 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 = [-1] // 上次查得的村道id // let lastVillageIds = [] // let lastAbstractVillage = {} // let gather = [] //汇总 // if (lastSpotRes) { // lastCountyPercentage = lastSpotRes.countyPercentage // lastCountyRoadIds = lastSpotRes.countyRoadId || [] // lastAbstractVillage = lastSpotRes.lastAbstractVillage || {} // let lastCounty = await models.RoadSpotCheckPreview.findAll({ // where: { // checked: true, // id: { $lte: lastSpotRes.id } // }, // limit: 3, // order: [['date', 'DESC']], // }) // if (lastCounty) { // let countyNnmter = 0 // lastCounty.forEach(d => { // if (countyNnmter < (100 - (countyPercentage == 75 ? 50 : 25))) { // lastTownRoadIds = lastTownRoadIds.concat(d.townshipRoadId) || [] // countyNnmter += (d.countyPercentage == 75 ? 50 : 25) // } // }) // } // let lastVillage = await models.RoadSpotCheckPreview.findAll({ // where: { // checked: true, // id: { $lte: lastSpotRes.id } // }, // limit: 9, // order: [['date', 'DESC']], // }) // if (lastVillage) { // let villageNnmter = 0 // lastVillage.forEach(d => { // if (villageNnmter < (100 - (countyPercentage == 75 ? 20 : 10))) { // lastVillageRoadRoadIds = lastVillageRoadRoadIds.concat(d.villageRoadId) || [] // lastVillageIds = lastVillageIds.concat(d.villageId) || [] // villageNnmter += (d.countyPercentage == 75 ? 20 : 10) // } // }) // } // // 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 = [], spot) { // let res = await sequelize.query(` // SELECT // SUM(COALESCE(CAST(chainage_mileage AS DOUBLE PRECISION), 0)) AS total_mileage // FROM road // WHERE del = false // AND spot = ${spot} // AND ${keyMap[key]} ${otherWhere.length ? `AND ${otherWhere.join(' AND ')}` : ''} // `) // return res[0][0].total_mileage || 0 // } // 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'} ( // ${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 // let last = null // 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; // } // } // } // } // if (key == '村') { // for await (let villageId of villageIdList) { // await filterRoad([ // ...otherWhere, // `village_id=${villageId}` // ], false) // spotVillageIds.push(villageId) // last = villageId // if (accumulationMileage >= targetMileage) { // break; // } // } // if (accumulationMileage < targetMileage) { // // 还小于 说明没取够 // // await filterRoad(otherWhere, true) // for await (let villageId of villageIdList.reverse()) { // await filterRoad([ // ...otherWhere, // `village_id=${villageId}` // ], true) // spotVillageIds.push(villageId) // last = villageId // if (accumulationMileage >= targetMileage) { // break; // } // } // } // } else { // await filterRoad(otherWhere, true) // } // return [spotRoadIds, accumulationMileage, last] // } // let villageMil = 0, townMil = 0, countryMil = 0; // // 抽县 // const countryRoadTotalMileage = await getRoadTotalMileage('县', '', true) // const countryRoadHide = await getRoadTotalMileage('县', '', false) // const countryRoadNeedMileage = countryRoadTotalMileage * countyPercentage / 100 // let spotCountyRoadIdsArr = await spotRoadId('县', lastCountyRoadIds, countryRoadNeedMileage, []) // let spotCountyRoadIds = spotCountyRoadIdsArr[0] // let countryMil_ = spotCountyRoadIdsArr[1] || 0 // if (countryMil_) countryMil += countryMil_; // gather.push({ // name: '南昌县交通运输局', // county: countryRoadTotalMileage + countryRoadHide, // countyParticipate: countryRoadTotalMileage, // countyPresent: countryMil_, // countyDifferenceValue: countryMil_ - countryRoadNeedMileage // }) // let town = await models.Town.findAll() || [] // // 抽乡 // const allTownCodeRes = await sequelize.query(` // SELECT // DISTINCT township_code // FROM road // WHERE del = false // AND spot = true // AND township_code IS NOT NULL // `, { type: QueryTypes.SELECT }); // let spotTownRoadIds = [] // let spotVillageRoadIds = [] // let spotVillageIds = [] // let allTownCodeResTown = [] // let lastEndVillage = {} //获取每个乡镇最后一个被抽取的村 // for await (let t of allTownCodeRes) { // // 遍历每个乡镇并抽取 // let otherWhere = [`township_code='${t.township_code}'`] // const townRoadTotalMileage = await getRoadTotalMileage('乡', otherWhere, true) // const townRoadHide = await getRoadTotalMileage('乡', otherWhere, false) // const townRoadNeedMileage = townRoadTotalMileage * (countyPercentage == 75 ? 50 : 25) / 100 // let spotTownRoadIdsArr = await spotRoadId('乡', lastTownRoadIds, townRoadNeedMileage, otherWhere) // let spotTownRoadIds_ = spotTownRoadIdsArr[0] // let townMil_ = spotTownRoadIdsArr[1] // spotTownRoadIds = spotTownRoadIds.concat(spotTownRoadIds_) // if (townMil_) townMil += townMil_ // // 抽村 // const villageRoadTotalMileage = await getRoadTotalMileage('村', otherWhere, true) // const villageRoadTotalHide = await getRoadTotalMileage('村', otherWhere, false) // const villageRoadNeedMileage = villageRoadTotalMileage * (countyPercentage == 75 ? 20 : 10) / 100 // let spotFirstVillageId = -1 // let villageRes = [] // if (lastAbstractVillage[t.township_code]) { // } else { // // 随机选取一个不在上次查过的村 // villageRes = await sequelize.query(` // SELECT id FROM village // WHERE township_code = '${t.township_code}' // ${lastVillageIds.length ? `AND id NOT IN ( // ${lastVillageIds.map(item => `'${item}'`).join(',')},-1 // )`: ''} // ORDER BY RANDOM() // LIMIT 1 // `, { type: QueryTypes.SELECT }); // 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 (lastAbstractVillage[t.township_code]) { // spotVillageIds.push(lastAbstractVillage[t.township_code]) // spotFirstVillageId = lastAbstractVillage[t.township_code] // } else if (villageRes.length) { // spotVillageIds.push(villageRes[0].id) // spotFirstVillageId = villageRes[0].id // } else { // allTownCodeResTown.push({ // code: t.township_code, // township: townRoadTotalMileage + townRoadHide, // townshipParticipate: townRoadTotalMileage, // townshipPresent: townMil_, // townshipDifferenceValue: townMil_ - townRoadNeedMileage, // village: villageRoadTotalMileage + villageRoadTotalHide, // villageParticipate: villageRoadTotalMileage, // villagePresent: 0, // villageDifferenceValue: 0 // }) // 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 spotVillageRoadIdsArr = await spotRoadId('村', lastVillageRoadRoadIds, villageRoadNeedMileage, otherWhere, villageCheckIdList) // let spotVillageRoadIds_ = spotVillageRoadIdsArr[0] // let villageMil_ = spotVillageRoadIdsArr[1] // lastEndVillage[t.township_code] = spotVillageRoadIdsArr[2] // spotVillageRoadIds = spotVillageRoadIds.concat(spotVillageRoadIds_) // if (villageMil_) villageMil += villageMil_ // allTownCodeResTown.push({ // code: t.township_code, // township: townRoadTotalMileage + townRoadHide, // townshipParticipate: townRoadTotalMileage, // townshipPresent: townMil_, // townshipDifferenceValue: townMil_ - townRoadNeedMileage, // village: villageRoadTotalMileage + villageRoadTotalHide, // villageParticipate: villageRoadTotalMileage, // villagePresent: villageMil_, // villageDifferenceValue: villageMil_ - villageRoadNeedMileage // }) // } // for (let index = 0; index < town.length; index++) { // let d = town[index] // if (allTownCodeResTown.find(c => c.code == d.code)) { // gather.push({ ...(allTownCodeResTown.find(c => c.code == d.code) || {}), name: d.name }) // } else { // let where = [`township_code='${d.code}'`] // let township = await getRoadTotalMileage('乡', where, false) // let village = await getRoadTotalMileage('村', where, false) // gather.push({ // name: d.name, // code: d.code, // township: township, // townshipParticipate: 0, // townshipPresent: 0, // townshipDifferenceValue: 0, // village: village, // villageParticipate: 0, // villagePresent: 0, // villageDifferenceValue: 0 // }) // } // } // const previewRes = await models.RoadSpotCheckPreview.create({ // countyPercentage: countyPercentage, // date: moment().format(), // countyRoadId: spotCountyRoadIds, // townshipRoadId: spotTownRoadIds, // villageRoadId: spotVillageRoadIds, // villageId: spotVillageIds, // checked: false, // villageMil, // townMil, // countryMil, // gather, // lastAbstractVillage: lastEndVillage // }) // ctx.status = 200; // ctx.body = { // previewId: previewRes.id, // spotCountyRoadCount: spotCountyRoadIds.length, // spotTownRoadCount: spotTownRoadIds.length, // spotVillageRoadCount: spotVillageRoadIds.length, // villageMil, // townMil, // countryMil // } // } 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(` SELECT road_id, COUNT(road_id) as count FROM report WHERE road_id IN ( ${spotedRoadIds.map(item => item).join(',')} ) AND report_type = 'conserve' 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 } } } async function roadSpotList (ctx) { 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 { ...item.dataValues, spotCountyRoadCount: item.countyRoadId ? item.countyRoadId.length : 0, spotTownRoadCount: item.townshipRoadId ? item.townshipRoadId.length : 0, spotVillageRoadCount: item.villageRoadId ? item.villageRoadId.length : 0, } }) } 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({ where: { prepareId: previewId, }, include: [{ model: models.Road, where: { ...(keyword ? { routeName: { $ilike: `%${keyword}%` } } : {}), del: false, }, include: [{ model: models.Village, }] }, { model: models.RoadSpotCheckPreview, attributes: ['id'], include: [{ 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 } } } 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) const level = curChangeRoad.level; let milData = {} let differenceValue = (parseFloat(curChangeRoad.chainageMileage) - parseFloat(curOriginRoad.chainageMileage)) || 0 if (level == '县') { if (previewRes.gather) { let town = previewRes.gather['countyRoad'] if (town) { town.countyPresent = town.countyPresent + differenceValue town.countyDifferenceValue = town.countyDifferenceValue + differenceValue town.countyRoadId = [...(town.countyRoadId.filter(d => d != originRoadId) || []), changeRoadId] } } milData = { countryMil: previewRes.countryMil + differenceValue, gather: previewRes.gather } } else if (level == '乡') { let town = previewRes.gather[curOriginRoad.townshipCode] if (town) { town.townshipPresent = town.townshipPresent + differenceValue town.townshipDifferenceValue = town.townshipDifferenceValue + differenceValue town.townRoadId = [...(town.townRoadId.filter(d => d != originRoadId) || []), changeRoadId] } milData = { townMil: previewRes.townMil + differenceValue, gather: previewRes.gather } } else if (level == '村') { let town = previewRes.gather[curOriginRoad.townshipCode] if (town) { town.villagePresent = town.villagePresent + differenceValue town.villageDifferenceValue = town.villageDifferenceValue + differenceValue town.villageRoadId = [...(town.villageRoadId.filter(d => d != originRoadId) || []), changeRoadId] } milData = { villageMil: previewRes.villageMil + differenceValue, gather: previewRes.gather } } await models.RoadSpotCheckPreview.update({ ...milData }, { where: { id: previewId }, transaction }) 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, 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()] } } } 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 town (ctx) { try { const { models } = ctx.fs.dc; const { } = ctx.query let options = { where: { }, } const res = await models.Town.findAll(options) ctx.status = 200; ctx.body = res } 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, drawPeople, level, code } = ctx.request.body; //获取最新的一次 const lastSpotRes = await models.RoadSpotCheckPreview.findOne({ where: { checked: true }, order: [['date', 'DESC']], }) // 先查上次没查的范围内的 然后比较百分比 如果重叠 再查上次查过的 let keyMap = { '县': `route_code LIKE 'X%'`, '乡': `route_code LIKE 'Y%'`, '村': `route_code LIKE 'C%'` } async function getRoadTotalMileage (key, otherWhere = [], spot) { let res = await sequelize.query(` SELECT SUM(COALESCE(CAST(chainage_mileage AS DOUBLE PRECISION), 0)) AS total_mileage FROM road WHERE del = false AND spot = ${spot} AND ${keyMap[key]} ${otherWhere.length ? `AND ${otherWhere.join(' AND ')}` : ''} `) return res[0][0].total_mileage || 0 } async function getRoadSpot (key, lastRoadIds = [], inOrNot, otherWhere = []) { // if (!lastRoadIds.length && !inOrNot) { // return [] // } return await sequelize.query(` SELECT id, chainage_mileage,route_code FROM road WHERE del = false AND spot = true AND ${keyMap[key]} ${lastRoadIds.length ? `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 let last = null let spotVillageIds = [] //县道乡道随机抽取 async function extractRandomElement (arr) { if (!arr.length || accumulationMileage >= targetMileage) { return } const index = Math.floor(Math.random() * arr.length); const extracted = arr.splice(index, 1)[0]; spotRoadIds.push(extracted.id) accumulationMileage += parseFloat(extracted.chainage_mileage) if (accumulationMileage >= targetMileage) { return } else { return await extractRandomElement(arr) } } if (key == '县') { let roadUnSpotedRes = await getRoadSpot(key, lastRoadIds, false, otherWhere) || [] await extractRandomElement(roadUnSpotedRes) if (accumulationMileage < targetMileage) { // 还小于 说明没取够 let roadUnSpotedRepeatRes = await getRoadSpot(key, lastRoadIds, true, otherWhere) await extractRandomElement(roadUnSpotedRepeatRes) } } else if (key == '乡') { let roadUnSpotedRes = await getRoadSpot(key, lastRoadIds, false, otherWhere) if (code == '360121201000') { let townY002 = roadUnSpotedRes.filter(d => d.route_code.indexOf('Y002') != -1) if (townY002[0]) { spotRoadIds.push(townY002[0].id) accumulationMileage += parseFloat(townY002[0].chainage_mileage) } if (countyPercentage == 75) { if (townY002[1]) { spotRoadIds.push(townY002[1].id) accumulationMileage += parseFloat(townY002[1].chainage_mileage) } } roadUnSpotedRes = roadUnSpotedRes.filter(d => !(d.route_code.indexOf('Y002') != -1)) } if (code == '360121105000') { let townY031 = roadUnSpotedRes.filter(d => d.route_code.indexOf('Y031') != -1) let townY032 = roadUnSpotedRes.filter(d => d.route_code.indexOf('Y032') != -1) if (townY031[0]) { spotRoadIds.push(townY031[0].id) accumulationMileage += parseFloat(townY031[0].chainage_mileage) } if (townY032[0]) { spotRoadIds.push(townY032[0].id) accumulationMileage += parseFloat(townY032[0].chainage_mileage) } if (countyPercentage == 75) { if (townY031[1]) { spotRoadIds.push(townY031[1].id) accumulationMileage += parseFloat(townY031[1].chainage_mileage) } if (townY032[1]) { spotRoadIds.push(townY032[1].id) accumulationMileage += parseFloat(townY032[1].chainage_mileage) } } roadUnSpotedRes = roadUnSpotedRes.filter(d => !(d.route_code.indexOf('Y031') != -1) && !(d.route_code.indexOf('Y032') != -1)) } await extractRandomElement(roadUnSpotedRes) if (accumulationMileage < targetMileage) { // 还小于 说明没取够 let roadUnSpotedRepeatRes = await getRoadSpot(key, lastRoadIds, true, [...otherWhere, `route_code not Like 'Y032%'`, `route_code not Like 'Y002%'`, `route_code not Like 'Y031%'`]) await extractRandomElement(roadUnSpotedRepeatRes) } } else if (key == '村') { for await (let villageId of villageIdList) { let roadUnSpotedRes = await getRoadSpot(key, lastRoadIds, false, [...otherWhere, `village_id=${villageId}`]) for (let r of roadUnSpotedRes) { spotRoadIds.push(r.id) accumulationMileage += parseFloat(r.chainage_mileage) if (accumulationMileage >= targetMileage) { break; } } spotVillageIds.push(villageId) last = villageId if (accumulationMileage >= targetMileage) { break; } } if (accumulationMileage < targetMileage) { // 还小于 说明没取够 // await filterRoad(otherWhere, true) for await (let villageId of villageIdList.reverse()) { let roadUnSpotedRes = await getRoadSpot(key, lastRoadIds, true, [...otherWhere, `village_id=${villageId}`]) for (let r of roadUnSpotedRes) { spotRoadIds.push(r.id) accumulationMileage += parseFloat(r.chainage_mileage) if (accumulationMileage >= targetMileage) { break; } } spotVillageIds.push(villageId) last = villageId if (accumulationMileage >= targetMileage) { break; } } } } return [spotRoadIds, accumulationMileage, last, spotVillageIds] } async function relevance (previewId, spotedRoadIds) { const conserveCountRes = await sequelize.query(` SELECT road_id, COUNT(road_id) as count FROM report WHERE road_id IN ( ${spotedRoadIds.map(item => item).join(',')} ) AND report_type = 'conserve' 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) } let gather = {} //汇总 if (level == '县') { let lastCountyRoadIds = [] // 上次查得的县道id if (lastSpotRes) { lastCountyRoadIds = lastSpotRes.countyRoadId || [] } //抽取县道长度 let countryMil = 0; // 抽县 const countryRoadTotalMileage = await getRoadTotalMileage('县', '', true) const countryRoadHide = await getRoadTotalMileage('县', '', false) const countryRoadNeedMileage = countryRoadTotalMileage * countyPercentage / 100 let spotCountyRoadIdsArr = await spotRoadId('县', lastCountyRoadIds, countryRoadNeedMileage, []) let spotCountyRoadIds = spotCountyRoadIdsArr[0] let countryMil_ = spotCountyRoadIdsArr[1] || 0 if (countryMil_) countryMil += countryMil_; gather.countyRoad = { id: 'countyRoad', name: '南昌县交通运输局', //总里程 county: countryRoadTotalMileage + countryRoadHide, //纳入考核里程 countyParticipate: countryRoadTotalMileage, //本次考核里程 countyPresent: countryMil_, //实际抽取比原计划多 countyDifferenceValue: countryMil_ - countryRoadNeedMileage, //本次抽取的县道id countyRoadId: spotCountyRoadIds, //抽取时间 abstractTime: moment().format(), //抽取人 drawPeople } let spotCheckCreate = await models.RoadSpotCheckPreview.create({ countyPercentage: countyPercentage, date: moment().format(), countyRoadId: spotCountyRoadIds, checked: true, countryMil, gather, abstractFinish: false }) if (spotCheckCreate) { await relevance(spotCheckCreate.id, spotCountyRoadIds) } } else { if (lastSpotRes) { let lastTownRoadIds = [] // 上次查得的乡镇道id let lastVillageRoadRoadIds = [-1] // 上次查得的村道id let lastVillageIds = [] //抽到的村道id let lastAbstractVillage = {} //每个乡最后抽查的村 let gather = lastSpotRes.gather || {} //汇总 let lastCounty = await models.RoadSpotCheckPreview.findAll({ where: { checked: true, id: { $lt: lastSpotRes.id } }, limit: 9, order: [['date', 'DESC']], }) if (lastCounty) { let countyNnmter = 0 let villageNnmter = 0 lastAbstractVillage = lastCounty[0] && lastCounty[0].lastAbstractVillage || {} lastCounty.forEach(d => { if (countyNnmter < (100 - (countyPercentage == 75 ? 50 : 25))) { lastTownRoadIds = lastTownRoadIds.concat(d.townshipRoadId || []) || [] countyNnmter += (d.countyPercentage == 75 ? 50 : 25) } if (villageNnmter < (100 - (countyPercentage == 75 ? 20 : 10))) { lastVillageRoadRoadIds = lastVillageRoadRoadIds.concat(d.villageRoadId || []) || [] lastVillageIds = lastVillageIds.concat(d.villageId || []) || [] villageNnmter += (d.countyPercentage == 75 ? 20 : 10) } }) } let town = await models.Town.findAll() || [] let spotTownRoadIds = lastSpotRes.townshipRoadId || [] let townMil = lastSpotRes.townMil || 0 //已抽取的乡道公里数 // 抽乡 let otherWhere = [`township_code='${code}'`] const townRoadTotalMileage = await getRoadTotalMileage('乡', otherWhere, true) const townRoadHide = await getRoadTotalMileage('乡', otherWhere, false) const townRoadNeedMileage = townRoadTotalMileage * (countyPercentage == 75 ? 50 : 25) / 100 let spotTownRoadIdsArr = await spotRoadId('乡', lastTownRoadIds, townRoadNeedMileage, otherWhere) let spotTownRoadIds_ = spotTownRoadIdsArr[0] let townMil_ = spotTownRoadIdsArr[1] spotTownRoadIds = spotTownRoadIds.concat(spotTownRoadIds_ || []) if (townMil_) townMil += townMil_ || 0 let spotVillageRoadIds = lastSpotRes.villageRoadId || [] let spotVillageIds = lastSpotRes.villageId || [] let lastEndVillage = lastSpotRes.lastAbstractVillage || {} //获取每个乡镇最后一个被抽取的村 let villageMil = lastSpotRes.villageMil || 0 //已抽取的村道公里数 // 抽村 const villageRoadTotalMileage = await getRoadTotalMileage('村', otherWhere, true) const villageRoadTotalHide = await getRoadTotalMileage('村', otherWhere, false) const villageRoadNeedMileage = villageRoadTotalMileage * (countyPercentage == 75 ? 20 : 10) / 100 let spotFirstVillageId = -1 let villageRes = [] //获取该抽取的村的id if (lastAbstractVillage[code]) { } else { // 随机选取一个不在上次查过的村 villageRes = await sequelize.query(` SELECT id FROM village WHERE township_code = '${code}' ${lastVillageIds.length ? `AND id NOT IN ( ${lastVillageIds.map(item => `'${item}'`).join(',')},-1 )`: ''} ORDER BY RANDOM() LIMIT 1 `, { type: QueryTypes.SELECT }); if (!villageRes.length) { // 没有村了,随机选一个 villageRes = await sequelize.query(` SELECT id FROM village WHERE township_code = '${code}' ORDER BY RANDOM() LIMIT 1 `, { type: QueryTypes.SELECT }); } } if (lastAbstractVillage[code]) { // spotVillageIds.push(lastAbstractVillage[code]) spotFirstVillageId = lastAbstractVillage[code] } else if (villageRes.length) { // spotVillageIds.push(villageRes[0].id) spotFirstVillageId = villageRes[0].id } //按照与当前村距离排序获取村id 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 spotVillageRoadIdsArr = await spotRoadId('村', lastVillageRoadRoadIds, villageRoadNeedMileage, otherWhere, villageCheckIdList) let spotVillageRoadIds_ = spotVillageRoadIdsArr[0] let villageMil_ = spotVillageRoadIdsArr[1] lastEndVillage[code] = spotVillageRoadIdsArr[2] spotVillageIds = spotVillageIds.concat(spotVillageRoadIdsArr[3] || []) spotVillageRoadIds = spotVillageRoadIds.concat(spotVillageRoadIds_ || []) if (villageMil_) villageMil += villageMil_ let fidOne = town.find(d => d.code == code) gather[code] = { id: code, name: fidOne.name, //总里程 乡 township: townRoadTotalMileage + townRoadHide, //纳入考核里程 乡 townshipParticipate: townRoadNeedMileage, //本次考核里程 乡 townshipPresent: townMil_, //实际抽取比原计划多 乡 townshipDifferenceValue: townMil_ - townRoadNeedMileage, //本次抽取的乡道id townRoadId: spotTownRoadIds_, //总里程 村 village: villageRoadTotalMileage + villageRoadTotalHide, //纳入考核里程 村 villageParticipate: villageRoadNeedMileage, //本次考核里程 村 villagePresent: villageMil_, //实际抽取比原计划多 村 villageDifferenceValue: villageMil_ - villageRoadNeedMileage, //本次抽取的村道id villageRoadId: spotVillageRoadIds_, //抽取时间 abstractTime: moment().format(), //抽取人 drawPeople: drawPeople } let abstractFinish = false for (let item of town) { if (item.code != '360121205000') { abstractFinish = true if (!gather[item.code]) { abstractFinish = false break; } } } let spotCheckCreate = await models.RoadSpotCheckPreview.update({ townshipRoadId: spotTownRoadIds, villageRoadId: spotVillageRoadIds, villageId: spotVillageIds, townMil, villageMil, gather, abstractFinish: abstractFinish }, { where: { id: lastSpotRes.id } }) if (spotCheckCreate) { await relevance(lastSpotRes.id, [...spotTownRoadIds_, ...spotVillageRoadIds_]) } } } const res = await models.RoadSpotCheckPreview.findOne({ where: { checked: true }, order: [['date', 'DESC']], }) ctx.status = 200; ctx.body = res } 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, roadId, isgather, code } = ctx.query const previewRes = await models.RoadSpotCheckPreview.findOne({ where: { id: previewId } }) let lastCounty = await models.RoadSpotCheckPreview.findOne({ where: { checked: true, id: { $lt: previewId } }, limit: 1, order: [['date', 'DESC']], }) let options = { where: { prepareId: previewId }, include: [{ model: models.Road, // required: false, where: { del: false, } }] } if (roadId) { options.where.roadId = { $in: roadId.split(',') } } const listRes = await models.RoadSpotCheck.findAll(options) let town = await models.Town.findAll({}) || [] let village = await models.Village.findAll({ attributes: ['id', 'name'] }) || [] const header = [{ key: 'townshipCode', title: '所属乡镇', }, { key: 'villageId', title: '所属行政村', }, { key: 'routeName', title: '道路名称', }, { key: 'routeCode', title: '道路代码', }, { key: 'startStation', title: '起点桩号', }, { key: 'stopStation', title: '止点桩号', }, { key: 'technicalLevel', title: '技术等级', }, { key: 'pavementType', title: '路面类型', }, { key: 'pavementWidth', title: '路面宽度', }, { key: 'subgradeWidth', title: '路基宽度', }, { key: 'chainageMileage', title: '桩号里程', }, { key: 'maintenanceCount', title: '养护次数(次)', }, { key: 'remark', title: '备注', }] let exportData = listRes.map(({ dataValues: item }) => { let road = item.road && item.road.dataValues || {} return { townshipCode: (town.find(d => d.code == road.townshipCode) || {}).name || '--', villageId: (village.find(d => road.villageId == d.id) || {}).name || '--', routeName: road.routeName, routeCode: road.routeCode, startStation: road.startStation || 0, stopStation: road.stopStation || 0, technicalLevel: road.technicalLevel, pavementType: road.pavementType, pavementWidth: road.pavementWidth || 0, subgradeWidth: road.subgradeWidth || 0, chainageMileage: road.chainageMileage || 0, maintenanceCount: item.maintenanceCount, } }) let option = { where: { prepareId: lastCounty.id }, include: [{ model: models.Road, where: { del: false, } }] } if (code) { if (code == 'countyRoad') { option.where.roadId = { $in: lastCounty.nextAbstract && lastCounty.nextAbstract['county'] || [] } } else { option.where.roadId = { $in: [...(lastCounty.nextAbstract && lastCounty.nextAbstract['town'] || []), ...(lastCounty.nextAbstract && lastCounty.nextAbstract['village'] || [])] } option.include[0].where.level = { $in: ['乡', '村'] } } } else { option.where.roadId = { $in: [...(lastCounty.nextAbstract && lastCounty.nextAbstract['county'] || []), ...(lastCounty.nextAbstract && lastCounty.nextAbstract['town'] || []), ...(lastCounty.nextAbstract && lastCounty.nextAbstract['village'] || [])] } } const res = await models.RoadSpotCheck.findAll(option) || [] if (res.length) { res.forEach(({ dataValues: item }) => { let road = item.road && item.road.dataValues || {} exportData.push({ townshipCode: (town.find(d => d.code == road.townshipCode) || {}).name || '--', villageId: (village.find(d => road.villageId == d.id) || {}).name || '--', routeName: road.routeName, routeCode: road.routeCode, startStation: road.startStation || 0, stopStation: road.stopStation || 0, technicalLevel: road.technicalLevel, pavementType: road.pavementType, pavementWidth: road.pavementWidth || 0, subgradeWidth: road.subgradeWidth || 0, chainageMileage: road.chainageMileage || 0, maintenanceCount: item.maintenanceCount, remark: true }) }) } const fileName = `${moment(previewRes.date).format('YYYY年MM月DD日HH时mm分')}道路抽查记录` + '.csv' let data = { data: exportData, header, fileName: fileName } if (isgather) { let gather = [previewRes.dataValues.gather['countyRoad']] town.forEach(d => { if (d.code != '360121205000') { gather.push(previewRes.dataValues.gather[d.code] || {}) } }) data.gather = { data: gather } } const filePath = await xlsxDownload.simpleExcelDown(data) 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 } } } async function postRoadSpotNext (ctx) { try { const { models } = ctx.fs.dc; const { previewId, level, roadId } = ctx.request.body const previewRes = await models.RoadSpotCheckPreview.findOne({ where: { id: previewId } }) let nextAbstract = previewRes && previewRes.nextAbstract || {} if (level == '县') { nextAbstract.county = [...(nextAbstract.county || []), roadId] } if (level == '乡') { nextAbstract.town = [...(nextAbstract.town || []), roadId] } if (level == '村') { nextAbstract.village = [...(nextAbstract.village || []), roadId] } await models.RoadSpotCheckPreview.update({ nextAbstract }, { where: { id: previewId }, }) 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 } } } module.exports = { reportList, reportPosition, reportDetail, createReport, deleteReport, reportHandle, spotPrepare, spotCheck, spotCheckDetail, roadSpotPrepare, confirmRoadSpot, roadSpotList, roadSpotDetail, roadSpotChange, roadSpotChangList, exportSpotRode, town, postRoadSpotNext };