Browse Source

冲突解决

dev
wenlele 1 year ago
parent
commit
f67008a1a6
  1. 2
      api/app/lib/controllers/data/index.js
  2. 16
      api/app/lib/controllers/data/road.js
  3. 648
      api/app/lib/controllers/report/index.js
  4. 30
      api/app/lib/index.js
  5. 9
      api/app/lib/models/report.js
  6. 9
      api/app/lib/models/road.js
  7. 52
      api/app/lib/models/road_spot_check.js
  8. 79
      api/app/lib/models/road_spot_check_change_log.js
  9. 88
      api/app/lib/models/road_spot_check_preview.js
  10. 61
      api/app/lib/models/village.js
  11. 60
      api/app/lib/models/village_distance.js
  12. 30
      api/app/lib/routes/report/index.js
  13. 2
      api/sequelize-automate.config.js
  14. 17
      scripts/1.4.0/data/1_calc_village_distance/.vscode/launch.json
  15. 11
      scripts/1.4.0/data/1_calc_village_distance/Dockerfile
  16. 7
      scripts/1.4.0/data/1_calc_village_distance/Dockerfilenew
  17. 161
      scripts/1.4.0/data/1_calc_village_distance/index.js
  18. 17
      scripts/1.4.0/data/1_calc_village_distance/package.json
  19. 91
      scripts/1.4.0/schema/1.create_road_spot_table.sql
  20. 50
      scripts/1.4.0/schema/2.create_village_table.sql
  21. 9
      scripts/1.4.0/schema/3.update_road.sql
  22. 6
      scripts/1.4.0/schema/4.update_report.sql
  23. 3
      web/client/src/sections/quanju/containers/footer/guanli/index.js

2
api/app/lib/controllers/data/index.js

