From 844086b218c963a4839a9ea2cf152dc6a74195c9 Mon Sep 17 00:00:00 2001 From: wenlele Date: Thu, 24 Aug 2023 13:44:16 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AF=AF=E5=88=A0=E7=9A=84=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/app/lib/controllers/superScreen/fire.js | 22 +- api/app/lib/middlewares/authenticator.js | 247 +++++++++--------- api/app/lib/routes/superScreen/fire.js | 3 + api/config.js | 9 + .../src/sections/fire-control/actions/fire.js | 131 +++++----- .../fire-control/components/Right-top2.js | 4 +- .../fire-control/containers/homePage.js | 8 + super-screen/client/src/utils/webapi.js | 3 +- 8 files changed, 240 insertions(+), 187 deletions(-) diff --git a/api/app/lib/controllers/superScreen/fire.js b/api/app/lib/controllers/superScreen/fire.js index 8a947f5..9a11675 100644 --- a/api/app/lib/controllers/superScreen/fire.js +++ b/api/app/lib/controllers/superScreen/fire.js @@ -229,7 +229,26 @@ function getFireTrend (opts) { } +function getSurroundingConditions (opts) { + return async function (ctx) { + try { + + const { app, yingshiTokenRes } = ctx + const { center } = ctx.query; + const res = await app.fs.baiDu.get('/traffic/v1/around', { ak: opts.baiduAK, radius: 1000, center: center }) + ctx.status = 200 + ctx.body = res.body || {} + + } catch (error) { + ctx.fs.logger.error(`path: ${ctx.path}, error: error`); + ctx.status = 400; + ctx.body = { + message: '获取南昌市道路数据失败' + } + } + } +} module.exports = { addAlarm, @@ -238,5 +257,6 @@ module.exports = { getFireDevice, getFireTrend, videoList, - getDetails + getDetails, + getSurroundingConditions } \ No newline at end of file diff --git a/api/app/lib/middlewares/authenticator.js b/api/app/lib/middlewares/authenticator.js index 4f29952..11d2978 100644 --- a/api/app/lib/middlewares/authenticator.js +++ b/api/app/lib/middlewares/authenticator.js @@ -8,42 +8,42 @@ const util = require('util'); const moment = require('moment'); class ExcludesUrls { - constructor(opts) { - this.allUrls = undefined; - this.reload(opts); - } + constructor(opts) { + this.allUrls = undefined; + this.reload(opts); + } - sanitizePath (path) { - if (!path) return '/'; - const p = '/' + path.replace(/^\/+/i, '').replace(/\/+$/, '').replace(/\/{2,}/, '/'); - return p; - } + sanitizePath (path) { + if (!path) return '/'; + const p = '/' + path.replace(/^\/+/i, '').replace(/\/+$/, '').replace(/\/{2,}/, '/'); + return p; + } - reload (opts) { - // load all url - if (!this.allUrls) { - this.allUrls = opts; - let that = this; - this.allUrls.forEach(function (url, i, arr) { - if (typeof url === "string") { - url = { p: url, o: '*' }; - arr[i] = url; - } - const keys = []; - let eachPath = url.p; - url.p = (!eachPath || eachPath === '(.*)' || util.isRegExp(eachPath)) ? eachPath : that.sanitizePath(eachPath); - url.pregexp = pathToRegexp(eachPath, keys); - }); - } - } + reload (opts) { + // load all url + if (!this.allUrls) { + this.allUrls = opts; + let that = this; + this.allUrls.forEach(function (url, i, arr) { + if (typeof url === "string") { + url = { p: url, o: '*' }; + arr[i] = url; + } + const keys = []; + let eachPath = url.p; + url.p = (!eachPath || eachPath === '(.*)' || util.isRegExp(eachPath)) ? eachPath : that.sanitizePath(eachPath); + url.pregexp = pathToRegexp(eachPath, keys); + }); + } + } - isExcluded (path, method) { - return this.allUrls.some(function (url) { - return !url.auth - && url.pregexp.test(path) - && (url.o === '*' || url.o.indexOf(method) !== -1); - }); - } + isExcluded (path, method) { + return this.allUrls.some(function (url) { + return !url.auth + && url.pregexp.test(path) + && (url.o === '*' || url.o.indexOf(method) !== -1); + }); + } } /** @@ -53,108 +53,109 @@ class ExcludesUrls { * @param {*} method 当前request的method */ let isPathExcluded = function (opts, path, method) { - let excludeAll = Boolean(opts.exclude && opts.exclude.length && opts.exclude[0] == '*'); - let excludes = null; - if (!excludeAll) { - let excludeOpts = opts.exclude || []; - excludeOpts.push({ p: '/login', o: 'POST' }); - excludeOpts.push({ p: '/logout', o: 'PUT' }); - excludeOpts.push({ p: '/water/realstate', o: 'GET' }); - excludeOpts.push({ p: '/water/emergency', o: 'GET' }); - excludeOpts.push({ p: '/videoCenter/list', o: 'GET' }); - excludeOpts.push({ p: '/trafficindex/city/details', o: 'GET' }); - excludeOpts.push({ p: '/fire/alarm', o: 'GET' }); - excludeOpts.push({ p: '/fire/alarm', o: 'POST' }); - excludeOpts.push({ p: '/fire/alarm/:id', o: 'PUT' }); - excludeOpts.push({ p: '/fire/device', o: 'GET' }); - excludeOpts.push({ p: '/fire/trend', o: 'GET' }); - excludeOpts.push({ p: '/pumpStatus/:structId', o: 'GET' }); - - excludes = new ExcludesUrls(excludeOpts); - } - let excluded = excludeAll || excludes.isExcluded(path, method); - return excluded; + let excludeAll = Boolean(opts.exclude && opts.exclude.length && opts.exclude[0] == '*'); + let excludes = null; + if (!excludeAll) { + let excludeOpts = opts.exclude || []; + excludeOpts.push({ p: '/login', o: 'POST' }); + excludeOpts.push({ p: '/logout', o: 'PUT' }); + excludeOpts.push({ p: '/water/realstate', o: 'GET' }); + excludeOpts.push({ p: '/water/emergency', o: 'GET' }); + excludeOpts.push({ p: '/videoCenter/list', o: 'GET' }); + excludeOpts.push({ p: '/trafficindex/city/details', o: 'GET' }); + excludeOpts.push({ p: '/traffic/v1/around', o: 'GET' }); + excludeOpts.push({ p: '/fire/alarm', o: 'GET' }); + excludeOpts.push({ p: '/fire/alarm', o: 'POST' }); + excludeOpts.push({ p: '/fire/alarm/:id', o: 'PUT' }); + excludeOpts.push({ p: '/fire/device', o: 'GET' }); + excludeOpts.push({ p: '/fire/trend', o: 'GET' }); + excludeOpts.push({ p: '/pumpStatus/:structId', o: 'GET' }); + + excludes = new ExcludesUrls(excludeOpts); + } + let excluded = excludeAll || excludes.isExcluded(path, method); + return excluded; }; let authorizeToken = async function (ctx, token) { - let rslt = null; - const tokenFormatRegexp = /^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$/g; - if (token && tokenFormatRegexp.test(token)) { - try { + let rslt = null; + const tokenFormatRegexp = /^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$/g; + if (token && tokenFormatRegexp.test(token)) { + try { - const authorizeRes = await ctx.fs.dc.models.UserToken.findOne({ - where: { - token: token - } - }) - const { userInfo, expired } = authorizeRes; - - if (expired && moment().valueOf() <= moment(expired).valueOf()) { - rslt = { - 'authorized': userInfo.authorized, - 'resources': (userInfo || {}).resources || [], - }; - ctx.fs.api.userId = userInfo.id; - ctx.fs.api.userInfo = userInfo; - ctx.fs.api.token = token; + const authorizeRes = await ctx.fs.dc.models.UserToken.findOne({ + where: { + token: token } - } catch (err) { - const { error } = err.response || {}; - ctx.fs.logger.log('[anxinyun]', '[AUTH] failed', (error || {}).message || `cannot GET /users/${token}`); - } - } - return rslt; + }) + const { userInfo, expired } = authorizeRes; + + if (expired && moment().valueOf() <= moment(expired).valueOf()) { + rslt = { + 'authorized': userInfo.authorized, + 'resources': (userInfo || {}).resources || [], + }; + ctx.fs.api.userId = userInfo.id; + ctx.fs.api.userInfo = userInfo; + ctx.fs.api.token = token; + } + } catch (err) { + const { error } = err.response || {}; + ctx.fs.logger.log('[anxinyun]', '[AUTH] failed', (error || {}).message || `cannot GET /users/${token}`); + } + } + return rslt; }; let isResourceAvailable = function (resources, options) { - let authCode = null; - // authorize user by authorization attribute - const { authAttr, method, path } = options; - for (let prop in authAttr) { - let keys = []; - let re = pathToRegexp(prop.replace(/\:[A-Za-z_\-]+\b/g, '(\\d+)'), keys); - if (re.test(`${method}${path}`)) { - authCode = authAttr[prop]; - break; - } - } - return !authCode || (resources || []).some(code => code === authCode); + let authCode = null; + // authorize user by authorization attribute + const { authAttr, method, path } = options; + for (let prop in authAttr) { + let keys = []; + let re = pathToRegexp(prop.replace(/\:[A-Za-z_\-]+\b/g, '(\\d+)'), keys); + if (re.test(`${method}${path}`)) { + authCode = authAttr[prop]; + break; + } + } + return !authCode || (resources || []).some(code => code === authCode); }; function factory (app, opts) { - return async function auth (ctx, next) { - const { path, method, header, query } = ctx; - ctx.fs.logger.log('[AUTH] start', path, method); - ctx.fs.api = ctx.fs.api || {}; - ctx.fs.port = opts.port; - ctx.redis = app.redis; - ctx.redisTools = app.redisTools; - let error = null; - if (path) { - if (!isPathExcluded(opts, path, method)) { - const user = await authorizeToken(ctx, header.token || query.token); - if (user && user.authorized) { - // if (!isResourceAvailable(user.resources, { authAttr: app.fs.auth.authAttr, path, method })) { - // error = { status: 403, name: 'Forbidden' } - // } else { - // error = { status: 401, name: 'Unauthorized' } - // } - } else { - error = { status: 401, name: 'Unauthorized' } - } + return async function auth (ctx, next) { + const { path, method, header, query } = ctx; + ctx.fs.logger.log('[AUTH] start', path, method); + ctx.fs.api = ctx.fs.api || {}; + ctx.fs.port = opts.port; + ctx.redis = app.redis; + ctx.redisTools = app.redisTools; + let error = null; + if (path) { + if (!isPathExcluded(opts, path, method)) { + const user = await authorizeToken(ctx, header.token || query.token); + if (user && user.authorized) { + // if (!isResourceAvailable(user.resources, { authAttr: app.fs.auth.authAttr, path, method })) { + // error = { status: 403, name: 'Forbidden' } + // } else { + // error = { status: 401, name: 'Unauthorized' } + // } + } else { + error = { status: 401, name: 'Unauthorized' } } - } else { - error = { status: 401, name: 'Unauthorized' }; - } - if (error) { - ctx.fs.logger.log('[AUTH] failed', path, method); - ctx.status = error.status; - ctx.body = error.name; - } else { - ctx.fs.logger.log('[AUTH] passed', path, method); - await next(); - } - } + } + } else { + error = { status: 401, name: 'Unauthorized' }; + } + if (error) { + ctx.fs.logger.log('[AUTH] failed', path, method); + ctx.status = error.status; + ctx.body = error.name; + } else { + ctx.fs.logger.log('[AUTH] passed', path, method); + await next(); + } + } } module.exports = factory; diff --git a/api/app/lib/routes/superScreen/fire.js b/api/app/lib/routes/superScreen/fire.js index 86ef193..63a7903 100644 --- a/api/app/lib/routes/superScreen/fire.js +++ b/api/app/lib/routes/superScreen/fire.js @@ -22,6 +22,9 @@ module.exports = function (app, router, opts, AuthCode) { app.fs.api.logAttr['GET/trafficindex/city/detailst'] = { content: '获取南昌市道路数据', visible: true }; router.get('/trafficindex/city/details', fire.getDetails(opts)); + app.fs.api.logAttr['GET/traffic/v1/around'] = { content: '获取周边路况数据失败', visible: true }; + router.get('/traffic/v1/around', fire.getSurroundingConditions(opts)); + //获取消防设备 app.fs.api.logAttr['GET/fire/device'] = { content: '获取消防设备', visible: true }; router.get('/fire/device', fire.getFireDevice(opts)); diff --git a/api/config.js b/api/config.js index aea1ab4..714d054 100644 --- a/api/config.js +++ b/api/config.js @@ -46,6 +46,9 @@ const YINGSHI_SECRET = process.env.YINGSHI_SECRET || flags.yingshiSecret; // 萤石服务的地址 const YINGSHI_URL = process.env.YINGSHI_URL || flags.yingshiUrl || 'https://open.ys7.com/api'; +const BAIDU_API = process.env.BAIDU_API || flags.baiDu || 'https://api.map.baidu.com'; +const BAIDU_AK = process.env.BAIDU_AK || flags.baiDuAk || 'AeSOcqC282tdSUVOfYxe68nEcNF1CTj7'; + if (!DB || !BACKUPS_URL || !KUBESPHERE_URL || !DATABASE_CONFIG || !WATER_URL || !WORKSAFETY_URL || !THIRD_FIRECONTROL || !AXY_API_URL || !AXY_PUMP_PROJECT) { console.log('缺少启动参数,异常退出'); args.showHelp(); @@ -73,6 +76,7 @@ const product = { dev, yingshiKey: YINGSHI_KEY, yingshiSecret: YINGSHI_SECRET, + baiduAK: BAIDU_AK, exclude: [ // "*" ], // 不做认证的路由,也可以使用 exclude: ["*"] 跳过所有路由 @@ -103,6 +107,11 @@ const product = { name: 'yingshiRequest', root: YINGSHI_URL, params: {} + }, + { + name: 'baiDu', + root: BAIDU_API, + params: {} },], } }, { diff --git a/super-screen/client/src/sections/fire-control/actions/fire.js b/super-screen/client/src/sections/fire-control/actions/fire.js index 680f0ed..e651ca6 100644 --- a/super-screen/client/src/sections/fire-control/actions/fire.js +++ b/super-screen/client/src/sections/fire-control/actions/fire.js @@ -3,86 +3,97 @@ import { basicAction } from '@peace/utils' import { ApiTable } from '$utils' -export function getFireAlarmList(query) { - return dispatch => basicAction({ - type: 'get', - dispatch: dispatch, - query: query || {}, - actionType: 'GET_FIRE_ALARM', - url: `${ApiTable.getFireAlarmList}`, - msg: { error: '获取消防告警列表失败' }, - reducer: { name: 'alarms' } - }); +export function getFireAlarmList (query) { + return dispatch => basicAction({ + type: 'get', + dispatch: dispatch, + query: query || {}, + actionType: 'GET_FIRE_ALARM', + url: `${ApiTable.getFireAlarmList}`, + msg: { error: '获取消防告警列表失败' }, + reducer: { name: 'alarms' } + }); } -export function addFireAlarm(params) { - return (dispatch) => basicAction({ - type: 'post', - data: params, - dispatch, - actionType: 'ADD_RIST_REPORT', - url: ApiTable.getFireAlarmList, - msg: { - option: '新增消防告警', - }, - }); +export function addFireAlarm (params) { + return (dispatch) => basicAction({ + type: 'post', + data: params, + dispatch, + actionType: 'ADD_RIST_REPORT', + url: ApiTable.getFireAlarmList, + msg: { + option: '新增消防告警', + }, + }); } -export function modifyFireAlarm(id, params) { - return (dispatch) => basicAction({ - type: 'put', - data: params, - dispatch, - actionType: 'MODIFY_FIRE_ALARM', - url: ApiTable.modifyFireAlarm.replace('{id}', id), - msg: { - option: '', - }, - }); +export function modifyFireAlarm (id, params) { + return (dispatch) => basicAction({ + type: 'put', + data: params, + dispatch, + actionType: 'MODIFY_FIRE_ALARM', + url: ApiTable.modifyFireAlarm.replace('{id}', id), + msg: { + option: '', + }, + }); } - export function getVideoCenterList () { return dispatch => basicAction({ - type: 'get', - dispatch: dispatch, - actionType: 'GET_VIDEO_CENTER_LIST', - url: ApiTable.videoCenterList, - msg: { error: '获取视频中心列表失败' }, - reducer: { name: 'videoCenterList' } + type: 'get', + dispatch: dispatch, + actionType: 'GET_VIDEO_CENTER_LIST', + url: ApiTable.videoCenterList, + msg: { error: '获取视频中心列表失败' }, + reducer: { name: 'videoCenterList' } }); } export function getDetails () { return dispatch => basicAction({ - type: 'get', - dispatch: dispatch, - actionType: 'GET_DETAILS', - url: ApiTable.details, - msg: { error: '获取南昌市道路数据失败' }, + type: 'get', + dispatch: dispatch, + actionType: 'GET_DETAILS', + url: ApiTable.details, + msg: { error: '获取南昌市道路数据失败' }, + // reducer: { name: 'videoCenterList' } + }); +} + +export function getSurroundingConditions (query = {}) { + return dispatch => basicAction({ + type: 'get', + dispatch: dispatch, + query: query, + actionType: 'GET_SURROUNDING_CONDITION', + url: ApiTable.surroundingConditions, + msg: { error: '获取周边路况数据失败' }, // reducer: { name: 'videoCenterList' } }); } -export function getFireDevice() { - return dispatch => basicAction({ - type: 'get', - dispatch: dispatch, - actionType: 'GET_FIRE_DEVICE', - url: `${ApiTable.getFireDevice}`, - msg: { error: '获取消防设备失败' }, - }); +export function getFireDevice () { + return dispatch => basicAction({ + type: 'get', + dispatch: dispatch, + actionType: 'GET_FIRE_DEVICE', + url: `${ApiTable.getFireDevice}`, + msg: { error: '获取消防设备失败' }, + }); } -export function getFireTrend() { - return dispatch => basicAction({ - type: 'get', - dispatch: dispatch, - actionType: 'GET_FIRE_TREND', - url: `${ApiTable.getFireTrend}`, - msg: { error: '获取火情趋势失败' }, - }); +export function getFireTrend () { + return dispatch => basicAction({ + type: 'get', + dispatch: dispatch, + actionType: 'GET_FIRE_TREND', + url: `${ApiTable.getFireTrend}`, + msg: { error: '获取火情趋势失败' }, + }); } diff --git a/super-screen/client/src/sections/fire-control/components/Right-top2.js b/super-screen/client/src/sections/fire-control/components/Right-top2.js index 7a1adc4..e4d0d89 100644 --- a/super-screen/client/src/sections/fire-control/components/Right-top2.js +++ b/super-screen/client/src/sections/fire-control/components/Right-top2.js @@ -21,9 +21,9 @@ const DataTop5 = ({ dispatch, actions, longitudeLatitude }) => { }, []) useEffect(() => { - dispatch(actions.firecontrol.getDetails()).then(res => { + dispatch(actions.firecontrol.getSurroundingConditions({ center: `${longitudeLatitude?.longitude},${longitudeLatitude?.latitude}` })).then(res => { if (res.success) { - setTraffic(res.payload.data?.data?.detail || {}); + // setTraffic(res.payload.data?.data?.detail || {}); } }) }, [longitudeLatitude]) diff --git a/super-screen/client/src/sections/fire-control/containers/homePage.js b/super-screen/client/src/sections/fire-control/containers/homePage.js index b301a25..c2e8afc 100644 --- a/super-screen/client/src/sections/fire-control/containers/homePage.js +++ b/super-screen/client/src/sections/fire-control/containers/homePage.js @@ -30,6 +30,14 @@ function homePage (props) { const [fireTrend, setFireTrend] = useState([]) const { data: emergencyList = {} } = useFsRequest({ url: 'water/emergency' }); + const endEvent = () => { + dispatch(actions.firecontrol.modifyFireAlarm( + alarmInfo?.alarmInfo?.id, { state: 2 } + )).then(res => { + setTab('overview') + }) + } + useEffect(() => { getFireData(); }, []) diff --git a/super-screen/client/src/utils/webapi.js b/super-screen/client/src/utils/webapi.js index 3243cce..a0699a2 100644 --- a/super-screen/client/src/utils/webapi.js +++ b/super-screen/client/src/utils/webapi.js @@ -139,8 +139,9 @@ export const ApiTable = { //获取摄像头数据 - videoCenterList:'videoCenter/list', + videoCenterList: 'videoCenter/list', details: '/trafficindex/city/details', + surroundingConditions: 'traffic/v1/around', getFireDevice: 'fire/device', getFireTrend: 'fire/trend',