Browse Source

水务数据接入

master
liujiangyong 2 years ago
parent
commit
707b070d5c
  1. 12
      api/app/lib/middlewares/proxy.js
  2. 12
      api/config.js
  3. 2
      api/package.json
  4. BIN
      super-screen/client/assets/images/weather/baoxue.png
  5. BIN
      super-screen/client/assets/images/weather/dayu.png
  6. BIN
      super-screen/client/assets/images/weather/duoyun.png
  7. BIN
      super-screen/client/assets/images/weather/fucheng.png
  8. BIN
      super-screen/client/assets/images/weather/leizhengyu.png
  9. BIN
      super-screen/client/assets/images/weather/mai.png
  10. BIN
      super-screen/client/assets/images/weather/qiangshachengbao.png
  11. BIN
      super-screen/client/assets/images/weather/qing.png
  12. BIN
      super-screen/client/assets/images/weather/shachengbao.png
  13. BIN
      super-screen/client/assets/images/weather/tedabaoyu.png
  14. BIN
      super-screen/client/assets/images/weather/weizhi.png
  15. BIN
      super-screen/client/assets/images/weather/wu.png
  16. BIN
      super-screen/client/assets/images/weather/xiaoxue.png
  17. BIN
      super-screen/client/assets/images/weather/xiaoyu.png
  18. BIN
      super-screen/client/assets/images/weather/yangsha.png
  19. BIN
      super-screen/client/assets/images/weather/yingtian.png
  20. BIN
      super-screen/client/assets/images/weather/yujiaxue.png
  21. BIN
      super-screen/client/assets/images/weather/zhenyu.png
  22. BIN
      super-screen/client/assets/images/weather/zhongxue.png
  23. BIN
      super-screen/client/assets/images/weather/zhongyu.png
  24. 6
      super-screen/client/src/sections/community-safty/components/style.less
  25. 4
      super-screen/client/src/sections/water-prevention/actions/index.js
  26. 83
      super-screen/client/src/sections/water-prevention/actions/waterconservancy.js
  27. 70
      super-screen/client/src/sections/water-prevention/actions/worksafety.js
  28. 69
      super-screen/client/src/sections/water-prevention/components/emergency-left-bottom.js
  29. 15
      super-screen/client/src/sections/water-prevention/components/emergency-right-top.js
  30. 12
      super-screen/client/src/sections/water-prevention/components/left-bottom.js
  31. 60
      super-screen/client/src/sections/water-prevention/components/right-bottom.js
  32. 16
      super-screen/client/src/sections/water-prevention/components/right-top.js
  33. 25
      super-screen/client/src/sections/water-prevention/components/style.less
  34. 145
      super-screen/client/src/sections/water-prevention/components/weather.js
  35. 22
      super-screen/client/src/sections/water-prevention/constants/water.js
  36. 94
      super-screen/client/src/sections/water-prevention/containers/gis.js
  37. 40
      super-screen/client/src/sections/water-prevention/containers/gis.less
  38. 150
      super-screen/client/src/sections/water-prevention/containers/homePage.js
  39. 15
      super-screen/client/src/utils/webapi.js
  40. 4
      super-screen/config.js
  41. 2
      super-screen/package.json
  42. 55
      super-screen/routes/weather/index.js

12
api/app/lib/middlewares/proxy.js

@ -0,0 +1,12 @@
const proxy = require('koa-proxy');
module.exports.entry = function (app, router, opts) {
app.use(proxy({
host: opts.host,
match: opts.match,
map: function (path) {
return path.replace(opts.match, '');
},
suppressRequestHeaders: ['content-length'],
}))
}

12
api/config.js