@ -101,7 +101,7 @@ async function dataExport (ctx) {
}
let header = []
console.log('tableAttributesCopy', tableAttributesCopy)
for (let k in tableAttributesCopy) {
let comment = tableAttributes[k].comment
if (k != 'id' && comment) {

16
api/app/lib/controllers/data/road.js

@ -1,7 +1,7 @@
'use strict';
const roadKeyMap = require('./road.json')
async function importIn(ctx) {
async function importIn (ctx) {
// 数据导入
try {
const models = ctx.fs.dc.models;
@ -32,16 +32,20 @@ async function importIn(ctx) {
}
}
async function get(ctx) {
async function get (ctx) {
try {
const models = ctx.fs.dc.models;
const { level, road, sectionStart, sectionEnd } = ctx.query;
const { codePrefix, level, road, sectionStart, sectionEnd } = ctx.query;
let findOption = {
where: {},
order: [['id', 'DESC']]
}
if (codePrefix) {
findOption.where.routeCode = { $like: `${codePrefix}%` }
}
if (level) {
findOption.where.level = level
}
@ -76,7 +80,7 @@ async function get(ctx) {
}
}
async function getRoadSection(ctx) {
async function getRoadSection (ctx) {
try {
const models = ctx.fs.dc.models;
const { level, road, sectionStart, sectionEnd } = ctx.query;
@ -119,7 +123,7 @@ async function getRoadSection(ctx) {
}
}
async function edit(ctx) {
async function edit (ctx) {
try {
const models = ctx.fs.dc.models;
const data = ctx.request.body;
@ -145,7 +149,7 @@ async function edit(ctx) {
}
}
async function del(ctx) {
async function del (ctx) {
try {
const models = ctx.fs.dc.models;
const { roadId } = ctx.params;

648
api/app/lib/controllers/report/index.js

@ -1,8 +1,9 @@
'use strict';
const { QueryTypes } = require('sequelize');
const moment = require('moment');
async function reportList(ctx) {
const xlsxDownload = require('../../../../utils/xlsxDownload.js');
const fs = require('fs');
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
@ -148,7 +149,7 @@ async function reportList(ctx) {
}
}
async function reportPosition(ctx) {
async function reportPosition (ctx) {
try {
const models = ctx.fs.dc.models;
const { startTime, endTime, userId, reportType } = ctx.query
@ -198,7 +199,7 @@ async function reportPosition(ctx) {
}
}
async function reportDetail(ctx) {
async function reportDetail (ctx) {
try {
const models = ctx.fs.dc.models;
const { reportId } = ctx.params
@ -220,7 +221,7 @@ async function reportDetail(ctx) {
}
}
async function reportHandle(ctx) {
async function reportHandle (ctx) {
try {
const { models } = ctx.fs.dc;
@ -250,7 +251,7 @@ async function reportHandle(ctx) {
}
}
async function createReport(ctx) {
async function createReport (ctx) {
try {
const { userId } = ctx.fs.api
const models = ctx.fs.dc.models;
@ -272,7 +273,7 @@ async function createReport(ctx) {
}
}
async function deleteReport(ctx) {
async function deleteReport (ctx) {
try {
const models = ctx.fs.dc.models;
const { reportId } = ctx.params;
@ -295,7 +296,7 @@ async function deleteReport(ctx) {
// TODO 小程序填写道路名称的时候的道路筛选 是一起都返回 还是不断传关键字搜索返回
async function spotPrepare(ctx) {
async function spotPrepare (ctx) {
try {
const { models } = ctx.fs.dc;
const sequelize = ctx.fs.dc.orm;
@ -367,7 +368,7 @@ async function spotPrepare(ctx) {
}
}
async function spotCheck(ctx) {
async function spotCheck (ctx) {
const transaction = await ctx.fs.dc.orm.transaction();
try {
const { models } = ctx.fs.dc;
@ -456,7 +457,7 @@ async function spotCheck(ctx) {
}
],
}) : []
console.log('rslt111', rslt)
await transaction.commit();
ctx.status = 200;
ctx.body = rslt
@ -469,7 +470,7 @@ async function spotCheck(ctx) {
}
}
}
async function spotCheckDetail(ctx) {
async function spotCheckDetail (ctx) {
const { models } = ctx.fs.dc
const { startTime, endTime } = ctx.query
try {
@ -508,10 +509,633 @@ async function spotCheckDetail(ctx) {
}
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 = [] // 上次查得的村道id
let lastVillageIds = []
if (lastSpotRes) {
lastCountyPercentage = lastSpotRes.countyPercentage
// 遍历 RoadSpotCheck,保存上次查询的路的id
lastCountyRoadIds = lastSpotRes.countyRoadId || []
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(`
SELECT
SUM(COALESCE(CAST(chainage_mileage AS DOUBLE PRECISION), 0)) AS total_mileage
FROM road
WHERE ${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(`
SELECT id, chainage_mileage FROM road
WHERE ${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
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)
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
WHERE 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(`
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 (villageRes.length) {
spotVillageIds.push(villageRes[0].id)
spotFirstVillageId = villageRes[0].id
} else {
continue;
}
const villageNearRes = await sequelize.query(`
SELECT id,calc_village,diatance FROM village_distance
WHERE origin_village = ${spotFirstVillageId}
ORDER BY diatance 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
}
}
}
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(item => item.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: false
}
}
if (startTime && endTime) {
findOpt.where = {
date: {
$between: [moment(startTime).startOf('day').format(), moment(endTime).endOf('day').format()]
}
}
}
const listRes = await models.RoadSpotCheckPreview.findAll({
order: [['id', 'DESC']],
where: {
checked: true,
}
})
if (page && limit) {
findOpt.offset = (page - 1) * limit
findOpt.limit = limit
}
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.villageId ? item.villageId.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 } = ctx.query
const listRes = await models.RoadSpotCheck.findAll({
where: {
prepareId: previewId
},
include: [{
model: models.Road,
// required: false,
}]
})
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] }
}
})
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,
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']
}
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 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({
where: {
prepareId: previewId
},
include: [{
model: models.Road,
// required: false,
}]
})
const header = [{
key: 'level',
title: '道路类型',
}, {
key: 'routeName',
title: '路线名称',
}, {
key: 'routeCode',
title: '路线代码',
}, {
key: 'sectionNo',
title: '路段序号',
}, {
key: 'startingPlaceName',
title: '起点名称',
}, {
key: 'stopPlaceName',
title: '止点名称',
}, {
key: '',
title: '里程',
}, {
key: '',
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 ''
}
}
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,
mileage: 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
})
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
spotPrepare, spotCheck, spotCheckDetail,
roadSpotPrepare, confirmRoadSpot, roadSpotList, roadSpotDetail, roadSpotChange, roadSpotChangList, exportSpotRode
};

30
api/app/lib/index.js

@ -30,7 +30,10 @@ module.exports.models = function (dc) { // dc = { orm: Sequelize对象, ORM: Seq
require(`./models/${filename}`)(dc)
});
const { User, Department, Report, FileType, Road, Files, FileRoad, TaskManage, UserResource, Resource, ReportSpotCheck, ReportSpotCheckPreview } = dc.models;
const {
User, Department, Report, FileType, Road, Files, FileRoad, TaskManage, UserResource, Resource, ReportSpotCheck, ReportSpotCheckPreview, RoadSpotCheck, RoadSpotCheckPreview,
Village, VillageDistance, RoadSpotCheckChangeLog
} = dc.models;
// 定义外键
User.belongsTo(Department, { foreignKey: 'departmentId', targetKey: 'id' });
Department.hasMany(User, { foreignKey: 'departmentId', sourceKey: 'id' });
@ -66,6 +69,31 @@ module.exports.models = function (dc) { // dc = { orm: Sequelize对象, ORM: Seq
ReportSpotCheck.belongsTo(ReportSpotCheckPreview, { foreignKey: 'prepareId', targetKey: 'id' });
ReportSpotCheckPreview.hasMany(ReportSpotCheck, { foreignKey: 'prepareId', sourceKey: 'id' });
//
RoadSpotCheck.belongsTo(Road, { foreignKey: 'roadId', targetKey: 'id' });
Road.hasMany(RoadSpotCheck, { foreignKey: 'roadId', sourceKey: 'id' });
RoadSpotCheck.belongsTo(RoadSpotCheckPreview, { foreignKey: 'prepareId', targetKey: 'id' });
RoadSpotCheckPreview.hasMany(RoadSpotCheck, { foreignKey: 'prepareId', sourceKey: 'id' });
RoadSpotCheckChangeLog.belongsTo(Road, { foreignKey: 'originRoadId', targetKey: 'id' });
Road.hasMany(RoadSpotCheckChangeLog, { foreignKey: 'originRoadId', sourceKey: 'id' });
RoadSpotCheckChangeLog.belongsTo(Road, { foreignKey: 'changeRoadId', targetKey: 'id' });
Road.hasMany(RoadSpotCheckChangeLog, { foreignKey: 'changeRoadId', sourceKey: 'id' });
RoadSpotCheckChangeLog.belongsTo(RoadSpotCheckPreview, { foreignKey: 'prepareId', targetKey: 'id' });
RoadSpotCheckPreview.hasMany(RoadSpotCheckChangeLog, { foreignKey: 'prepareId', sourceKey: 'id' });
RoadSpotCheckChangeLog.belongsTo(User, { foreignKey: 'userId', targetKey: 'id' });
User.hasMany(RoadSpotCheckChangeLog, { foreignKey: 'userId', sourceKey: 'id' });
VillageDistance.belongsTo(Village, { foreignKey: 'originVillage', targetKey: 'id' });
Village.hasMany(VillageDistance, { foreignKey: 'originVillage', sourceKey: 'id' });
VillageDistance.belongsTo(Village, { foreignKey: 'calcVillage', targetKey: 'id' });
Village.hasMany(VillageDistance, { foreignKey: 'calcVillage', sourceKey: 'id' });
};

9
api/app/lib/models/report.js

@ -455,6 +455,15 @@ module.exports = dc => {
field: "handle_advice",
autoIncrement: false
},
roadId: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: null,
comment: "",
primaryKey: false,
field: "road_id",
autoIncrement: false
}
}, {
tableName: "report",
comment: "",

9
api/app/lib/models/road.js

@ -775,6 +775,15 @@ module.exports = dc => {
primaryKey: false,
field: "surface_thickness",
autoIncrement: false
},
villageId: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: null,
// comment: "所属村",
primaryKey: false,
field: "village_id",
autoIncrement: false
}
}, {
tableName: "road",

52
api/app/lib/models/road_spot_check.js

@ -0,0 +1,52 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const RoadSpotCheck = sequelize.define("roadSpotCheck", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: true,
field: "id",
autoIncrement: true,
unique: "report_spot_check_v2_id_uindex"
},
roadId: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "road_id",
autoIncrement: false
},
maintenanceCount: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: null,
comment: "抽查时养护次数",
primaryKey: false,
field: "maintenance_count",
autoIncrement: false
},
prepareId: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: "抽查预览id",
primaryKey: false,
field: "prepare_id",
autoIncrement: false
}
}, {
tableName: "road_spot_check",
comment: "",
indexes: []
});
dc.models.RoadSpotCheck = RoadSpotCheck;
return RoadSpotCheck;
};

79
api/app/lib/models/road_spot_check_change_log.js

@ -0,0 +1,79 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const RoadSpotCheckChangeLog = sequelize.define("roadSpotCheckChangeLog", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: true,
field: "id",
autoIncrement: true,
unique: "road_spot_check_change_log_id_uindex"
},
userId: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: "修改者",
primaryKey: false,
field: "user_id",
autoIncrement: false
},
time: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "time",
autoIncrement: false
},
content: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: "修改内容描述",
primaryKey: false,
field: "content",
autoIncrement: false
},
originRoadId: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: "原本的道路",
primaryKey: false,
field: "origin_road_id",
autoIncrement: false
},
changeRoadId: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: "更改后的道路",
primaryKey: false,
field: "change_road_id",
autoIncrement: false
},
prepareId: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: "抽查预览id",
primaryKey: false,
field: "prepare_id",
autoIncrement: false
}
}, {
tableName: "road_spot_check_change_log",
comment: "",
indexes: []
});
dc.models.RoadSpotCheckChangeLog = RoadSpotCheckChangeLog;
return RoadSpotCheckChangeLog;
};

