system: [SYSTEM]

user: 4. 系统总体设计 4.1. 平台结构设计 水环境监测系统的整体结构如图6所示。本系统由前端展示层，业务逻辑层和数据库结构组成。 1) 前端展示层：前端展示层主要通过Vue.js + Vuetify开发的，系统为了更好的展示数据引用了Echarts的图表，在UI设计中也加了dnd.js特效，第三方库的引入使得系统具有良好的展示能力。为使系统中的信息高效利用，团队使用了Vuex作为系统中数据的管理工具，使得前端开发更加高效。 2) 业务逻辑层：本系统的业务逻辑主要分为以下几块，分别是：项目管理，人员管理，数据管理与展示，其中数据的管理与展示是本系统的核心业务，项目管理主要负责生成和维护日常项目，人员管理主要是对项目中的人员进行分配，其中人员的角色分别为：admin、项目管理员、操作员。数据的管理和展示业务则是对上传的水质数据进行合理的管理与展示。 3) 数据库结构：水环境监测系统的将上传的所有数据存放在MySQL数据库中，MySQL是当前中小企业最喜欢的关系型数据库管理系统之一，因其在数据处理上的优秀性能，所有在WEB系统方面使用尤为广泛。由于团队担心随着数据的累积，数据的传输效率以及并发的问题必将成为系统的瓶颈，所以团队采用Redis作为缓存，将符合特点条件的数据信息存放在Redis中，通过设置命中的时效性来对其中缓存的数据实时维护更新，提高数据传输和系统响应的速度。 图6. 系统整体架构图 4.2. 开发环境介绍 本系统后端基于Tornado技术开发，Tornado本身是一个轻量级的web框架，在处理高网络流量的请求时也可以发挥出出色的性能，而且还可以用于各种应用程序和工具。我们项目开发使用的是Anaconda下的python3环境编写的Tornado程序。Anaconda是一个开源的包、环境管理器，可以用于在同一个机器上安装不同版本的软件包及其依赖，并能够在不同的环境之间切换。项目开发时服务器都部署在本地，一般部署的服务器指定端口号为80，本地服务器连接地址为http:localhost:8080，这里的端口号是8080，在调试过程中，如遇端口号被占用的情况下，可以自定义其他端口。前端页面使用的是Vue框架去管理js、css、html等文件，安装Vue时本地必须先装上Node.js环境，Vue是npm下的开源包，需通过Node环境下载。团队使用Vue官方CLI创建Vue项目，使用webpack管理依赖包同时将项目运行在本地，端口8082。 系统在本地开发时数据的请求流程是先请求基于Mock管理平台YApi，该平台为本地Node服务器搭建，可直接请求，需要预先输入API的URL、参数、JSON数据等。如果某个接口已经完成开发，可以在YApi平台上点击取消该接口的链接，然后系统可以通过API直接请求后端服务。本系统通过第三方库Axios请求后端服务，使用ES6的Async/Await处理异步，系统开发时本地部署，所以前端不需要配置Nginx服务器，部署到云服务器上后需要开启Nginx配置代理请求服务。 4.3. 关键技术系统实现 本系统针对水质仪采集到的数据进行水体环境的实体建模，以可视化的方法在Web页面上进行图形化展示，直观地表现水体的各类数据，从而对水体水质能够进行网络化科学而直观的分析。 4.3.1. 数据保存与操作 用户上传数据后系统记录用户ID与文件id，将文件中的数据读取到数据库中，前端可展示出文件中的数据，如遇到错误或者不准确的数据，用户可自行删除该数据行。 4.3.2. GIS标定与展示 用户上传数据的文件中，有些文件具有GPS的定位信息，也有的文件不具备定位信息，所以在系统使用GIS进行标定时必须确定两个信息，文件中是否具有GPS定位信息和定位信息如何纠偏。本文中的系统使用百度地图开发包，在上传数据是用户可根据其他定位工具获取当然GPS信息进行手动输入，获取到大概位置时可展示在地图中进行纠偏操作。 纠偏操作分别包括两个步骤，分别是坐标转换和数据微调纠偏。第一个步骤可以通过相应地图提供的API来实现，如百度地图可以通过百度地图提供的转换坐标API来实现WGS84向百度地图坐标的转换；第二个步骤，因为在特定区域，坐标加偏方式是相同的，所以可以通过经验公式，进行自动纠偏。例如，太湖西岸经度和纬度加偏值大约为0.011107013599996662和0.004045467299999217。虽然这样的经验纠偏方式可以解决大部分的标定问题，但有时还可能存在标定不准确的现象，所以此时需要人工进行修正，人工修正只需要一次就可以得到区域内所有采样点的偏差，因此能够快速得到满意的结果。 4.3.3. 平面渲染图实现 平面图主要是为展示单指标在水域中的差异程度。平面图的渲染技术使用的是颜色差值，在系统实现过程中主要依靠对图片的处理完成颜色的渲染。用户选取数据点和水域后，前端将一系列信息传往后端，包含其中视图框大小，地图大小，地图中心点坐标，地图左上角及右下角经纬度坐标，Zoom等。后端通过这些数据截取与前端视图框同样大小的地图截图，由于地图具有覆盖层数据，需要通过自定义设置样式清除地图覆盖物，核心代码如下： map.setMapStyle({ styleJson: [{ featureType: road， elementType: all， stylers: { color: #ffffff， visibility: off } }， { featureType: building， elementType: all， stylers: { visibility: off } }， { featureType: poilabel， elementType: all， stylers: { visibility: off } }， { featureType: manmade， elementType: all， stylers: { visibility: off } }， ] }); 后端截取图片后根据地图上水域的RGB值进行逐行遍历和填充颜色，但如果单纯的扫描水域可能会导致其他无效水域被渲染颜色，所以经过讨论后团队采用的是扩散扫描法，此算法将从其中一个样本点出发，遍历这个像素点的上下左右点，若为蓝色，则进行渲染，并将此点加入未扫描的队列，之后遍历未扫描队列像素点的上下左右点，判断颜色进行渲染，如此循环，直至未扫描队列为空，渲染完毕。然后将渲染后的图片传到前端展示。 4.3.4. 断面图 断面图是为了了解不同水环境中的地势环境和水质情况，断面图是有用户选取不同的测量点，将不同的测量点通过选取的顺序连接，然后将所有被选中的点拉成一条直线，按数据点中的水深和单个指标绘制出水域中地形和水质的大体状况。前端负责将选中的点集以顺序排列的方式传往后端，后端根据数据点最中的水深，首先绘制水体的底部断面，再通过颜色扩散渲染方法，根据某一指标逐步的渲染水域信息，最后将渲染的图片传回前端。渲染的断面图如图7所示。 图7. 水体断面图 4.3.5. 四维水体图 四维水体的渲染是本系统最为复杂的工作，不仅要考虑大量的数据传输，还要考虑到数据的离散性，水体的全貌与水质的信息，团队采用了Echarts散点建模。面对大量的数据传输，团队优先考虑异步接口分批传输，但性能上并不理想，传输时间过长，接口如果调用失败则导致图形渲染失败等问题出现，由于数据的特殊性，团队选用字符串来进行数据的传输，既避免了多个接口连掉带来的性能消耗，也加快了传输的效率。 图8. 四维水体图 由于生成大量数据点需要经过构建水体底部三角网面、细化网面、分割水域、插值计算水质数据等操作，生成数据点的速度比较慢。如果用户只是改变希望展示的水深、水质参数，每次生成散点图都重新计算数据点会花费大量不必要的时间。因此，定义两个字符串a和b，初始赋值均为空。当需要生成3D散点图时，将用户所选数据条的id以字符串的形式存入a中，每个id中间用“，”分隔，并判断字符串a、b是否相等。如果相等，则无需重新计算数据点，直接生成散点图。如果a、b不相等，那么先令b = a，然后计算新的数据点，以新的数据点为基础去生成水体图。这样，当用户选择的数据条不变时，无需重新计算数据点。 系统选用视觉映射组件visualMap对散点图进行颜色渲染。将visualMap.min、visualMax.max分别定义为所有数据点对应水质数据的最小、最大值，设置visualMap.inRange.color为['#1710c0'， '#0b9df0'， '#00fea8'， '#00ff0d'， '#f5f811'， '#f09a09'， '#fe0300']，使各散点根据其所对应的水质数据进行了渐变的颜色渲染。四维水体图如图8所示。