时间:2023-09-04 14:06:01 | 来源:网站运营
时间:2023-09-04 14:06:01 来源:网站运营
基于 React+antd 的环境监测网站的设计与实现:摘 要: 生态环境是人类生存的物质基础,也是经济系统运行的基础,生态环境问题是由于人类长期的生产和生活等社会经济行为所引起的生态环境破坏而反作用于人类社会经济生活的不良影响,其实质是经济发展与环境保护、人与自然关系的失调。目前,环境问题已成为全球社会性的问题。如何解决好这一问题,关系到人类社会的生存。因此,采取有效的治理措施,对促进社会经济持续、健康发展具有十分重要的意义。所以,本网站的作用就是致力于监控生态环境并处理污染,主要针对空气、水质、土质和污染四个方面,并根据这四个方面来改善周围环境。本文主要阐述的是利用 React+antd 框架来搭建一个环境监测管理网站,包括网页制作,数据联调和功能说明等。'use strict';import React, { Component } from 'react';import { connect } from 'react-redux';import { Link,browserHistory } from 'react-router';import Headers from '../../components/Header';import Navigation from '../../components/Navigation';import NavList from '../../components/Navigation/NavList.jsx';import { Layout } from 'antd';const { Header, Footer, Sider, Content } = Layout;import '../../static/css/reset.css';import '../../static/css/common.css';import '../../static/css/icon.less';import './App.css';import Login from '../Login/index.jsx';import { fetchPost, fetchPut, fetchGet, fetchDelete } from '../../static/js/httprequest';import URL from '../../constants/HostConfig';import {adminUser} from '@app/constants/DataSource.jsx';class App extends Component { constructor(props, context) { super(props); this.state = { }; } componentWillMount() { if(adminUser.login === false) { browserHistory.push('/Login'); } } render() { return ( <div> { adminUser.login ?<Layout style = {{ minHeight: document.body.clientHeight,minWidth: 980 }}> {/*头部*/} <Header className='header'> <Headers isOline = {false} userName = {'admin'} menuList = { [{title: '退出登录',props: {onClick: () => {adminUser.login = false; browserHistory.push('/Login');} } }] } /> </Header> <Layout> {/*导航条*/} <Sider className = 'navigation'> <Navigation navlist = {NavList} pathname = {this.props.location.pathname} /> </Sider> {/*右侧内容*/} <Content className = "main" style = {{padding:20}}> {this.props.children} </Content> </Layout> </Layout>: <Login /> } </div> ); }}function mapStateToProps(state) { return { }}export default connect( mapStateToProps,{}App)
React 的 jsx 代码和 Java 代码很像,都有头部 import 引入,定义 Class 类,类中有构造函数和 render 输出。const menuList = this.props.menuList;const messageList = this.props.messageList;const menu = ( <Menu>{ menuList.map((item, index) => ( <Menu.Item key = {index}> <a {...item.props}>退出登录</a> </Menu.Item>}</Menu> );let menuNode, messageNode;return ( <div> <img className = 'header-img' src = '../../static/img/logo.png' /> <span className = 'alimis-header-title'></span> <ul className = "login-message"> <li className = 'login-menu-list' ref = {(node) => menuNode = node}> <Dropdown overlay= {menu} trigger= {['click']}getPopupContainer = {() => { return menuNode; }}><a> {adminUser.name}<Icon style = {{ fontSize: 12 }} type="down" /></a></Dropdown></li></ul></div> );
<Menu><Menu.Item>菜单项</Menu.Item><SubMenu title="子菜单"> <Menu.Item><Link to ="路由" >子菜单项</Link></Menu.Item> </SubMenu> </Menu>
其中导航条个数和导航条标题内容主要存放在相同文件夹的 NavList.jsx 文件中,代码是:const NavList = [ {component: '',layout: '',name: '导航条',path: '',children: [{name:'首页',icon:'laptop',path:'首页',children:[{name:'分析',path:'/Analysis',component:'首页', },{name:'监控',path:'/Monitor',component:'首页' },{name:'工作台',path:'/Workbench',component:'首页' }] },{name:'列表',icon:'line-chart',path:'列表',children:[{name:'项目',path:'/ProjectTeam',component:'列表',info:'/ProjectInfo' },{name:'人员信息',path:'/UserManage',component:'列表', }] },{name:'操作',icon:'setting',path:'操作',children:[{name:'新建项目',path:'/ProjectForm',component:'操作' },{name:'财务管理',path:'/Finance',component:'操作' }] },{name:'排行榜',icon:'bars',path:'/Rankings' }]} ];export default NavList;
使用 getNavMenuItems 方法把以上代码进行 map 循环,输出每一个的导航条按钮,效果如图 5.3.1。主要 getNavMenuItems 方法代码如下://获取导航栏目录名字信息,输出 DOM 目录getNavMenuItems = (menusData) => { if (!menusData) { return []; } return menusData.map((item) => { if (!item.name) { return null; } let itemPath; if (item.path.indexOf('http') === 0) { itemPath = item.path; } else { itemPath = `$ {item.path || ''}`.replace(///+/g, '/'); } let active = []; if (item.children && item.children.some(child => child.name)) { return ( <SubMenu title = { item.icon ? ( <span> <Icon type = {item.icon}/> <span>{item.name}</span> </span> : item.name } key = {item.path || item.key} > {this.getNavMenuItems(item.children)} </SubMenu> ); } return ( <Menu.Item key = {item.key || item.path}> <Link to = {itemPath} target = {item.target} onClick = {this.props.onClick}> {item.icon ? <Icon type = {item.icon}/> : null} <span> {item.name}</span> </Link> </Menu.Item> ); });}
clockTime = () =>{ this.timer = setInterval(() => { const time = new Date(); this.setState({time}); },1000); }
return 方法代码如下:<div> <p>{formatTime(this.state.time,'yyyy年mm月dd')}日</p> <p>星期{dayArr[this.state.time.getDay()]}</p> <p style = {{color:'#008CFF'}}>{formatTime(this.state.time,'hh:ff:ss')}</p> </div>
<ReactHighcharts config={config1} />let config1 = this.formChart({ title:'环境指数评分详情(每天12点更新)', series:[{ name:'分值', data: [ {name:'空气',y: endexData[analysisJson.region].a,color: '#008CFF'}, {name:'污染',y: endexData[analysisJson.region].b,color:'#008CFF'}, {name:'水质',y: endexData[analysisJson.region].c,color:'#008CFF'}, {name:'土质',y: endexData[analysisJson.region].d,color:'#008CFF'}, ] }], type:'bar', xAxis:{ categories: ['空气', '污染', '水质', '土质'], title: { text: null } }, legend:{ enabled:false }});formChart = (option) => { let config = { chart: { type: option.type, height:423 }, title: { text: option.title, style:{'fontSize': '16px'} }, xAxis: option.xAxis, yAxis: { min: 0, max:100, title: { text: null } }, legend:option.legend, plotOptions: { bar: { dataLabels: { allowOverlap: true, enabled: true, //禁用数据名称 } } }, exporting:{ enabled:false }, credits:{ enabled: false // 禁用版权信息 }, series: option.series }; return config; }
环境历史指数也是使用相同的 formChart 方法来完成 Highchart 的配置,部分代码如下:let config2 = this.formChart({title:'历史环境指数评分(每月1号更新)',series:[{name:'分值',data: endexData[analysisJson.region].score,color:'#008CFF' },{name:'平均分值',data: [89,90,89,86,86,88,92,91,86,85,84,90],color:'#00FF00' }],type:'',xAxis:{ max:12, min:1, maxPadding:1 },legend: {layout: 'vertical',align: 'right',verticalAlign: 'middle' }});
formChart = (option) => { let config = {chart: {type: 'spline' , marginRight: 10,events: {load: function () { var series = this.series[0], series1 = this.series[1], chart = this; option.clock(option.timer,option.wholeNum,series,series1); } } },title: {text: '实时数据' },tooltip: {dateTimeLabelFormats: {millisecond:"%b %e, %H:%M:%S" } },xAxis: {type: 'datetime' , tickPixelInterval: 150,dateTimeLabelFormats: {millisecond: '%H:%M:%S' , } },yAxis: {title: {text: '值' }, max:100, min:50 },legend: {enabled: true },exporting: {enabled: false },credits: {enabled: false // 禁用版权信息 },series: [{name: '分值',data: (function () { var data = [], time = (new Date()).getTime()+1000*60*60*8, i; for (i = -100; i <= 0; i += 1) { data.push({x: time + i * 1000,y: option.wholeNum + ((-1)^Math.ceil(Math.random()*10))*(Math.ceil(Math.random()*100)/100) }); } return data; } ()),color:'#008CFF' },{name: '平均值',data: (function () { var data = [], time = (new Date()).getTime()+1000*60*60*8, i; for (i = -100; i <= 0; i += 1) { data.push({x: time + i * 1000,y: option.wholeNum + ((-1)^Math.ceil(Math.random()*10))*(Math.ceil(Math.random()*100)/100) }); } return data; } ()),color:'#FF0000' },] }; return config;}
const Card_Grid = [];for(let i = 0; i<6; i++) { if(projectData[i]) { let status = 'normal'; if(projectData[i].state === 0) { status='active'; } else if(projectData[i].state === 1) { status='exception'; } else if(projectData[i].state ===2) { status = 'success'; } Card_Grid.push( <Card.Grid style= {gridStyle} key = {'Card.Grid'+i} style = {{paddingBottom:20}}> <Link to = {'/ProjectInfo?key='+i}> <div className = 'xiangmu'><Avatar style= {{ backgroundColor: projectData[i].color, verticalAlign: 'middle' }}> {projectData[i].title.substr(3,2)} </Avatar> <span className = 'titleItem'> {projectData[i].title}</span> <Progress percent= {projectData[i].process} status= {status}/><div style = {{marginTop:10,fontSize:10,color:'#999'}}> {projectData[i].name} <Divider type="vertical" style = {{height:10,top:0}}/> {projectData[i].endDate} </div> </div> </Link> </Card.Grid> ) }}
<div className = 'projectForm'> <Card> <Breadcrumb> <Breadcrumb.Item><Link to = '/Analysis'>首页</Link></Breadcrumb.Item> <Breadcrumb.Item>新建项目</Breadcrumb.Item> </Breadcrumb><p style = {{fontSize:20,paddingTop:20}}>新建项目</p></Card><Card style = {{marginTop:20}}><Row><Col span = {12} offset = {5}> <Form onSubmit= {this.handleSubmit}> <FormItem{...formItemLayout}label="项目名称" >{ getFieldDecorator('title', {rules: [{required: true, message: '请输入项目名称', }], })( <Input placeholder = '请输入项目名称'/> )}</FormItem><FormItem{...formItemLayout}label="项目类型" >{ getFieldDecorator('type', {rules: [{required: true, message: '请选择项目类型', }], })( <Select placeholder="请选择项目类型"> <Option value="空气">空气</Option> <Option value="污染">污染</Option> <Option value="土质">土质</Option> <Option value="水质">水质</Option> </Select> )}</FormItem><FormItem{...formItemLayout}label="初始分数" >{ getFieldDecorator('initial', {rules: [{required: true, message: '请输入初始分数', }], })( <InputNumber min = {0} max = {100} placeholder = '请输入'/> )}</FormItem><FormItem{...formItemLayout}label="目标分数" >{ getFieldDecorator('target', {rules: [{ required: true, message: '请输入目标分数' }], })( <InputNumber min = {0} max = {100} placeholder = '请输入'/> )}</FormItem><FormItem{...formItemLayout}label="资金" >{ getFieldDecorator('capitalAll', {rules: [{ required: true, message: '请输入资金' }], })( <InputNumber min = {0} max = {10000} placeholder = '请输入'/> )}</FormItem><FormItem{...formItemLayout}label="开始和结束时间" >{ getFieldDecorator('time', {rules: [{ required: true, message: '请选择开始和结束时间' }], })( <RangePicker onChange={this.onChange}/> )}</FormItem><FormItem{...formItemLayout}label="成员" >{ getFieldDecorator('user', {rules: [{ required: true, message: '请至少选择一个成员' }], })( <Select mode="multiple" placeholder="请选择成员" > {userList} </Select> )}</FormItem><FormItem{...formItemLayout}label="描述" >{ getFieldDecorator('task', {rules: [{ required: true, message: '请输入描述' }], })( <TextArea rows={4} placeholder = '请输入描述'/> )}</FormItem><FormItem {...tailFormItemLayout}><Button type="primary" htmlType="submit">新建</Button> </FormItem> </Form> </Col> </Row> </Card> </div>
<div className = 'workbench'> <Row gutter = {16}> <Col span = {24}> <Card loading = {this.state.loading}> <Breadcrumb> <Breadcrumb.Item><Link to = '/Analysis'>首页</Link></Breadcrumb.Item> <Breadcrumb.Item>财务管理</Breadcrumb.Item> </Breadcrumb> <Table dataSource={this.state.data} columns={columns} /> </Card> </Col> </Row> <Modal title="拨款" visible={this.state.visible} onOk={this.handleOk} onCancel={this.handleCancel} > 资金:<InputNumber min={0} max={100000} defaultValue={0} onChange = {this.onChange}/> </Modal> </div>
<div className = 'workbench'> <Row gutter = {16}> <Col span = {24}> <Card> <Breadcrumb> <Breadcrumb.Item><Link to='/Analysis'>首页</Link></Breadcrumb.Item> <Breadcrumb.Item>排行榜</Breadcrumb.Item> </Breadcrumb> <Row><Col span = {24} style = {{paddingTop:30,textAlign:'center'}}><div className = 'statItem'> <p>环境指数</p> <p> {endexData[analysisJson.region].fraction}</p> </div> <Divider type="vertical" /> <div className = 'statItem'> <p>队伍编号</p> <p> {endexData[analysisJson.region].ranksId}</p> </div> <Divider type="vertical" /> <div className = 'statItem'> <p>队伍排名</p> <p> {endexData[analysisJson.region].key}/ {endexData.length}</p> </div> </Col> </Row> <Table dataSource= {data} columns= {columns} loading = {this.state.loading}/> </Card> </Col> </Row> </div>
级别 | 描述 |
---|
React 技术栈系列教程:http://www.ruanyifeng.com/blog/2016/09/react-technology-stack.html Ant Design 组件库:https://ant.design/index-cn ES6 入门:http://es6.ruanyifeng.com/ [4] hcharts 教程:http://www.hcharts.cn/
关键词:设计,实现