88
api/app/lib/models/road_spot_check_preview.js

@ -0,0 +1,88 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const RoadSpotCheckPreview = sequelize.define("roadSpotCheckPreview", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: true,
field: "id",
autoIncrement: true,
unique: "report_spot_check_preview_v2_id_uindex"
},
countyPercentage: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: "县道抽查比例",
primaryKey: false,
field: "county_percentage",
autoIncrement: false
},
date: {
type: DataTypes.DATE,
allowNull: true,
defaultValue: null,
comment: "抽取时间",
primaryKey: false,
field: "date",
autoIncrement: false
},
countyRoadId: {
type: DataTypes.ARRAY(DataTypes.INTEGER),
allowNull: true,
defaultValue: null,
comment: "抽到的县道id",
primaryKey: false,
field: "county_road_id",
autoIncrement: false
},
townshipRoadId: {
type: DataTypes.ARRAY(DataTypes.INTEGER),
allowNull: true,
defaultValue: null,
comment: "乡道id",
primaryKey: false,
field: "township_road_id",
autoIncrement: false
},
checked: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: null,
comment: "是否应用",
primaryKey: false,
field: "checked",
autoIncrement: false
},
villageRoadId: {
type: DataTypes.ARRAY(DataTypes.INTEGER),
allowNull: true,
defaultValue: null,
comment: "村道id",
primaryKey: false,
field: "village_road_id",
autoIncrement: false
},
villageId: {
type: DataTypes.ARRAY(DataTypes.INTEGER),
allowNull: true,
defaultValue: null,
comment: "抽到的村庄的id",
primaryKey: false,
field: "village_id",
autoIncrement: false
}
}, {
tableName: "road_spot_check_preview",
comment: "",
indexes: []
});
dc.models.RoadSpotCheckPreview = RoadSpotCheckPreview;
return RoadSpotCheckPreview;
};

