This commit is contained in:
cracklesparkle
2025-01-30 12:36:39 +09:00
parent e6b3dc05d3
commit 0788a401ca
43 changed files with 3710 additions and 1724 deletions

98
ems/package-lock.json generated
View File

@ -19,7 +19,7 @@
"ioredis": "^5.4.1",
"md5": "^2.3.0",
"multer": "^1.4.5-lts.1",
"pg": "^8.13.0",
"pg": "^8.13.1",
"pump": "^3.0.0",
"sharp": "^0.33.5",
"tedious": "^18.6.1"
@ -31,6 +31,7 @@
"@types/md5": "^2.3.5",
"@types/multer": "^1.4.12",
"@types/node": "^22.4.1",
"@types/pg": "^8.11.10",
"@types/pump": "^1.1.3",
"@types/redis": "^4.0.11",
"nodemon": "^3.1.4",
@ -896,6 +897,74 @@
"undici-types": "~6.19.2"
}
},
"node_modules/@types/pg": {
"version": "8.11.10",
"resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.11.10.tgz",
"integrity": "sha512-LczQUW4dbOQzsH2RQ5qoeJ6qJPdrcM/DcMLoqWQkMLMsq83J5lAX3LXjdkWdpscFy67JSOWDnh7Ny/sPFykmkg==",
"dev": true,
"dependencies": {
"@types/node": "*",
"pg-protocol": "*",
"pg-types": "^4.0.1"
}
},
"node_modules/@types/pg/node_modules/pg-types": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.2.tgz",
"integrity": "sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng==",
"dev": true,
"dependencies": {
"pg-int8": "1.0.1",
"pg-numeric": "1.0.2",
"postgres-array": "~3.0.1",
"postgres-bytea": "~3.0.0",
"postgres-date": "~2.1.0",
"postgres-interval": "^3.0.0",
"postgres-range": "^1.1.1"
},
"engines": {
"node": ">=10"
}
},
"node_modules/@types/pg/node_modules/postgres-array": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz",
"integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==",
"dev": true,
"engines": {
"node": ">=12"
}
},
"node_modules/@types/pg/node_modules/postgres-bytea": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz",
"integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==",
"dev": true,
"dependencies": {
"obuf": "~1.1.2"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/@types/pg/node_modules/postgres-date": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.1.0.tgz",
"integrity": "sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==",
"dev": true,
"engines": {
"node": ">=12"
}
},
"node_modules/@types/pg/node_modules/postgres-interval": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz",
"integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==",
"dev": true,
"engines": {
"node": ">=12"
}
},
"node_modules/@types/pump": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@types/pump/-/pump-1.1.3.tgz",
@ -2454,6 +2523,12 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/obuf": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
"integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==",
"dev": true
},
"node_modules/on-finished": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
@ -2503,9 +2578,9 @@
"integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
},
"node_modules/pg": {
"version": "8.13.0",
"resolved": "https://registry.npmjs.org/pg/-/pg-8.13.0.tgz",
"integrity": "sha512-34wkUTh3SxTClfoHB3pQ7bIMvw9dpFU1audQQeZG837fmHfHpr14n/AELVDoOYVDW2h5RDWU78tFjkD+erSBsw==",
"version": "8.13.1",
"resolved": "https://registry.npmjs.org/pg/-/pg-8.13.1.tgz",
"integrity": "sha512-OUir1A0rPNZlX//c7ksiu7crsGZTKSOXJPgtNiHGIlC9H0lO+NC6ZDYksSgBYY/thSWhnSRBv8w1lieNNGATNQ==",
"dependencies": {
"pg-connection-string": "^2.7.0",
"pg-pool": "^3.7.0",
@ -2547,6 +2622,15 @@
"node": ">=4.0.0"
}
},
"node_modules/pg-numeric": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz",
"integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==",
"dev": true,
"engines": {
"node": ">=4"
}
},
"node_modules/pg-pool": {
"version": "3.7.0",
"resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.7.0.tgz",
@ -2630,6 +2714,12 @@
"node": ">=0.10.0"
}
},
"node_modules/postgres-range": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.4.tgz",
"integrity": "sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==",
"dev": true
},
"node_modules/prisma": {
"version": "5.19.1",
"resolved": "https://registry.npmjs.org/prisma/-/prisma-5.19.1.tgz",

143
ems/src/api/db/index.ts Normal file
View File

@ -0,0 +1,143 @@
import express, { Request, Response } from 'express';
import { pgQuery } from '../../utils/postgres';
const router = express.Router()
router.get('/rows/:table_name', async (req: Request, res: Response) => {
try {
const { table_name } = req.params
const { offset, limit } = req.query
const result = await pgQuery(
`
SELECT * FROM ${table_name}
OFFSET ${offset || 0} LIMIT ${limit || 10}
`
)
if (Array.isArray(result)) {
if (result.length > 0) {
res.status(200).json(result)
} else {
res.status(404).json('not found')
}
} else {
res.status(404).json('not found')
}
} catch (err) {
res.status(500)
}
})
router.get('/columns/:table_name', async (req: Request, res: Response) => {
try {
const { table_name } = req.params
const result = await pgQuery(
`
SELECT column_name, data_type
FROM information_schema.columns
WHERE table_name = '${table_name}'
`
)
if (Array.isArray(result)) {
if (result.length > 0) {
res.status(200).json(result)
} else {
res.status(404).json('not found')
}
} else {
res.status(404).json('not found')
}
} catch (err) {
res.status(500)
}
})
router.get('/tables', async (req: Request, res: Response) => {
try {
const result = await pgQuery(
`
SELECT tablename FROM pg_tables WHERE schemaname = 'public';
`
)
if (Array.isArray(result)) {
if (result.length > 0) {
res.status(200).json(result)
} else {
res.status(404).json('not found')
}
} else {
res.status(404).json('not found')
}
} catch (err) {
res.status(500)
}
})
router.get('/figures/import', async (req: Request, res: Response) => {
try {
const { entity_type } = req.params
const result = await pgQuery(
`
SELECT * FROM bounds
WHERE entity_type = $1
`,
[entity_type]
)
if (Array.isArray(result)) {
if (result.length > 0) {
const geometries = result.map((bound: { id: number, entity_id: number, entity_type: string, geometry: JSON, published_at: string, deleted_at: string | null }) => {
return {
...bound.geometry,
properties: {
id: bound.id,
entity_id: bound.entity_id,
entity_type: bound.entity_type
}
}
})
res.status(200).json(geometries)
} else {
res.status(404).json('not found')
}
} else {
res.status(404).json('not found')
}
} catch (err) {
res.status(500)
}
})
router.get('/bounds/:entity_type/:entity_id', async (req: Request, res: Response) => {
try {
const { entity_type, entity_id } = req.params
const result = await pgQuery(
`
SELECT * FROM bounds
WHERE entity_type = $1
AND entity_id = $2
`,
[entity_type, entity_id]
)
if (Array.isArray(result)) {
if (result.length > 0) {
res.status(200).json(result[0].geometry)
} else {
res.status(404).json('not found')
}
} else {
res.status(404).json('not found')
}
} catch (err) {
res.status(500)
}
})
export default router

View File

@ -171,27 +171,34 @@ router.get('/objects/list', async (req: Request, res: Response) => {
const result = await tediousQuery(
`
SELECT
tTypes.id AS id,
tTypes.name AS name,
COUNT(vObjects.type) AS count
${GeneralDB}..tTypes.id AS id,
${GeneralDB}..tTypes.name AS name,
COUNT(vo.type) AS count,
tr.r,
tr.g,
tr.b
FROM
vObjects
${GeneralDB}..vObjects vo
JOIN
tTypes ON vObjects.type = tTypes.id
${GeneralDB}..tTypes ON vo.type = ${GeneralDB}..tTypes.id
LEFT JOIN ${GisDB}..TypeRoles tr ON tr.id = ${GeneralDB}..tTypes.id
WHERE
vObjects.id_city = ${city_id} AND vObjects.year = ${year}
vo.id_city = ${city_id} AND vo.year = ${year}
AND
(
CASE
WHEN TRY_CAST(vObjects.planning AS BIT) IS NOT NULL THEN TRY_CAST(vObjects.planning AS BIT)
WHEN vObjects.planning = 'TRUE' THEN 1
WHEN vObjects.planning = 'FALSE' THEN 0
WHEN TRY_CAST(vo.planning AS BIT) IS NOT NULL THEN TRY_CAST(vo.planning AS BIT)
WHEN vo.planning = 'TRUE' THEN 1
WHEN vo.planning = 'FALSE' THEN 0
ELSE NULL
END
) = ${planning}
GROUP BY
tTypes.id,
tTypes.name;
${GeneralDB}..tTypes.id,
${GeneralDB}..tTypes.name,
tr.r,
tr.g,
tr.b;
`
)
res.status(200).json(result)

View File

@ -4,6 +4,19 @@ import { GeneralDB, GisDB } from '../../constants/db';
import { pgQuery } from '../../utils/postgres';
const router = express.Router()
router.get('/type-roles', async (req: Request, res: Response) => {
try {
const result = await tediousQuery(
`
SELECT * FROM ${GisDB}..TypeRoles;
`
)
res.status(200).json(result)
} catch (err) {
res.status(500)
}
})
router.get('/bounds/:entity_type', async (req: Request, res: Response) => {
try {
const { entity_type } = req.params

View File

@ -10,7 +10,7 @@ const router = express.Router()
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, path.join(__dirname, '..', 'public', 'temp'))
cb(null, path.join(__dirname, '..', '..', '..', 'public', 'temp'))
},
filename: function (req, file, cb) {
cb(null, Date.now() + path.extname(file.originalname))

View File

@ -1,6 +1,7 @@
import express from 'express'
import bodyParser from 'body-parser'
import cors from 'cors'
import dbRouter from './api/db'
import generalRouter from './api/general'
import gisRouter from './api/gis'
import nodesRouter from './api/nodes'
@ -17,6 +18,7 @@ app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }))
app.use('/db', dbRouter)
app.use('/general', generalRouter)
app.use('/gis', gisRouter)
app.use('/nodes', nodesRouter)