CODE
1 year ago
28 changed files with 409 additions and 55 deletions
@ -0,0 +1,30 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
function realtime (opts) { |
||||
|
return async (ctx, next) => { |
||||
|
try { |
||||
|
const { models } = ctx.fs.dc; |
||||
|
const { location } = ctx.query |
||||
|
let location_ = location || '114.298156,27.717683';//经纬度字符串
|
||||
|
|
||||
|
const weatherRes = await ctx.app.fs.caiyunRequest.get(`${opts.caiyun.key}/${location_}/realtime`) |
||||
|
let rslt = {} |
||||
|
if (weatherRes.status == 'ok') { |
||||
|
rslt = weatherRes.result |
||||
|
} |
||||
|
|
||||
|
ctx.status = 200; |
||||
|
ctx.body = rslt |
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { |
||||
|
message: typeof error == 'string' ? error : undefined |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
module.exports = { |
||||
|
realtime |
||||
|
} |
@ -0,0 +1,8 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
const weather = require('../../controllers/weather'); |
||||
|
|
||||
|
module.exports = function (app, router, opts) { |
||||
|
app.fs.api.logAttr['GET/weather/realtime'] = { content: '获取实时天气', visible: true }; |
||||
|
router.get('/weather/realtime', weather.realtime(opts)); |
||||
|
}; |
Binary file not shown.
After Width: | Height: | Size: 67 KiB |
After Width: | Height: | Size: 790 B |
After Width: | Height: | Size: 428 B |
After Width: | Height: | Size: 3.2 KiB |
@ -1,7 +1,20 @@ |
|||||
'use strict'; |
'use strict'; |
||||
|
|
||||
import auth from './auth'; |
import auth from './auth'; |
||||
|
import { ApiTable, basicAction } from '$utils' |
||||
|
|
||||
|
export function getWeatherRealtime () { |
||||
|
return dispatch => basicAction({ |
||||
|
type: 'get', |
||||
|
dispatch: dispatch, |
||||
|
actionType: 'GET_WEATHER_REALTIME', |
||||
|
url: `${ApiTable.weatherRealtime}`, |
||||
|
msg: { error: '获取实时天气失败' }, |
||||
|
reducer: { name: 'weatherRealtime' } |
||||
|
}); |
||||
|
} |
||||
|
|
||||
export default { |
export default { |
||||
...auth |
...auth, |
||||
|
getWeatherRealtime, |
||||
}; |
}; |
@ -0,0 +1,27 @@ |
|||||
|
import React, { useEffect, useRef, useState } from 'react'; |
||||
|
import { connect } from 'react-redux'; |
||||
|
|
||||
|
const Body = (props) => { |
||||
|
|
||||
|
return ( |
||||
|
<div style={{ |
||||
|
backgroundImage: "url('/assets/images/projectGroup/body.png')", |
||||
|
backgroundRepeat: "no-repeat", |
||||
|
backgroundSize: "100% 100%", |
||||
|
height: 'calc(100vh - 64px)', |
||||
|
padding: '24px 16px' |
||||
|
}}> |
||||
|
{props?.children} |
||||
|
</div> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
function mapStateToProps (state) { |
||||
|
const { auth, global, } = state; |
||||
|
return { |
||||
|
user: auth.user, |
||||
|
actions: global.actions, |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
export default connect(mapStateToProps)(Body); |
@ -0,0 +1,45 @@ |
|||||
|
import React, { useEffect, useRef, useState } from 'react'; |
||||
|
import { connect } from 'react-redux'; |
||||
|
|
||||
|
const Card = (props) => { |
||||
|
const { title } = props |
||||
|
|
||||
|
return ( |
||||
|
<div style={{ |
||||
|
background: ' #FFFFFF', |
||||
|
boxShadow: '0 2px 4px 2px #CBD5EE', |
||||
|
borderRadius: 4, |
||||
|
// filter: 'blur(5px)', |
||||
|
padding: '6px 4px', |
||||
|
}}> |
||||
|
<div style={{ |
||||
|
height: 34, lineHeight: '34px', |
||||
|
backgroundImage: "url('/assets/images/projectGroup/cardTitle.png')", |
||||
|
backgroundRepeat: "no-repeat", |
||||
|
padding: '0 10px', |
||||
|
display: 'flex', alignItems: 'center', justifyContent: 'space-between' |
||||
|
}}> |
||||
|
<span style={{ fontSize: 'x-large', letterSpacing: 1, textShadow: '0 0 8px #2a62fc05' }}>{title}</span> |
||||
|
<img src='/assets/images/projectGroup/cardTitlePoint.png' style={{ |
||||
|
width: 4, |
||||
|
height: 3, |
||||
|
background: '#2C66F3', |
||||
|
boxShadow: '0 0 4px 1px #2C66F3' |
||||
|
}} /> |
||||
|
</div> |
||||
|
<div style={{ minHeight: 24, padding: '12px 18px' }}> |
||||
|
{props?.children} |
||||
|
</div> |
||||
|
</div> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
function mapStateToProps (state) { |
||||
|
const { auth, global, } = state; |
||||
|
return { |
||||
|
user: auth.user, |
||||
|
actions: global.actions, |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
export default connect(mapStateToProps)(Card); |
@ -0,0 +1,127 @@ |
|||||
|
import React, { useEffect, useRef, useState } from 'react'; |
||||
|
import { connect } from 'react-redux'; |
||||
|
import { Skeleton, Button, Pagination, Form, Popconfirm, Table, Toast } from '@douyinfe/semi-ui'; |
||||
|
import moment from "moment"; |
||||
|
|
||||
|
const Header = (props) => { |
||||
|
const { dispatch, actions, weatherRealtime } = props |
||||
|
const [date, setDate] = useState(moment()); |
||||
|
const dayMap = { 0: '日', 1: '一', 2: '二', 3: '三', 4: '四', 5: '五', 6: '六' } |
||||
|
const weatherMap = { |
||||
|
CLEAR_DAY: '晴(白天)', |
||||
|
CLEAR_NIGHT: '晴(夜间)', |
||||
|
PARTLY_CLOUDY_DAY: '多云(白天)', |
||||
|
PARTLY_CLOUDY_NIGHT: '多云(夜间)', |
||||
|
CLOUDY: '阴', |
||||
|
WIND: '大风', |
||||
|
HAZE: '雾霾', |
||||
|
RAIN: '雨', |
||||
|
SNOW: '雪' |
||||
|
} |
||||
|
const [weatherTemperature, setWeatherTemperature] = useState(''); |
||||
|
const getWeather = () => { |
||||
|
dispatch(actions.auth.getWeatherRealtime()) |
||||
|
} |
||||
|
useEffect(() => { |
||||
|
const setTime = () => { |
||||
|
setDate(moment()); |
||||
|
setTimeout(() => { |
||||
|
setTime() |
||||
|
}, 1000); |
||||
|
} |
||||
|
|
||||
|
const refreshWeather = () => { |
||||
|
getWeather(); |
||||
|
setTimeout(() => { |
||||
|
refreshWeather() |
||||
|
}, 1000 * 60 * 15); |
||||
|
} |
||||
|
|
||||
|
setTimeout(() => { |
||||
|
setTime() |
||||
|
refreshWeather() |
||||
|
}, 0); |
||||
|
}, []) |
||||
|
|
||||
|
useEffect(() => { |
||||
|
setWeatherTemperature( |
||||
|
weatherRealtime?.temperature ? |
||||
|
(weatherRealtime?.temperature - Math.ceil(Math.random() * 5)) |
||||
|
+ '~' + |
||||
|
(weatherRealtime?.temperature + Math.ceil(Math.random() * 3)) |
||||
|
+ '℃' |
||||
|
: '' |
||||
|
) |
||||
|
}, [weatherRealtime]) |
||||
|
|
||||
|
const lineBetweenStyle = { |
||||
|
width: 1, |
||||
|
height: 15, |
||||
|
border: '1px solid #B3C9FF', |
||||
|
margin: '0 4px' |
||||
|
} |
||||
|
|
||||
|
return ( |
||||
|
<div style={{ |
||||
|
backgroundImage: "url('/assets/images/projectGroup/header.png')", |
||||
|
backgroundRepeat: "no-repeat", |
||||
|
backgroundSize: "100% 100%", |
||||
|
height: 64, |
||||
|
lineHeight: '64px', |
||||
|
padding: '0 24px', |
||||
|
display: 'flex', alignItems: 'center', justifyContent: 'space-between' |
||||
|
}}> |
||||
|
<span style={{ fontSize: 'xx-large', fontWeight: 'bolder' }}>运维中台大屏</span> |
||||
|
<span style={{ |
||||
|
display: 'flex', alignItems: 'center', flexDirection: 'row' |
||||
|
}}> |
||||
|
<div> |
||||
|
<span style={{ fontSize: 'large', fontWeight: 'bolder' }}> |
||||
|
{date.format('HH:mm:ss')} |
||||
|
</span> |
||||
|
</div> |
||||
|
<div style={lineBetweenStyle} /> |
||||
|
<div style={{ |
||||
|
display: 'flex', flexDirection: 'column', |
||||
|
lineHeight: '12px', |
||||
|
fontSize: 12, |
||||
|
color: '#5A6685', |
||||
|
letterSpacing: 0.6 |
||||
|
}}> |
||||
|
<span style={{ lineHeight: '14px', }}> |
||||
|
星期{dayMap[date.day()]} |
||||
|
</span> |
||||
|
<span style={{ display: 'inline-block', minWidth: 74 }}> |
||||
|
{date.format('YYYY-MM-DD')} |
||||
|
</span> |
||||
|
</div> |
||||
|
<div style={lineBetweenStyle} /> |
||||
|
<div style={{ |
||||
|
display: 'flex', flexDirection: 'column', |
||||
|
lineHeight: '12px', |
||||
|
fontSize: 12, |
||||
|
color: '#5A6685', |
||||
|
letterSpacing: 0.6 |
||||
|
}}> |
||||
|
<span style={{ lineHeight: '14px', }}> |
||||
|
{weatherTemperature} |
||||
|
</span> |
||||
|
<span style={{}}> |
||||
|
{weatherMap[weatherRealtime?.skycon]} |
||||
|
</span> |
||||
|
</div> |
||||
|
</span> |
||||
|
</div> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
function mapStateToProps (state) { |
||||
|
const { auth, global, weatherRealtime } = state; |
||||
|
return { |
||||
|
user: auth.user, |
||||
|
actions: global.actions, |
||||
|
weatherRealtime: weatherRealtime.data || {} |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
export default connect(mapStateToProps)(Header); |
@ -0,0 +1,30 @@ |
|||||
|
import React, { useEffect, useRef, useState } from 'react'; |
||||
|
import { connect } from 'react-redux'; |
||||
|
import Header from '../components/header'; |
||||
|
import Body from '../components/body' |
||||
|
import Card from '../components/card' |
||||
|
import '../style.less' |
||||
|
|
||||
|
const Bigscreen = (props) => { |
||||
|
|
||||
|
return ( |
||||
|
<div className='project-group'> |
||||
|
<Header /> |
||||
|
<Body> |
||||
|
<Card> |
||||
|
123 |
||||
|
</Card> |
||||
|
</Body> |
||||
|
</div> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
function mapStateToProps (state) { |
||||
|
const { auth, global, } = state; |
||||
|
return { |
||||
|
user: auth.user, |
||||
|
actions: global.actions, |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
export default connect(mapStateToProps)(Bigscreen); |
@ -1,4 +1,4 @@ |
|||||
'use strict'; |
'use strict'; |
||||
import Static from './static' |
import Statistic from './statistic' |
||||
|
|
||||
export { Static }; |
export { Statistic }; |
@ -1,23 +0,0 @@ |
|||||
import React, { useEffect, useRef, useState } from 'react'; |
|
||||
import { connect } from 'react-redux'; |
|
||||
import { Skeleton, Button, Pagination, Form, Popconfirm, Table, Toast } from '@douyinfe/semi-ui'; |
|
||||
import moment from "moment"; |
|
||||
|
|
||||
const Static = (props) => { |
|
||||
|
|
||||
return ( |
|
||||
<div> |
|
||||
|
|
||||
</div> |
|
||||
) |
|
||||
} |
|
||||
|
|
||||
function mapStateToProps (state) { |
|
||||
const { auth, global, } = state; |
|
||||
return { |
|
||||
user: auth.user, |
|
||||
actions: global.actions, |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
export default connect(mapStateToProps)(Static); |
|
@ -0,0 +1,31 @@ |
|||||
|
import React, { useEffect, useRef, useState } from 'react'; |
||||
|
import { connect } from 'react-redux'; |
||||
|
import Header from '../components/header'; |
||||
|
import Body from '../components/body' |
||||
|
import Card from '../components/card' |
||||
|
import '../style.less' |
||||
|
|
||||
|
|
||||
|
const Statistic = (props) => { |
||||
|
|
||||
|
return ( |
||||
|
<div className='project-group'> |
||||
|
<Header /> |
||||
|
<Body> |
||||
|
<Card title="12312312"> |
||||
|
123 |
||||
|
</Card> |
||||
|
</Body> |
||||
|
</div> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
function mapStateToProps (state) { |
||||
|
const { auth, global, } = state; |
||||
|
return { |
||||
|
user: auth.user, |
||||
|
actions: global.actions, |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
export default connect(mapStateToProps)(Statistic); |
@ -1,11 +1,11 @@ |
|||||
import { Static } from './containers'; |
import { Statistic } from './containers'; |
||||
|
|
||||
export default [{ |
export default [{ |
||||
type: 'outer', |
type: 'outer', |
||||
route: { |
route: { |
||||
path: '/projectGroup/static', |
path: '/projectGroup/statistic', |
||||
key: 'projectGroup', |
key: 'projectGroup', |
||||
breadcrumb: '项目集', |
breadcrumb: '项目集', |
||||
component: Static, |
component: Statistic, |
||||
} |
} |
||||
}]; |
}]; |
@ -0,0 +1,3 @@ |
|||||
|
.project-group { |
||||
|
font-family: PangMenZhengDaoBiaoTiTi; |
||||
|
} |
Loading…
Reference in new issue