61
api/app/lib/models/village.js

@ -0,0 +1,61 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const Village = sequelize.define("village", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: true,
field: "id",
autoIncrement: true,
unique: "village_id_uindex"
},
name: {
type: DataTypes.STRING,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: false,
field: "name",
autoIncrement: false
},
townshipCode: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
comment: "所属乡镇代码",
primaryKey: false,
field: "township_code",
autoIncrement: false
},
longitude: {
type: DataTypes.DOUBLE,
allowNull: true,
defaultValue: null,
comment: "经度",
primaryKey: false,
field: "longitude",
autoIncrement: false
},
latitude: {
type: DataTypes.DOUBLE,
allowNull: true,
defaultValue: null,
comment: "纬度",
primaryKey: false,
field: "latitude",
autoIncrement: false
}
}, {
tableName: "village",
comment: "",
indexes: []
});
dc.models.Village = Village;
return Village;
};

60
api/app/lib/models/village_distance.js

@ -0,0 +1,60 @@
/* eslint-disable*/
'use strict';
module.exports = dc => {
const DataTypes = dc.ORM;
const sequelize = dc.orm;
const VillageDistance = sequelize.define("villageDistance", {
id: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: null,
primaryKey: true,
field: "id",
autoIncrement: true,
unique: "village_distance_id_uindex"
},
originVillage: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: null,
comment: "原点村庄",
primaryKey: false,
field: "origin_village",
autoIncrement: false,
references: {
key: "id",
model: "village"
}
},
calcVillage: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: null,
comment: "相对计算村庄",
primaryKey: false,
field: "calc_village",
autoIncrement: false,
references: {
key: "id",
model: "village"
}
},
diatance: {
type: DataTypes.INTEGER,
allowNull: true,
defaultValue: null,
comment: "距离 m",
primaryKey: false,
field: "diatance",
autoIncrement: false
}
}, {
tableName: "village_distance",
comment: "",
indexes: []
});
dc.models.VillageDistance = VillageDistance;
return VillageDistance;
};