@ -78,6 +78,18 @@ const product = {
dbConfig: DATABASE_CONFIG,
}
}, {
entry: require('./app/lib/middlewares/proxy').entry,
opts: {
host: 'https://waterconservancy.anxinyun.cn',
match: /\/_water\//,
}
}, {
entry: require('./app/lib/middlewares/proxy').entry,
opts: {
host: 'https://smartworksafety.anxinyun.cn',
match: /\/_worksafety\//,
}
}
],
dc: {

2
api/package.json

@ -27,7 +27,7 @@
"jszip": "^3.10.1",
"kafka-node": "^2.2.3",
"koa-convert": "^1.2.0",
"koa-proxy": "^0.9.0",
"koa-proxy": "^1.0.0-alpha.3",
"moment": "^2.24.0",
"mqtt": "^4.3.7",
"node-schedule": "^2.1.0",

BIN
super-screen/client/assets/images/weather/baoxue.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
super-screen/client/assets/images/weather/dayu.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
super-screen/client/assets/images/weather/duoyun.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
super-screen/client/assets/images/weather/fucheng.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
super-screen/client/assets/images/weather/leizhengyu.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
super-screen/client/assets/images/weather/mai.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
super-screen/client/assets/images/weather/qiangshachengbao.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
super-screen/client/assets/images/weather/qing.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
super-screen/client/assets/images/weather/shachengbao.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
super-screen/client/assets/images/weather/tedabaoyu.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
super-screen/client/assets/images/weather/weizhi.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
super-screen/client/assets/images/weather/wu.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 665 B

BIN
super-screen/client/assets/images/weather/xiaoxue.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
super-screen/client/assets/images/weather/xiaoyu.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
super-screen/client/assets/images/weather/yangsha.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
super-screen/client/assets/images/weather/yingtian.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
super-screen/client/assets/images/weather/yujiaxue.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
super-screen/client/assets/images/weather/zhenyu.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
super-screen/client/assets/images/weather/zhongxue.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
super-screen/client/assets/images/weather/zhongyu.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

6
super-screen/client/src/sections/community-safty/components/style.less

@ -456,7 +456,7 @@
background-size: 100% 100%;
margin-bottom: 7px;
padding-left: 7px;
padding-right: 16px;
padding-right: 6px;
.alarm_title1 {
float: left;
@ -466,6 +466,10 @@
font-size: 16px;
color: #FFFFFF;
letter-spacing: 0;
width: 75%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.alarm_title2 {

4
super-screen/client/src/sections/water-prevention/actions/index.js

@ -1,7 +1,11 @@
'use strict';
import * as example from './example'
import * as waterconservancy from './waterconservancy'
import * as worksafety from './worksafety'
export default {
...example,
...waterconservancy,
...worksafety,
}

83
super-screen/client/src/sections/water-prevention/actions/waterconservancy.js

@ -0,0 +1,83 @@
'use strict';
import { basicAction } from '@peace/utils'
import { ApiTable } from '$utils'
export function getPcode(orgId) {
return dispatch => basicAction({
type: 'get',
dispatch: dispatch,
actionType: 'GET_PCODE',
url: `${ApiTable.getPcode}`,
msg: { error: '获取水环境pcode失败' },
});
}
export function waterLogin(data) {
return dispatch => basicAction({
type: 'post',
data,
dispatch: dispatch,
actionType: 'POST_WATER_LOGIN',
url: `${ApiTable.waterLogin}`,
msg: { error: '登录水环境失败' },
// reducer: { name: 'members' }
});
}
export function getWaterLevelTrend(query) {
return dispatch => basicAction({
type: 'get',
query,
dispatch: dispatch,
actionType: 'GET_WATER_LEVEL_TREND',
url: `${ApiTable.getWaterLevelTrend}`,
msg: { error: '获取水位趋势失败' },
});
}
export function getWaterStructures(query) {
return dispatch => basicAction({
type: 'get',
query,
dispatch: dispatch,
actionType: 'GET_WATER_STRUCTURES',
url: `${ApiTable.getWaterStructures}`,
msg: { error: '获取水务结构物失败' },
});
}
export function getWaterVideoList(struIds, query) {
return dispatch => basicAction({
type: 'get',
query,
dispatch: dispatch,
actionType: 'GET_WATER_VIDEO_LIST',
url: `${ApiTable.getWaterVideoList.replace('{struIds}', struIds)}`,
msg: { error: '获取水务视频失败' },
});
}
export function getYsAccessToken(query) {
return dispatch => basicAction({
type: 'get',
query,
dispatch: dispatch,
actionType: 'GET_YS_ACCESS_TOKEN',
url: `${ApiTable.getYsAccessToken}`,
msg: { error: '获取萤石授权失败' },
});
}
export function getWaterAlarms(query) {
return dispatch => basicAction({
type: 'post',
query,
// data: { "keywords": "", "status": "new", "levels": [1, 2, 3], "orderBy": "endTime", "orderDirection": "desc", "limit": 10, "offset": 0, "structures": null, "types": [1] },
data: { "structures": null, "orderBy": "endTime", "endTime": "2022-06-30 23:59:59", "keywords": "", "levels": [1, 2, 3], "startTime": "2022-06-01 00:00:00", "orderDirection": "desc", "status": "history", "offset": 0, "types": [1], "limit": 10 },
dispatch: dispatch,
actionType: 'GET_WATER_ALARMS',
url: `${ApiTable.getWaterAlarms}`,
msg: { error: '获取告警失败' },
});
}

70
super-screen/client/src/sections/water-prevention/actions/worksafety.js

@ -0,0 +1,70 @@
'use strict';
import { basicAction } from '@peace/utils'
import { ApiTable } from '$utils'
export function worksafetyLogin(data) {
return dispatch => basicAction({
type: 'post',
data,
dispatch: dispatch,
actionType: 'POST_WORKSAFETY_LOGIN',
url: `${ApiTable.worksafetyLogin}`,
msg: { error: '登录安监失败' },
});
}
export function getEmerOrgList(query) {
return dispatch => basicAction({
type: 'get',
query,
dispatch: dispatch,
actionType: 'GET_EMER_ORG_LIST',
url: `${ApiTable.getEmerOrgList}`,
msg: { error: '登录应急机构失败' },
});
}
export function getEmerTeamList(query) {
return dispatch => basicAction({
type: 'get',
query,
dispatch: dispatch,
actionType: 'GET_EMER_TEAM_LIST',
url: `${ApiTable.getEmerTeamList}`,
msg: { error: '登录应急队伍失败' },
});
}
export function getEmerExpertList(query) {
return dispatch => basicAction({
type: 'get',
query,
dispatch: dispatch,
actionType: 'GET_EMER_EXPERT_LIST',
url: `${ApiTable.getEmerExpertList}`,
msg: { error: '登录应急专家失败' },
});
}
export function getEmerMedicalList(query) {
return dispatch => basicAction({
type: 'get',
query,
dispatch: dispatch,
actionType: 'GET_EMER_MEDICAL_LIST',
url: `${ApiTable.getEmerMedicalList}`,
msg: { error: '登录医疗机构失败' },
});
}
export function getEmerRefugeList(query) {
return dispatch => basicAction({
type: 'get',
query,
dispatch: dispatch,
actionType: 'GET_EMER_REFUGE_LIST',
url: `${ApiTable.getEmerRefugeList}`,
msg: { error: '登录避难场所失败' },
});
}

69
super-screen/client/src/sections/water-prevention/components/emergency-left-bottom.js

@ -1,55 +1,42 @@
import React from 'react'
import { Box } from '$components';
import { Tooltip } from 'antd';
function Infrastructure(props) {
const { waterLevelAlarms } = props;
return <Box title={"预警统计"} >
<div className='_city_safty'>
<div className='alarm_handle'>
<div className='handle_img' />
<div className='alarm_content'>
<div className='alarm_bg'>
<div className='alarm_title1'>2023-06-20 170000</div>
<div className='alarm_title2' style={{ color: '#FFEA00' }}>二级预警</div>
</div>
<div className='alarm_text'>萌萌小区25栋305等等等等等发生等等火灾扥大哥大呢个</div>
</div>
</div>
<div className='alarm_unhandle'>
<div className='handle_img' />
<div className='alarm_content'>
<div className='alarm_bg'>
<div className='alarm_title1'>2023-06-20 170000</div>
<div className='alarm_title2' style={{ color: '#FF2C2C' }}>一级预警</div>
</div>
<div className='alarm_text'>萌萌小区25栋305等等等等等发生等等火灾扥大哥大呢个</div>
</div>
</div>
<div className='alarm_unhandle'>
<div className='handle_img' />
<div className='alarm_content'>
<div className='alarm_bg'>
<div className='alarm_title1'>2023-06-20 170000</div>
<div className='alarm_title2' style={{ color: '#FF2C2C' }}>二级预警</div>
{
// alarm_unhandle FF2C2C alarm_handle FFEA00
waterLevelAlarms.map(a => <div className={a.alarms[0]?.state >= 3 ? 'alarm_handle' : 'alarm_unhandle'}>
<div className='handle_img' />
<div className='alarm_content'>
<div className='alarm_bg'>
<Tooltip title={a.alarms[0]?.source?.name}>
<div className='alarm_title1'>{a.alarms[0]?.source?.name}</div>
</Tooltip>
<div className='alarm_title2' style={{ color: a.alarms[0]?.state >= 3 ? '#FFEA00' : '#FF2C2C' }}>{convertLevelToLabel(a.alarms[0]?.level)}</div>
</div>
<div className='alarm_text'>{a.alarms[0]?.content}</div>
</div>
<div className='alarm_text'>萌萌小区25栋305等等等等等发生等等火灾扥大哥大呢个</div>
</div>
</div>
<div className='alarm_unhandle'>
<div className='handle_img' />
<div className='alarm_content'>
<div className='alarm_bg'>
<div className='alarm_title1'>2023-06-20 170000</div>
<div className='alarm_title2' style={{ color: '#FF2C2C' }}>二级预警</div>
</div>
<div className='alarm_text'>萌萌小区25栋305等等等等等发生等等火灾扥大哥大呢个</div>
</div>
</div>
</div>)
}
</div>
</Box>
}
export default Infrastructure;
function convertLevelToLabel(level) {
switch (level) {
case 1:
return '一级预警';
case 2:
return '二级预警';
case 3:
return '三级预警';
default:
return '';
}
}

15
super-screen/client/src/sections/water-prevention/components/emergency-right-top.js

@ -3,7 +3,7 @@ import { Box } from '$components';
import './style.less';
function CitySafty(props) {
const { emengencyTab } = props;
const { emengencyTab, emerResource } = props;
const tab_name = {
yjjg: '应急机构',
yjdw: '应急队伍',
@ -11,29 +11,28 @@ function CitySafty(props) {
yljg: '医疗机构',
bncs: '避难场所',
}
return <Box title={"避难场所"} >
return <Box title={tab_name[emengencyTab]} >
<div className='fire_item_right_container'>
{
[1, 2, 3, 4, 5, 6, 7].map((s, index) => {
emerResource?.map((s, index) => {
return <div className='fire_right_item'>
<div className='item_left'></div>
<div className='item_right'>
<div className='flex-row'>
<div className='item_right_left'>场所名称</div>
<div className='item_right_right'>{tab_name[emengencyTab] + s}</div>
<div className='item_right_right'>{s.name || '--'}</div>
</div>
<div className='flex-row'>
<div className='item_right_left'>场所地点</div>
<div className='item_right_right'>南昌县中心街道人民路168号
人民路168号人民路168号</div>
<div className='item_right_right'>{s.address || s.region || '--'}</div>
</div>
<div className='flex-row'>
<div className='item_right_left'>承载人数</div>
<div className='item_right_right'>2000 </div>
<div className='item_right_right'>-- </div>
</div>
<div className='flex-row'>
<div className='item_right_left'>目标距离</div>
<div className='item_right_right'>2.5 Km</div>
<div className='item_right_right'>-- Km</div>
</div>
</div>
<div className='position_bg'><div className='position_icon' /> <span>场所{index + 1}</span> </div>

12
super-screen/client/src/sections/water-prevention/components/left-bottom.js

@ -1,8 +1,10 @@
import React from 'react'
import { Box } from '$components';
import RingChart from './charts/ring'
function LeftBottom(props) {
import RingChart from './charts/ring';
import { SHUI_ZHAN } from '../constants/water';
function LeftBottom(props) {
const { waterLevelLength } = props;
const colors = [
{
linearGradientTo: 'rgba(5, 207, 247, 0)',
@ -31,9 +33,9 @@ function LeftBottom(props) {
];
const data = [
{ name: '泵站站点', value: 2560 },
{ name: '雨量站点', value: 1560 },
{ name: '水位站点', value: 3560 }
{ name: '泵站站点', value: SHUI_ZHAN.length },
{ name: '雨量站点', value: 1 },
{ name: '水位站点', value: waterLevelLength }
]
return <Box title={"建设数据"} >

60
super-screen/client/src/sections/water-prevention/components/right-bottom.js

@ -1,31 +1,53 @@
import React, { useEffect, useState } from 'react'
import { Box } from '$components';
import { Select } from 'antd';
import './style.less';
const { Option } = Select;
function DataTop5(props) {
const { structures, accessToken, videoList } = props;
const [showVideoList, setShowVideoList] = useState([]);
useEffect(() => {
if (videoList.length && structures.length) setShowVideoList(videoList.filter(v => v.structId === structures[0].id));
}, [videoList])
return <Box title={"视频监控"} bodyPaddingTop={1} >
const renderSubtitle = () => (
<Select
className="gis-search-select"
popupClassName="super-dropdownClassName"
style={{ width: 120, height: 24 }}
showSearch={false}
optionFilterProp="children"
key={Math.random()}
defaultValue={structures[0]?.id}
onChange={(value) => { setShowVideoList(videoList.filter(v => v.structId === value)) }}
>
{structures.map(s => <Option key={s.id} value={s.id}>{s.name}</Option>)}
</Select>
);
return <Box title={"视频监控"} bodyPaddingTop={1} subtitleSelect={renderSubtitle()}>
<div className='water_video_container'>
<div className='_item'>
<div className='video_bottom'><span>南昌大道</span><span>14:12:32</span></div>
</div>
<div className='_item'>
<div className='video_bottom'><span>南昌大道</span><span>11:34:12</span></div>
</div>
<div className='_item'>
<div className='video_bottom'><span>南昌大道</span><span>08:34:12</span></div>
</div>
<div className='_item'>
<div className='video_bottom'><span>南昌大道</span><span>09:12:34</span></div>
</div>
<div className='_item'>
<div className='video_bottom'><span>南昌大道</span><span>08:34:12</span></div>
</div>
<div className='_item'>
<div className='video_bottom'><span>南昌大道</span><span>09:12:34</span></div>
</div>
{
showVideoList?.map((v, i) => {
const src = `https://open.ys7.com/ezopen/h5/iframe?url=${v.url}&autoplay=1&accessToken=${accessToken}`
return <div className='_item' key={v.url}>
<iframe
id={`myPlayer-${i}`}
src={src}
width='100%' // https://open.ys7.com/doc/zh/book/index/live_proto.html 单个播放器的长宽比例限制最小为{width: 400px;height: 300px;}
height='100%'
allowFullScreen
>
</iframe>
<div className='video_bottom'>
<span className='video_bottom_text'>{v.name}</span>
</div>
</div>
})
}
</div>
</Box>
}

16
super-screen/client/src/sections/water-prevention/components/right-top.js

@ -1,8 +1,10 @@
import React, { useEffect, useState } from 'react'
import { Box } from '$components';
import { Tooltip } from 'antd';
import './style.less';
function CitySafty(props) {
const { trendData } = props;
return <Box title={"水位趋势预测图"} >
<div className='water_traffic_ranking'>
@ -14,16 +16,16 @@ function CitySafty(props) {
</div>
<div className='rank_content_overflow'>
{[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11].map((s, index) => {
return <div className='_rank_content'>
{trendData?.map((s, index) => {
return <div className='_rank_content' key={s.index}>
<div className={`_rank_item1`}>
点位{index + 1}
<Tooltip placement="topLeft" title={s.name}>{s.name}</Tooltip>
</div>
<div className='_rank_item2'>2023-01-02 12:12:12</div>
<div className='_rank_item3'>111 <div className={index % 2 == 0 ? '_upicon' : '_downicon'} /> </div>
<div className='_rank_item2'>{s.currentTime}</div>
<div className='_rank_item3'>{s.waterLevel}{s.waterLevel && <div className={s.waterLevel - s.lastWaterLevel > 0 ? '_upicon' : '_downicon'} />}</div>
<div className='_rank_item4'>
<div className={index % 2 == 0 ? 'normalbg' : 'warningbg'} >
{index % 2 == 0 ? '正常' : '告警'}
<div className={s.futureState === '正常' ? 'normalbg' : 'warningbg'} >
{s.futureState === '正常' ? '正常' : s.futureState.length ? '告警' : '--'}
</div>
</div>
</div>

25
super-screen/client/src/sections/water-prevention/components/style.less

@ -365,11 +365,12 @@
height: 100%;
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
align-items: start;
justify-content: start;
._item {
width: 46%;
margin: 0.5% 2%;
height: 32%;
background: url('/assets/images/homepage/fire/videobg.png') no-repeat;
background-size: 100% 100%;
@ -377,9 +378,9 @@
.video_bottom {
position: absolute;
bottom: 9%;
left: 4%;
width: 91%;
bottom: 0;
left: 2%;
width: 96%;
height: 20px;
background: rgba(0, 0, 0, 0.4);
font-size: 12px;
@ -387,6 +388,12 @@
display: flex;
justify-content: space-between;
.video_bottom_text {
width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
}
@ -505,12 +512,16 @@
._rank_item1 {
text-align: center;
width: 15%;
width: 20%;
margin-left: 5px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
._rank_item2 {
// text-align: center;
width: 40%;
width: 35%;
}
._rank_item3 {

145
super-screen/client/src/sections/water-prevention/components/weather.js

@ -1,18 +1,153 @@
import React, { useEffect, useState } from 'react'
import React, { useEffect, useState, useMemo } from 'react'
import moment from 'moment';
import { RouteRequest } from '@peace/utils';
const WEATHERMARGIN = 1 * 60 * 60 * 1000;
const WEATHERArr = [
{
lbl: '未知',
key: 'weizhi',
},
{
lbl: '暴雪',
key: 'baoxue',
},
{
lbl: '多云',
key: 'duoyun',
},
{
lbl: '浮沉',
key: 'fucheng',
},
{
lbl: '雷阵雨',
key: 'leizhengyu',
},
{
lbl: '霾',
key: 'mai',
},
{
lbl: '强沙尘暴',
key: 'qiangshachengbao',
},
{
lbl: '晴',
key: 'qing',
},
{
lbl: '沙尘暴',
key: 'shachengbao',
},
{
lbl: '特大暴雨',
key: 'tedabaoyu',
},
{
lbl: '雾',
key: 'wu',
},
{
lbl: '小雪',
key: 'xiaoxue',
},
{
lbl: '小雨',
key: 'xiaoyu',
},
{
lbl: '扬沙',
key: 'yangsha',
},
{
lbl: '阴天',
key: 'yingtian',
},
{
lbl: '雨夹雪',
key: 'yujiaxue',
},
{
lbl: '阵雨',
key: 'zhenyu',
},
{
lbl: '中雪',
key: 'zhongxue',
},
{
lbl: '中雨',
key: 'zhongyu',
},
{
lbl: '大雨',
key: 'dayu',
},
];
const ICONSMAP = {};
WEATHERArr.forEach(({ lbl, key }) => {
const icon = `/assets/images/weather/${key}.png`;
ICONSMAP[lbl] = icon;
});
function Weather() {
const [time, setTime] = useState(new Date().toLocaleTimeString());
const [weather, setWeather] = useState('');
const [temp, setTemp] = useState(0);
useEffect(() => {
const timeUpdate = setInterval(() => {
setTime(new Date().toLocaleTimeString());
}, 1000);
return () => {
clearInterval(timeUpdate);
};
}, []);
const queryWeather = () => {
RouteRequest.get(`/query/weather?cname=南昌市`).then((doc) => {
console.log(doc, 'weather');
const w = doc?.text || '未知';
const temp = doc?.temp || 0;
setWeather(w);
setTemp(temp);
});
};
useEffect(() => {
queryWeather();
const timeUpdate = setInterval(() => {
queryWeather();
}, WEATHERMARGIN);
return () => {
clearInterval(timeUpdate);
};
}, []);
const iconSrc = useMemo(() => {
const icon = ICONSMAP[weather];
if (icon) return icon;
const rgx = new RegExp(weather);
for (const k in ICONSMAP) {
if (rgx.test(k)) {
return ICONSMAP[k];
}
}
return '';
}, [weather]);
return <div className='_weather_container'>
<div className='column1'>
<div>{moment().format('YYYY-MM-DD')}</div>
<div style={{ fontSize: 14 }}>{moment().format('HH:mm:ss')}</div>
<div style={{ fontSize: 14 }}>{time}</div>
</div>
<div className='_divider'></div>
<div className='weather_icon'></div>
<img src={iconSrc} alt="icon" style={{ width: 43, height: 38, margin: '0 5px' }} />
<div className='column2'>
<div>晴转多云</div>
<div style={{ fontSize: 14 }}>18~26</div>
<div>{weather}</div>
<div style={{ fontSize: 14 }}>{temp}</div>
</div>
</div>
}

22
super-screen/client/src/sections/water-prevention/constants/water.js

@ -0,0 +1,22 @@
export const SHUI_ZHAN = [
{ name: '莲塘渡槽', location: [115.95219, 28.5429711], },
{ name: '雄溪站', location: [115.908888, 28.5337351], structId: 2945 },
{ name: '塔田站', location: [115.916979, 28.5319411], },
{ name: '万寿湖站', location: [115.929167, 28.5222881], },
{ name: '张坊站', location: [115.9092, 28.5049421], },
{ name: '东山站', location: [115.887528, 28.4872531], },
{ name: '河外泵站', location: [115.889888, 28.4856311], },
{ name: '三山站', location: [115.888521, 28.4726391], },
{ name: '内湖电排站', location: [115.891311, 28.4692441], },
{ name: '沥山站', location: [115.897692, 28.5616881], },
{ name: '象湖站', location: [115.894774, 28.5789311], },
{ name: '姚塘站', location: [115.863709, 28.579954], },
{ name: '河下站', location: [115.844769, 28.5602231], },
{ name: '霞山站', location: [115.841465, 28.5508371], },
{ name: '石岐站', location: [115.838675, 28.5507611], },
{ name: '清湖站', location: [115.838418, 28.5378311], },
{ name: '虎山站', location: [115.843673, 28.5366861], },
{ name: '新八月湖站', location: [115.880322, 28.6076911], },
// { name: '八月湖站', location: [115.868392, 28.6091981], },
{ name: '河口电排站', location: [115.924659, 28.52865] },
]

94
super-screen/client/src/sections/water-prevention/containers/gis.js

@ -2,6 +2,7 @@ import React, { useEffect, useState } from 'react';
import { connect } from 'react-redux';
import { render } from 'react-dom';
import { data as heatmapData } from './data'
import { SHUI_ZHAN } from '../constants/water';
import './gis.less'
const MAPDOMID = 'fs-amap-container1';
let map = null;
@ -15,8 +16,10 @@ const MARKER_IMG_NAME = {
markeryellow: '廉租房',
}
function Map(props) {
const { trendData, waterLevelAlarms } = props;
const [delay, setDelay] = useState(true)
const [tab, setTab] = useState('overview')
// 地图初始化
const loadMap = () => {
// 图片图层 实现瓦片地图中国地图样式 bounds 第一个点为左下角 第二个点为右上角
@ -74,8 +77,6 @@ function Map(props) {
renderLayer()
createText()
}, 1000);
};
const createText = () => {
@ -145,7 +146,7 @@ function Map(props) {
// 初始化GIS 组件销毁清空定时器
useEffect(() => {
loadMap();
}, []);
}, [trendData, waterLevelAlarms]);
const renderMarkers = () => {
map.clearMap();
@ -156,18 +157,18 @@ function Map(props) {
if (loca && heatmap) loca.remove(heatmap)
//初始层级 zoom14以下显示聚合点
const data = [
{ lng: 116.117906, lat: 28.678096, type: 'home', name: '泵站1', kind: 'markergreen' },
{ lng: 116.195238, lat: 28.842114, type: 'home', name: '泵站2', kind: 'markerblue' },
{ lng: 116.037227, lat: 28.558811, type: 'home', name: '泵站3', kind: 'markeryellow' },
{ lng: 115.925856, lat: 28.558811, type: 'home', name: '泵站4', kind: 'markergreen' },
{ lng: 115.989847, lat: 28.484411, type: 'home', name: '泵站5', kind: 'markergreen' },
]
// const data = [
// { lng: 116.117906, lat: 28.678096, type: 'home', name: '泵站1', kind: 'markergreen' },
// { lng: 116.195238, lat: 28.842114, type: 'home', name: '泵站2', kind: 'markerblue' },
// { lng: 116.037227, lat: 28.558811, type: 'home', name: '泵站3', kind: 'markeryellow' },
// { lng: 115.925856, lat: 28.558811, type: 'home', name: '泵站4', kind: 'markergreen' },
// { lng: 115.989847, lat: 28.484411, type: 'home', name: '泵站5', kind: 'markergreen' },
// ]
//初始点位显示
data.map((x, index) => {
SHUI_ZHAN.map((x, index) => {
var marker = new AMap.Marker({
position: new AMap.LngLat(x.lng, x.lat),
position: new AMap.LngLat(x.location[0], x.location[1]),
// 将一张图片的地址设置为 icon
icon: '/assets/images/homepage/water/_monitor.png',
// 设置了 icon 以后,设置 icon 的偏移量,以 icon 的 [center bottom] 为原点
@ -250,14 +251,25 @@ function Map(props) {
}
const renderAlarms = () => {
if (tab == 'person') {
if (tab == 'person' || !waterLevelAlarms.length || !trendData.length) {
return;
}
const alarms = [
{ lng: 116.044599, lat: 28.663869, type: 'device', name: 'xxx水位1', kind: 'markeralarm' },
]
const alarms = waterLevelAlarms.map(a => {
let alarm = {
lng: a.lng,
lat: a.lat,
// type: 'device',
name: a.alarms[0]?.source.name,
kind: 'markeralarm'
};
for (const t of trendData) {
if (t?.id == a.alarms[0]?.source.id) {
alarm.waterLevel = t.waterLevel;
alarm.alert = t.alert;
}
}
return alarm;
})
alarms.map((x, index) => {
var marker = new AMap.Marker({
position: new AMap.LngLat(x.lng, x.lat),
@ -266,13 +278,14 @@ function Map(props) {
// 设置了 icon 以后,设置 icon 的偏移量,以 icon 的 [center bottom] 为原点
offset: new AMap.Pixel(-13, -30),
zooms: [3, 14],
zIndex: 13,
});
marker.setTitle(x.name);
map.add(marker);
let infowindow = new AMap.InfoWindow({
isCustom: true, //使用自定义窗体
content: `<div id="map-content" class="gis-infowindow water-gis-infowindow-alarm gis-infowindow-alarm">
content: `<div id="map-content" class="gis-infowindow-alarm">
<div style="height:${360}px;" id="alarmcontentid${x.name}"></div></div>`,
offset: new AMap.Pixel(233, 260)
});
@ -301,11 +314,11 @@ function Map(props) {
</div>
<div className='gis_item'>
<span className='gis_title'>实时水位</span>
<span className='gis_text'>7.86m</span>
<span className='gis_text'>{x.waterLevel}m</span>
</div>
<div className='gis_item'>
<span className='gis_title'>预警水位</span>
<span className='gis_text'>7.86m</span>
<span className='gis_text'>{x.alert}m</span>
</div>
<div className='gis_item'>
<span className='gis_title'>近1h雨量</span>
@ -405,12 +418,13 @@ function Map(props) {
const renderLayer = () => {
if (!loca) return;
const dataSource = [
{ lng: 116.194039, lat: 28.712472, data: 14 },
{ lng: 116.051963, lat: 28.546815, data: 25 },
{ lng: 116.064207, lat: 28.694385, data: 35 },
{ lng: 115.983192, lat: 28.345722, data: 20 }
]
// const dataSource = [
// { lng: 116.194039, lat: 28.712472, data: 14 },
// { lng: 116.051963, lat: 28.546815, data: 25 },
// { lng: 116.064207, lat: 28.694385, data: 35 },
// { lng: 115.983192, lat: 28.345722, data: 20 }
// ]
const dataSource = trendData;
if (gridLayer && loca) loca.remove(gridLayer)
@ -462,25 +476,25 @@ function Map(props) {
// }
height: function (index, feature) {
const baseHeigh = 1200
return feature.coordinates[0].properties.x.data > 30 ? baseHeigh * 6 :
feature.coordinates[0].properties.x.data > 25 ? baseHeigh * 5 :
feature.coordinates[0].properties.x.data > 20 ? baseHeigh * 4 :
feature.coordinates[0].properties.x.data > 15 ? baseHeigh * 3 :
feature.coordinates[0].properties.x.data > 10 ? baseHeigh * 2 :
feature.coordinates[0].properties.x.data > 0 ? baseHeigh * 1 : 0
return feature.coordinates[0].properties.x.waterLevel > 30 ? baseHeigh * 6 :
feature.coordinates[0].properties.x.waterLevel > 25 ? baseHeigh * 5 :
feature.coordinates[0].properties.x.waterLevel > 20 ? baseHeigh * 4 :
feature.coordinates[0].properties.x.waterLevel > 15 ? baseHeigh * 3 :
feature.coordinates[0].properties.x.waterLevel > 10 ? baseHeigh * 2 :
feature.coordinates[0].properties.x.waterLevel > 0 ? baseHeigh * 1 : 0
},
topColor: function (index, feature) {
return feature.coordinates[0].properties.x.data > 30 ? 'rgba(255,136,140,1)' : 'rgba(117,154,206,1)'
return feature.coordinates[0].properties.x.waterLevel > 30 ? 'rgba(255,136,140,1)' : 'rgba(117,154,206,1)'
},
sideColor: function (index, feature) {
return feature.coordinates[0].properties.x.data > 30 ? 'rgba(255,136,140,1)' : 'rgba(117,154,206,1)'
return feature.coordinates[0].properties.x.waterLevel > 30 ? 'rgba(255,136,140,1)' : 'rgba(117,154,206,1)'
},
sideTopColor: function (index, feature) {
return feature.coordinates[0].properties.x.data > 30 ? 'rgba(255,136,140,1)' : 'rgba(117,154,206,1)'
return feature.coordinates[0].properties.x.waterLevel > 30 ? 'rgba(255,136,140,1)' : 'rgba(117,154,206,1)'
},
sideBottomColor: function (index, feature) {
return feature.coordinates[0].properties.x.data > 30 ? 'rgba(255,136,140,0.5)' : 'rgba(117,154,206,0.5)'
return feature.coordinates[0].properties.x.waterLevel > 30 ? 'rgba(255,136,140,0.5)' : 'rgba(117,154,206,0.5)'
},
});
gridLayer = gridLayer
@ -495,7 +509,7 @@ function Map(props) {
cursor: 'pointer',
angle: 0,
// visible: false,
offset: [0, -s.data],
offset: [0, -s.waterLevel],
style: {
'padding': '5px 10px',
'margin-bottom': '1rem',
@ -511,7 +525,7 @@ function Map(props) {
});
text.setMap(map);
text.show();
text.setText(s.data + 'm')
text.setText(`${s.waterLevel || '--'}m`)
text.setPosition(new AMap.LngLat(s.lng, s.lat));
})
@ -523,7 +537,7 @@ function Map(props) {
// if (feat) {
// text.show();
// text.setText(feat.coordinates[0].properties.x.data + 'm');
// text.setText(feat.coordinates[0].properties.x.waterLevel + 'm');
// text.setPosition(e.lnglat);
// } else {

40
super-screen/client/src/sections/water-prevention/containers/gis.less

@ -199,15 +199,17 @@
.gis-infowindow-alarm {
background: url('/assets/images/homepage/communtity/alarminfowindow.png') no-repeat;
background-size: 100% 100% !important;
height: 380px !important;
background-size: 100% 100%;
height: 380px;
width: 311px;
padding-top: 137px !important;
padding-top: 137px;
padding-left: 22px;
color: #fff;
.gis_exit {
cursor: pointer;
position: absolute;
right: 2px;
right: 8px;
top: 15px;
width: 30.75px;
height: 23px;
@ -219,8 +221,32 @@
margin-bottom: 10px;
height: 35px;
background-image: linear-gradient(180deg, #a7050591 0%, #48010191 100%);
;
width: 93%;
display: flex;
align-items: center;
padding-left: 10px;
.gis_title {
font-family: SourceHanSansCN-Regular;
font-weight: 400;
font-size: 14px;
color: #C3E6FF;
letter-spacing: 0;
margin-right: 12px;
}
.gis_text {
font-family: SourceHanSansCN-Regular;
font-weight: 400;
font-size: 14px;
color: #FFFFFF;
letter-spacing: 0;
line-height: 21px;
max-width: 183px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
.confirm_text {
@ -262,8 +288,8 @@
line-height: 30px;
width: 81px;
height: 30px;
background-image: linear-gradient(180deg, #C50000 1%, #b600006e 52%, #C50000 100%);
box-shadow: inset 0 1px 14px 0 #ff2b2b59;
background-image: linear-gradient(180deg, #C50000 1%, #b600006e 52%, #C50000 100%) !important;
box-shadow: inset 0 1px 14px 0 #ff2b2b59 !important;
border-radius: 4px;
font-family: SourceHanSansCN-Medium;
font-weight: 500;

150
super-screen/client/src/sections/water-prevention/containers/homePage.js

@ -16,18 +16,155 @@ import moment from 'moment';
import './style.less'
function homePage(props) {
const { dispatch } = props;
const { dispatch, actions } = props;
const {
getPcode, waterLogin, getWaterLevelTrend, getWaterStructures, getWaterVideoList, getYsAccessToken, getWaterAlarms,
worksafetyLogin, getEmerOrgList, getEmerTeamList, getEmerExpertList, getEmerMedicalList, getEmerRefugeList
} = actions.waterprevention;
const childStyle = { height: '49%', color: '#fff', marginBottom: 17 }
const cardHeight = document.body.clientHeight * 0.896 * 0.32
const cardContentHeight = cardHeight - 42 - 13
const [tab, setTab] = useState('overview');// overview emergency
const [emengencyTab, setEmengencyTab] = useState('yjjg');
const [trendData, setTrendData] = useState([]);
const [videoList, setVideoList] = useState([]);
const [accessToken, setAccessToken] = useState('');
const [structures, setStructures] = useState([]);
const [waterLevelAlarms, setWaterLevelAlarms] = useState([]);
const [emerResource, setEmerResource] = useState([]);
const SCREEN_COMPONENTS = {
overview: { leftTop: LeftTop, leftBottom: LeftBottom, rightTop: RightTop, rightBottom: RightBottom },
emergency: { leftTop: EmergencyLeftTop, leftBottom: EmergencyLeftBottom, rightTop: EmergencyRightTop, rightBottom: EmergencyRightBottom }
}
const currentContainer = SCREEN_COMPONENTS[tab];
useEffect(() => {
getData();
}, [])
const getData = () => {
// 水务
dispatch(getPcode()).then(res => {
if (res.success) {
dispatch(waterLogin({ username: "123456", password: "123456", pcode: res.payload.data.pcode })).then(loginRes => {
if (loginRes.success) {
const { token } = loginRes.payload.data;
sessionStorage.setItem('waterUser', JSON.stringify(loginRes.payload.data));
// 水位趋势
dispatch(getWaterLevelTrend({ orgId: 84, keyword: '', token })).then(trendRes => {
let fifterData = []
if (trendRes.success) {
trendRes.payload.data.map((item, index) => {
let alert = item.alert ? item.alert.replace('(', '').replace(')', '').split(',')[0] : '--'
let historyMax = item.historyMax ? item.historyMax.replace('(', '').replace(')', '').split(',')[0] : '--'
let waterLevel = item.data.length != 0 ? item.data[item.data.length - 1].waterLevel : ''
let lastWaterLevel = item.data.length != 0 ? item.data[item.data.length - 2].waterLevel : ''
let currentTime = item.data.length != 0 ? moment(item.data[item.data.length - 1].time).format('YYYY-MM-DD HH:mm:ss') : ''
let currentState = item.data.length != 0 ? (item.alert && alert <= waterLevel ? '超警戒' : '正常') : ''
let futureState = ''
if (item.alert && item.futureData && item.futureData.length != 0) {
item.futureData.map((futureItem) => {
if (futureItem.value >= alert) {
futureState = `超警戒,预计${item.forecast_time}时水位抵达${(item.value).toFixed(2)}m`
}
})
futureState = futureState != '' ? futureState : '正常'
}
fifterData.push({
index: index + 1,
name: item.name,
currentState,
waterLevel,
lastWaterLevel,
currentTime,
alert,
historyMax,
futureState,
lat: item.latitude,
lng: item.longitude,
id: item.id
})
})
}
setTrendData(fifterData)
})
// 结构物
dispatch(getWaterStructures({ token })).then(structRes => {
if (structRes.success) {
setStructures(structRes.payload.data);
// 视频
let promiseArr = [
dispatch(getWaterVideoList(structRes.payload.data?.map(s => s.id).join(), { token })),
dispatch(getYsAccessToken({ token }))
];
Promise.all(promiseArr).then(resArr => {
if (resArr[0].success && resArr[1].success) {
const at = resArr[1].payload.data.accessToken;
const list = resArr[0].payload.data?.map(v => ({ url: v.yingshi.hlsAddress, name: v.name, structId: v.structId }));
setAccessToken(at)
setVideoList(list);
}
})
// 告警
dispatch(getWaterAlarms({ token })).then(alarmRes => {
if (alarmRes.success) {
let levelAlarms = [];
alarmRes.payload.data.alarms.forEach(a => {
let alarm = { ...a }
for (const struct of structRes.payload.data) {
if (struct.id === a.structureId && struct.type.name === '河流') {
alarm.lng = struct.longitude;
alarm.lat = struct.latitude;
levelAlarms.push(alarm);
}
};
})
setWaterLevelAlarms(levelAlarms);
}
})
}
})
}
})
}
})
// 安监
dispatch(worksafetyLogin({ p: 'anjianshidian', username: 'SuperAdmin', password: '123456' })).then(res => {
if (res.success) {
sessionStorage.setItem('worksafetyUser', JSON.stringify(res.payload.data));
getEmerResource(emengencyTab, res.payload.data.token)
}
})
}
const getEmerResource = (type, token) => {
if (type && token) {
const handleRequestComplete = (res) => {
if (res.success) setEmerResource(res.payload.data);
}
switch (type) {
case 'yjjg':
dispatch(getEmerOrgList({ token })).then(handleRequestComplete);
break;
case 'yjdw':
dispatch(getEmerTeamList({ token })).then(handleRequestComplete);
break;
case 'yjzj':
dispatch(getEmerExpertList({ token })).then(handleRequestComplete);
break;
case 'yljg':
dispatch(getEmerMedicalList({ token })).then(handleRequestComplete);
break;
case 'bncs':
dispatch(getEmerRefugeList({ token })).then(handleRequestComplete);
break;
default:
break;
}
}
}
return <>
<div className='homepage'>
<div className='_title'>
@ -43,7 +180,7 @@ function homePage(props) {
<currentContainer.leftTop />
</div>
<div className='child' style={childStyle}>
<currentContainer.leftBottom />
<currentContainer.leftBottom waterLevelLength={trendData.length} waterLevelAlarms={waterLevelAlarms} />
</div>
</div>
</div>
@ -54,16 +191,20 @@ function homePage(props) {
}}
changeEmengencyTab={(e) => {
setEmengencyTab(e)
const { token } = JSON.parse(sessionStorage.getItem('worksafetyUser'));
getEmerResource(e, token)
}}
trendData={trendData}
waterLevelAlarms={waterLevelAlarms}
/>
</div>
<div className='homepage-left homepage-left-right'>
<div div className="list">
<div className='child-right' style={childStyle}>
<currentContainer.rightTop emengencyTab={emengencyTab} />
<currentContainer.rightTop emengencyTab={emengencyTab} emerResource={emerResource} trendData={trendData} />
</div>
<div className='child-right' style={childStyle}>
<currentContainer.rightBottom />
<currentContainer.rightBottom structures={structures} videoList={videoList} accessToken={accessToken} />
</div>
</div>
</div>
@ -78,7 +219,6 @@ function mapStateToProps(state) {
return {
clientHeight: global.clientHeight,
actions: global.actions,
};
}

15
super-screen/client/src/utils/webapi.js

@ -116,6 +116,21 @@ export const ApiTable = {
delServiceManagement: 'service-management/{id}',
lookField: 'lookField',
//大屏-水务
getPcode: '_water/get/pcode',
waterLogin: '_water/_api/login',
getWaterLevelTrend: '_water/_api/overview/monitoring-station',
getWaterStructures: '_water/_api/organizations/84/structures',
getWaterVideoList: '_water/_api/structures/{struIds}/ipcs?stationIds=undefined',
getYsAccessToken: '_water/_api/yingshi/accessToken',
getWaterAlarms: '_water/_api/axy/alarm?userId=1134&orderBy=endTime&orderDirection=desc&limit=10&offset=0',
//安监
worksafetyLogin: '_worksafety/_api/project/login',
getEmerOrgList: '_worksafety/_api/emergency/resource-org-list', // 应急机构
getEmerTeamList: '_worksafety/_api/emergency/resource-team-list', // 应急队伍
getEmerExpertList: '_worksafety/_api/emergency/resource-expert-list', // 应急专家
getEmerMedicalList: '_worksafety/_api/emergency/resource-medical-list', // 医疗机构
getEmerRefugeList: '_worksafety/_api/emergency/resource-refuge-list', // 避难场所
};
export const RouteTable = {

4
super-screen/config.js

@ -26,6 +26,7 @@ const ANXINCLOUD_QINIU_ACCESSKEY = process.env.ANXINCLOUD_QINIU_ACCESSKEY || fla
const ANXINCLOUD_QINIU_SECRETKEY = process.env.ANXINCLOUD_QINIU_SECRETKEY || flags.qnsk;
const ANXINCLOUD_QINIU_BUCKET_RESOURCE = process.env.ANXINCLOUD_QINIU_BUCKET_RESOURCE || flags.qnbkt;
const ANXINCLOUD_QINIU_DOMAIN_QNDMN_RESOURCE = process.env.ANXINCLOUD_QINIU_DOMAIN_QNDMN_RESOURCE || flags.qndmn;
const weatherUrl = process.env.ANXINCLOUD_WEATHERAPP_API || "https://weatherssj.anxinyun.cn/weatherApp/weather/getImmeData"
//阿里OSS
const ALI_OSS_ACCESSKEY = process.env.ALI_OSS_ACCESSKEY || flags.aliOssAccessKey;
@ -84,7 +85,8 @@ const product = {
secretKey: ALI_OSS_SECRETKET,
bucket: ALI_OSS_BUCKET,
region: ALI_OSS_REGION
}
},
weatherUrl,
}
},
{

2
super-screen/package.json

@ -69,7 +69,7 @@
"@fs/attachment": "^1.0.0",
"@jiaminghi/data-view-react": "^1.2.5",
"@peace/components": "0.0.35",
"@peace/utils": "0.0.37",
"@peace/utils": "0.0.66",
"ahooks": "^3.7.4",
"ali-oss": "^6.17.1",
"antd": "^4.24.5",

55
super-screen/routes/weather/index.js

@ -0,0 +1,55 @@
const request = require('superagent');
let _weatherUrl = '';
module.exports.entry = function (app, router, opts) {
const { weatherUrl } = opts;
console.log(weatherUrl, '天气');
_weatherUrl = weatherUrl;
// _weatherUrl = "https://weatherssj.anxinyun.cn/weatherApp/weather/getImmeData"
router.get('/query/weather', weather);
};
async function weather(ctx) {
try {
const { cname } = ctx.query;
const reg = /.+?(省|市|自治区|自治州|县|区)/g;
const arr = cname.match(reg);
if (Array.isArray(arr)) {
let cityName = arr[0];
if (arr[1]) {
cityName = arr[1];
}
const weatherRes = await request.post(_weatherUrl).send({ cityName });
const { body } = weatherRes;
if (body && body.data) {
ctx.status = 200;
ctx.body = { ...body.data, cname, texta: _weatherUrl };
} else {
ctx.status = 400;
ctx.body = { msg: '获取天气错误' };
}
} else {
ctx.status = 400;
ctx.body = { msg: '地址解析错误' };
}
} catch (error) {
console.log('[*err]', error);
ctx.status = 400;
ctx.body = error;
}
}
// ip地址识别库
// 淘宝IP地址查询接口:http://ip.taobao.com/service/getIpInfo.php?ip=1.1.35.57
// 腾讯IP地址查询接口:http://fw.qq.com/ipaddress
// 新浪的IP地址查询接口:http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=js
// 新浪多地域测试方法:http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=js&ip=218.192.3.42
// 搜狐IP地址查询接口(默认GBK):http://pv.sohu.com/cityjson
// 搜狐IP地址查询接口(可设置编码):http://pv.sohu.com/cityjson?ie=utf-8
// 搜狐另外的IP地址查询接口:http://txt.go.sohu.com/ip/soip
// 谷歌IP地址查询接口:http://j.maxmind.com/app/geoip.js
// 1616 IP地址查询接口:http://w.1616.net/chaxun/iptolocal.php
// 126 http://ip.ws.126.net/ipquery hao123
// http://app.hao123.com/ipquery/getcity.php?rtype=2
// 太平洋电脑网 http://whois.pconline.com.cn/
Loading…
Cancel
Save