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'; |
|||
|
|||
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 { |
|||
...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'; |
|||
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 [{ |
|||
type: 'outer', |
|||
route: { |
|||
path: '/projectGroup/static', |
|||
path: '/projectGroup/statistic', |
|||
key: 'projectGroup', |
|||
breadcrumb: '项目集', |
|||
component: Static, |
|||
component: Statistic, |
|||
} |
|||
}]; |
@ -0,0 +1,3 @@ |
|||
.project-group { |
|||
font-family: PangMenZhengDaoBiaoTiTi; |
|||
} |
Loading…
Reference in new issue