30
api/app/lib/routes/report/index.js

@ -23,14 +23,36 @@ module.exports = function (app, router, opts) {
router.del('/report/:reportId', report.deleteReport);
app.fs.api.logAttr['get/allDepUsers'] = { content: '查询所有部门的员工', visible: false };
router.get('allDepUsers', Department.getDepUsers);
router.get('/allDepUsers', Department.getDepUsers);
app.fs.api.logAttr['POST/report/spot/prepare'] = { content: '抽查预览', visible: false };
router.post('report/spot/prepare', report.spotPrepare);
router.post('/report/spot/prepare', report.spotPrepare);
app.fs.api.logAttr['GET/report/spot/check'] = { content: '抽查', visible: false };
router.get('report/spot/check', report.spotCheck)
router.get('/report/spot/check', report.spotCheck)
app.fs.api.logAttr['GET/report/spot/check/detail'] = { content: '抽查明细', visible: false };
router.get('report/spot/check/detail', report.spotCheckDetail)
router.get('/report/spot/check/detail', report.spotCheckDetail)
//v2
app.fs.api.logAttr['POST/road/spot/prepare'] = { content: '抽查预览V2', visible: false };
router.post('/road/spot/prepare', report.roadSpotPrepare);
app.fs.api.logAttr['POST/road/spot/confirm'] = { content: '确认抽查', visible: false };
router.post('/road/spot/confirm', report.confirmRoadSpot)
app.fs.api.logAttr['GET/road/spot/list'] = { content: '抽查列表', visible: false };
router.get('/road/spot/list', report.roadSpotList)
app.fs.api.logAttr['GET/road/spot/detail'] = { content: '抽查详情', visible: false };
router.get('/road/spot/detail', report.roadSpotDetail)
app.fs.api.logAttr['POST/road/spot/change'] = { content: '更改抽查路线', visible: false };
router.post('/road/spot/change', report.roadSpotChange)
app.fs.api.logAttr['GET/road/spot/change'] = { content: '抽查路线更改列表', visible: false };
router.get('/road/spot/change', report.roadSpotChangList)
app.fs.api.logAttr['GET/road/spot/export'] = { content: '导出路线抽查', visible: false };
router.get('/road/spot/export', report.exportSpotRode)
}

2
api/sequelize-automate.config.js

@ -35,7 +35,7 @@ module.exports = {
dir: './app/lib/models', // 指定输出 models 文件的目录
typesDir: 'models', // 指定输出 TypeScript 类型定义的文件目录,只有 TypeScript / Midway 等会有类型定义
emptyDir: false, // !!! 谨慎操作 生成 models 之前是否清空 `dir` 以及 `typesDir`
tables: ['reportxxx'], // 指定生成哪些表的 models,如 ['user', 'user_post'];如果为 null,则忽略改属性
tables: ['road_spot_check_preview'], // 指定生成哪些表的 models,如 ['user', 'user_post'];如果为 null,则忽略改属性
skipTables: [], // 指定跳过哪些表的 models,如 ['user'];如果为 null,则忽略改属性
tsNoCheck: false, // 是否添加 `@ts-nocheck` 注释到 models 文件中
ignorePrefix: [], // 生成的模型名称忽略的前缀,因为 项目中有以下表名是以 t_ 开头的,在实际模型中不需要, 可以添加多个 [ 't_data_', 't_',] ,长度较长的 前缀放前面

17
scripts/1.4.0/data/1_calc_village_distance/.vscode/launch.json

@ -0,0 +1,17 @@
{
// 使 IntelliSense
//
// 访: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "启动程序",
"skipFiles": [
"<node_internals>/**"
],
"program": "${workspaceFolder}\\index.js"
}
]
}

11
scripts/1.4.0/data/1_calc_village_distance/Dockerfile

@ -0,0 +1,11 @@
FROM repository.anxinyun.cn/base-images/nodejs12:20.10.12.2
COPY . /var/app
WORKDIR /var/app
RUN npm cache clean -f
RUN rm -rf package-lock.json
RUN npm install --registry http://10.8.30.22:7000
CMD ["node", "index.js"]

7
scripts/1.4.0/data/1_calc_village_distance/Dockerfilenew

@ -0,0 +1,7 @@
FROM repository.anxinyun.cn/base-images/nodejs12:20.10.12.2
COPY ./scripts/1.3.1/data/1_insert_report_data /var/app
WORKDIR /var/app
RUN npm cache clean -f
RUN rm -rf package-lock.json
RUN npm install --registry https://nexus.ngaiot.com/repository/fs-npm/
CMD ["node", "index.js"]

161
scripts/1.4.0/data/1_calc_village_distance/index.js

@ -0,0 +1,161 @@
try {
const { Pool, Client } = require('pg')
const request = require('superagent')
const path = require('path')
const fs = require("fs");
const pool = new Pool({
host: '10.8.30.32',
port: 5432,
user: 'postgres',
password: '123',
database: 'highways4good',
})
function getDistance (lat1, lon1, lat2, lon2) {
var R = 6371000; // 半径 of the earth in meters
var dLat = deg2rad(lat2 - lat1); // deg2rad below
var dLon = deg2rad(lon2 - lon1);
var a =
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) *
Math.sin(dLon / 2) * Math.sin(dLon / 2)
;
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = R * c; // Distance in meters
return d;
}
function deg2rad (deg) {
return deg * (Math.PI / 180)
}
// 两个经纬度
let coord1 = { latitude: 31.2304, longitude: 121.4737 }; // 上海
let coord2 = { latitude: 30.5685, longitude: 114.3055 }; // 武汉
// let distance = getDistance(coord1.latitude, coord1.longitude, coord2.latitude, coord2.longitude);
const fun = async () => {
// note: we don't try/catch this because if connecting throws an exception
// we don't need to dispose of the client (it will be undefined)
const client = await pool.connect()
try {
await client.query('BEGIN')
console.log(`开始`);
// 遍历南昌县所有村
let pageNum = 1
let continueSearch = true
for (; continueSearch;) {
console.log(`查询第${pageNum}`);
const res = await request.get(`https://restapi.amap.com/v5/place/text?key=21c2d970e1646bb9a795900dd00093ce&keywords=%E6%9D%91%E5%A7%94%E4%BC%9A%7C%E6%9D%91%E6%B0%91%E5%A7%94%E5%91%98%E4%BC%9A&types=130106&region=360121&citylimit=true&page_size=25&page_num=${pageNum}&extensions=all`)
// console.log(res.body);
const data = res.body
console.log(`查得 ${data.pois.length}`);
if (data.count == 0) {
continueSearch = false
break;
} else {
pageNum++
}
for await (let p of data.pois) {
if (p.name.includes('村委会') || p.name.includes('村民委员会')) {
let vName = p.name.replace('村委会', '').replace('村民委员会', '').replace(/\(.*?\)/g, '')
if (vName.includes('乡')) {
let townKeyIndex = vName.indexOf('乡')
if (townKeyIndex >= 0) {
vName = vName.substring(townKeyIndex + 1)
}
}
if (vName.includes('镇')) {
let townKeyIndex = vName.indexOf('镇')
if (townKeyIndex >= 0) {
vName = vName.substring(townKeyIndex + 1)
}
}
if (!vName.endsWith('村')) {
vName = vName + '村'
}
console.log(`${vName}`);
let locationArr = p.location.split(',')
// 查询镇名是否存在
const existRes = await client.query(
`SELECT * FROM village WHERE name=$1`,
[vName]
)
if (existRes.rowCount == 0) {
} else {
let existV = existRes[0]
await client.query(
`UPDATE village SET longitude=$1, latitude=$2 WHERE id=$3`,
[locationArr[0], locationArr[1], existV.id]
)
}
}
}
}
const allVillagesRes = await client.query(
`SELECT * FROM village`
)
const allVillages = allVillagesRes.rows
for (let v of allVillages) {
if (!v.longitude || !v.latitude) {
continue
}
for (let vv of allVillages) {
if (
v.id != vv.id
// 只计算一个乡镇内的村
&& v.township_code == vv.township_code
) {
if (!vv.longitude || !vv.latitude) {
continue
}
let distance = getDistance(v.latitude, v.longitude, vv.latitude, vv.longitude)
console.log(`${v.name}${vv.name} 的距离为 ${distance}`);
distance = Math.round(distance)
const existRes = await client.query(
`SELECT * FROM village_distance WHERE origin_village=$1 AND calc_village=$2`,
[v.id, vv.id]
)
if (existRes.rowCount == 0) {
await client.query(
`INSERT INTO village_distance (origin_village, calc_village, distance) VALUES ($1, $2, $3)`,
[v.id, vv.id, distance]
)
} else {
await client.query(
`UPDATE village_distance SET distance=$1 WHERE origin_village=$2 AND calc_village=$`
, [distance, v.id, vv.id]
)
}
}
}
}
// await client.query('ROLLBACK')
await client.query('COMMIT')
console.log('执行完毕~')
} catch (e) {
await client.query('ROLLBACK')
console.log('执行错误~')
throw e
} finally {
client.release();
}
}
fun()
} catch (error) {
console.error(error)
}

17
scripts/1.4.0/data/1_calc_village_distance/package.json

@ -0,0 +1,17 @@
{
"name": "appkey-generator",
"version": "1.0.0",
"description": "tool",
"main": "index.js",
"scripts": {
"test": "mocha",
"start": "set NODE_ENV=development&&node index"
},
"author": "liu",
"license": "ISC",
"dependencies": {
"crypto-js": "^4.1.1",
"pg": "^7.18.2",
"superagent": "^8.1.2"
}
}

91
scripts/1.4.0/schema/1.create_road_spot_table.sql

@ -0,0 +1,91 @@
create table if not exists road_spot_check_preview
(
id serial not null
constraint report_spot_check_preview_v2_pk
primary key,
county_percentage integer not null,
date timestamp with time zone,
county_road_id integer[],
township_road_id integer[],
checked boolean default false not null,
village_road_id integer[],
village_id integer[]
);
comment on table road_spot_check_preview is '道路抽查预览表';
comment on column road_spot_check_preview.county_percentage is '县道抽查比例';
comment on column road_spot_check_preview.date is '抽取时间';
comment on column road_spot_check_preview.county_road_id is '抽到的县道id';
comment on column road_spot_check_preview.township_road_id is '乡道id';
comment on column road_spot_check_preview.checked is '是否应用';
comment on column road_spot_check_preview.village_road_id is '村道id';
comment on column road_spot_check_preview.village_id is '抽到的村庄的id';
create unique index if not exists report_spot_check_preview_v2_id_uindex
on road_spot_check_preview (id);
create table if not exists road_spot_check
(
id serial not null
constraint report_spot_check_v2_pk
primary key,
road_id integer not null,
maintenance_count integer,
prepare_id integer not null
);
comment on table road_spot_check is '抽查结果表';
comment on column road_spot_check.maintenance_count is '抽查时养护次数';
comment on column road_spot_check.prepare_id is '抽查预览id';
create unique index if not exists report_spot_check_v2_id_uindex
on road_spot_check (id);
create table if not exists road_spot_check_change_log
(
id serial not null
constraint road_spot_check_change_log_pk
primary key,
user_id integer not null,
time timestamp with time zone not null,
content varchar(1024),
origin_road_id integer not null,
change_road_id integer not null,
prepare_id integer
constraint road_spot_check_change_log_road_spot_check_preview_id_fk
references road_spot_check_preview
);
comment on table road_spot_check_change_log is '道路养护抽查调整日志';
comment on column road_spot_check_change_log.user_id is '修改者';
comment on column road_spot_check_change_log.content is '修改内容描述';
comment on column road_spot_check_change_log.origin_road_id is '原本的道路';
comment on column road_spot_check_change_log.change_road_id is '更改后的道路';
comment on column road_spot_check_change_log.prepare_id is '抽查预览id';
create unique index if not exists road_spot_check_change_log_id_uindex
on road_spot_check_change_log (id);

50
scripts/1.4.0/schema/2.create_village_table.sql

@ -0,0 +1,50 @@
create table if not exists village
(
id serial not null
constraint village_pk
primary key,
name varchar(256) not null,
township_code varchar(256),
longitude double precision,
latitude double precision
);
comment on table village is '';
comment on column village.township_code is '所属乡镇代码';
comment on column village.longitude is '经度';
comment on column village.latitude is '纬度';
create unique index if not exists village_id_uindex
on village (id);
create table if not exists village_distance
(
id serial not null
constraint village_distance_pk
primary key,
origin_village integer not null
constraint village_distance_village_id_fk
references village,
calc_village integer
constraint village_distance_village_id_fk_2
references village,
diatance integer
);
comment on table village_distance is '村之间的距离';
comment on column village_distance.origin_village is '原点村庄';
comment on column village_distance.calc_village is '相对计算村庄';
comment on column village_distance.diatance is '距离 m';
create unique index if not exists village_distance_id_uindex
on village_distance (id);

9
scripts/1.4.0/schema/3.update_road.sql

@ -0,0 +1,9 @@
alter table road
add village_id int;
comment on column road.village_id is '所属村';
alter table road
add constraint road_village_id_fk
foreign key (village_id) references village;

6
scripts/1.4.0/schema/4.update_report.sql

@ -0,0 +1,6 @@
alter table report
add road_id int;
alter table report
add constraint report_road_id_fk
foreign key (road_id) references road;

3
web/client/src/sections/quanju/containers/footer/guanli/index.js

@ -180,6 +180,7 @@ const Guanli = (props) => {
)
})
const renderLeftContent = () => {
// setleftDatas(leftDatas=>leftDatas.sort((a,b)=>b.total - a.total))
@ -242,7 +243,7 @@ const Guanli = (props) => {
</>
)
}
function mapStateToProps(state) {
function mapStateToProps (state) {
const { auth, depMessage, global } = state;
const pakData = (dep) => {
return dep.map((d) => {

Loading…
Cancel
Save