├── Database
├── ddl.sql
├── water_model.sql
├── water_role.sql
├── water_user.sql
└── water_waterquality.sql
├── FrontEnd
├── .babelrc
├── .editorconfig
├── .gitignore
├── .postcssrc.js
├── Dockerfile
├── build
│ ├── build.js
│ ├── check-versions.js
│ ├── logo.png
│ ├── utils.js
│ ├── vue-loader.conf.js
│ ├── webpack.base.conf.js
│ ├── webpack.dev.conf.js
│ └── webpack.prod.conf.js
├── config
│ ├── dev.env.js
│ ├── index.js
│ └── prod.env.js
├── index.html
├── package-lock.json
├── package.json
├── src
│ ├── App.vue
│ ├── assets
│ │ ├── drop.png
│ │ ├── drop_big.png
│ │ ├── drop_medium.png
│ │ └── logo.png
│ ├── components
│ │ ├── HelloWorld.vue
│ │ ├── Home.vue
│ │ └── Login.vue
│ ├── main.js
│ └── router
│ │ └── index.js
└── static
│ ├── .gitkeep
│ ├── drop.png
│ ├── favicon.ico
│ └── water.png
├── README.md
├── WQMS
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── Dockerfile
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── cn
│ │ │ └── edu
│ │ │ └── njupt
│ │ │ └── sctpan
│ │ │ └── wqms
│ │ │ ├── WqmsApplication.java
│ │ │ ├── config
│ │ │ ├── CORSFilter.java
│ │ │ └── SecurityConfig.java
│ │ │ ├── controller
│ │ │ ├── ErrorController.java
│ │ │ └── UserController.java
│ │ │ ├── model
│ │ │ ├── Model.java
│ │ │ ├── Role.java
│ │ │ ├── User.java
│ │ │ ├── WaterQuality.java
│ │ │ └── WaterQualityHelper.java
│ │ │ ├── repository
│ │ │ ├── ModelRepository.java
│ │ │ ├── RoleRepository.java
│ │ │ ├── UserRepository.java
│ │ │ └── WaterQualityRepository.java
│ │ │ └── service
│ │ │ ├── ModelService.java
│ │ │ ├── UserService.java
│ │ │ └── WaterQualityService.java
│ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── cn
│ └── edu
│ └── njupt
│ └── sctpan
│ └── wqms
│ ├── WqmsApplicationTests.java
│ ├── repository
│ ├── RoleRepositoryTest.java
│ ├── UserRepositoryTest.java
│ └── WaterQualityRepositoryTest.java
│ ├── security
│ └── SecurityTest.java
│ └── service
│ ├── ModelServiceTest.java
│ ├── UserServiceTest.java
│ └── WaterQualityServiceTest.java
├── WQPS
├── .idea
│ ├── WQPS.iml
│ ├── encodings.xml
│ ├── inspectionProfiles
│ │ └── Project_Default.xml
│ ├── misc.xml
│ ├── modules.xml
│ ├── vcs.xml
│ └── workspace.xml
├── Dockerfile
├── Model
│ ├── ADABOOST
│ │ └── PH
│ │ │ ├── 4.model
│ │ │ └── 5.model
│ ├── LSTM
│ │ ├── DO
│ │ │ ├── 20.h5
│ │ │ └── 21.h5
│ │ └── PH
│ │ │ └── 2.h5
│ └── SVM
│ │ ├── DO
│ │ └── 22.model
│ │ └── PH
│ │ ├── 1.model
│ │ └── 3.model
├── WQPS
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-35.pyc
│ │ ├── __init__.cpython-36.pyc
│ │ ├── settings.cpython-35.pyc
│ │ ├── settings.cpython-36.pyc
│ │ ├── urls.cpython-36.pyc
│ │ └── wsgi.cpython-36.pyc
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── __pycache__
│ └── manage.cpython-36.pyc
├── manage.py
├── predicter
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-35.pyc
│ │ ├── __init__.cpython-36.pyc
│ │ ├── adaboost.cpython-36.pyc
│ │ ├── admin.cpython-36.pyc
│ │ ├── bp.cpython-36.pyc
│ │ ├── data_processor.cpython-36.pyc
│ │ ├── lstm.cpython-36.pyc
│ │ ├── model_handler.cpython-36.pyc
│ │ ├── model_predicter.cpython-36.pyc
│ │ ├── model_tester.cpython-36.pyc
│ │ ├── model_trainer.cpython-36.pyc
│ │ ├── models.cpython-36.pyc
│ │ ├── rvr.cpython-36.pyc
│ │ ├── service.cpython-36.pyc
│ │ ├── svm.cpython-36.pyc
│ │ ├── svr.cpython-36.pyc
│ │ ├── urls.cpython-36.pyc
│ │ └── views.cpython-36.pyc
│ ├── adaboost.py
│ ├── admin.py
│ ├── apps.py
│ ├── bp.py
│ ├── data_processor.py
│ ├── lstm.py
│ ├── migrations
│ │ ├── __init__.py
│ │ └── __pycache__
│ │ │ └── __init__.cpython-36.pyc
│ ├── model_handler.py
│ ├── model_predicter.py
│ ├── model_tester.py
│ ├── model_trainer.py
│ ├── models.py
│ ├── my_tests.py
│ ├── rvr.py
│ ├── service.py
│ ├── svm.py
│ ├── svr.py
│ ├── urls.py
│ └── views.py
├── requirements.txt
└── templates
│ └── test.html
├── docker-compose.yml
├── pics
├── 下月预测.png
├── 修改密码.png
├── 历史数据.png
├── 数据趋势.png
├── 模型训练.png
├── 水质数据添加.png
├── 水质数据编辑.png
├── 注册.png
├── 用例图.jpg
├── 用户信息.png
├── 用户授权.png
├── 用户管理.png
├── 用户菜单.png
├── 登录.png
├── 系统架构.jpg
└── 近日监测.png
└── 关于系统.txt
/Database/ddl.sql:
--------------------------------------------------------------------------------
1 | create table role
2 | (
3 | id int auto_increment
4 | primary key,
5 | name varchar(255) null
6 | );
7 |
8 | create table user
9 | (
10 | id int auto_increment
11 | primary key,
12 | username varchar(50) not null,
13 | password varchar(50) not null,
14 | rid int null,
15 | constraint FK8079530ngl61ed971pmagese0
16 | foreign key (rid) references role (id)
17 | );
18 |
19 | create table model
20 | (
21 | id int auto_increment
22 | primary key,
23 | name varchar(50) not null,
24 | target varchar(50) not null,
25 | method varchar(50) null,
26 | rmse float null,
27 | uid int not null,
28 | date datetime not null,
29 | constraint model_user_id_fk
30 | foreign key (uid) references user (id)
31 | );
32 |
33 | create table waterquality
34 | (
35 | id int auto_increment,
36 | PH float null,
37 | DO float null,
38 | NH3N float null,
39 | date datetime not null,
40 | station int null,
41 | constraint waterquality_id_uindex
42 | unique (id)
43 | );
44 |
45 | alter table waterquality
46 | add primary key (id);
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Database/water_model.sql:
--------------------------------------------------------------------------------
1 | INSERT INTO water.model (id, name, target, method, rmse, uid, date) VALUES (19, 'PH_Adaboost', 'PH', 'Adaboost', 0.2, 1, '2019-04-16 19:15:07');
2 | INSERT INTO water.model (id, name, target, method, rmse, uid, date) VALUES (20, 'DO_Adaboost', 'DO', 'Adaboost', 0.77, 1, '2019-04-16 19:16:20');
3 | INSERT INTO water.model (id, name, target, method, rmse, uid, date) VALUES (22, 'DO_LSTM', 'DO', 'LSTM', 0.73, 1, '2019-04-17 14:44:11');
4 | INSERT INTO water.model (id, name, target, method, rmse, uid, date) VALUES (25, 'DO_SVM', 'DO', 'SVM', 0.7, 1, '2019-04-21 12:09:22');
5 | INSERT INTO water.model (id, name, target, method, rmse, uid, date) VALUES (28, 'PH_RVM', 'PH', 'RVM', 0.19, 1, '2019-04-21 13:07:06');
6 | INSERT INTO water.model (id, name, target, method, rmse, uid, date) VALUES (29, 'PH_LSTM', 'PH', 'LSTM', 0.18, 1, '2019-04-21 13:12:17');
7 | INSERT INTO water.model (id, name, target, method, rmse, uid, date) VALUES (32, 'NH3N_ADABOOST', 'NH3N', 'ADABOOST', 0.35, 1, '2019-04-21 13:13:10');
8 | INSERT INTO water.model (id, name, target, method, rmse, uid, date) VALUES (34, 'DO_LSTM', 'DO', 'LSTM', 0.75, 1, '2019-04-21 13:13:50');
9 | INSERT INTO water.model (id, name, target, method, rmse, uid, date) VALUES (35, 'NH3N_LSTM', 'NH3N', 'LSTM', 0.32, 1, '2019-04-22 20:07:44');
10 | INSERT INTO water.model (id, name, target, method, rmse, uid, date) VALUES (36, 'PH_BP', 'PH', 'BP', 0.22, 1, '2019-04-23 10:28:43');
11 | INSERT INTO water.model (id, name, target, method, rmse, uid, date) VALUES (37, 'PH_SVM', 'PH', 'SVM', 0.18, 1, '2019-04-23 10:28:50');
12 | INSERT INTO water.model (id, name, target, method, rmse, uid, date) VALUES (43, 'PH_BP', 'PH', 'BP', 0.19, 1, '2019-05-07 21:26:01');
13 | INSERT INTO water.model (id, name, target, method, rmse, uid, date) VALUES (45, 'NH3N_BP', 'NH3N', 'BP', 0.4, 1, '2019-05-07 21:26:16');
14 | INSERT INTO water.model (id, name, target, method, rmse, uid, date) VALUES (46, 'NH3N_RVM', 'NH3N', 'RVM', 0.41, 1, '2019-05-07 21:26:27');
15 | INSERT INTO water.model (id, name, target, method, rmse, uid, date) VALUES (47, 'NH3N_LSTM', 'NH3N', 'LSTM', 0.32, 1, '2019-05-07 21:26:37');
16 | INSERT INTO water.model (id, name, target, method, rmse, uid, date) VALUES (48, 'NH3N_SVM', 'NH3N', 'SVM', 0.35, 1, '2019-05-07 21:26:56');
17 | INSERT INTO water.model (id, name, target, method, rmse, uid, date) VALUES (52, 'PH_择优算法', 'PH', '择优算法', 0.2, 1, '2019-05-08 16:15:44');
18 | INSERT INTO water.model (id, name, target, method, rmse, uid, date) VALUES (54, 'DO_LSTM', 'DO', 'LSTM', 0.73, 5, '2019-05-11 10:28:32');
19 | INSERT INTO water.model (id, name, target, method, rmse, uid, date) VALUES (55, 'DO_择优算法', 'DO', '择优算法', 0.73, 1, '2019-05-13 12:53:52');
20 | INSERT INTO water.model (id, name, target, method, rmse, uid, date) VALUES (56, 'DO_择优算法', 'DO', '择优算法', 0.73, 1, '2019-05-13 12:54:02');
21 | INSERT INTO water.model (id, name, target, method, rmse, uid, date) VALUES (57, 'DO_择优算法', 'DO', '择优算法', 0.68, 1, '2019-05-13 12:54:11');
22 | INSERT INTO water.model (id, name, target, method, rmse, uid, date) VALUES (58, 'PH_择优算法', 'PH', '择优算法', 0.2, 1, '2019-05-13 13:17:40');
23 | INSERT INTO water.model (id, name, target, method, rmse, uid, date) VALUES (59, 'DO_LSTM', 'DO', 'LSTM', 0.96, 1, '2019-05-23 15:26:56');
24 | INSERT INTO water.model (id, name, target, method, rmse, uid, date) VALUES (60, 'DO_LSTM', 'DO', 'LSTM', 0.72, 1, '2019-05-23 15:35:05');
25 | INSERT INTO water.model (id, name, target, method, rmse, uid, date) VALUES (62, 'PH_SVM', 'PH', 'SVM', 0.18, 1, '2019-06-07 09:09:48');
26 | INSERT INTO water.model (id, name, target, method, rmse, uid, date) VALUES (63, 'PH_SVM', 'PH', 'SVM', 0.18, 1, '2019-06-07 09:13:20');
27 | INSERT INTO water.model (id, name, target, method, rmse, uid, date) VALUES (64, 'DO_LSTM', 'DO', 'LSTM', 0.76, 1, '2019-06-07 22:51:25');
--------------------------------------------------------------------------------
/Database/water_role.sql:
--------------------------------------------------------------------------------
1 | INSERT INTO water.role (id, name) VALUES (1, 'admin');
2 | INSERT INTO water.role (id, name) VALUES (2, 'vip');
3 | INSERT INTO water.role (id, name) VALUES (3, 'user');
--------------------------------------------------------------------------------
/Database/water_user.sql:
--------------------------------------------------------------------------------
1 | INSERT INTO water.user (id, username, password, rid) VALUES (1, 'admin', '202cb962ac59075b964b07152d234b70', 1);
2 | INSERT INTO water.user (id, username, password, rid) VALUES (5, 'user1', '202cb962ac59075b964b07152d234b70', 2);
3 | INSERT INTO water.user (id, username, password, rid) VALUES (6, 'user2', '827ccb0eea8a706c4c34a16891f84e7b', 3);
4 | INSERT INTO water.user (id, username, password, rid) VALUES (7, 'user3', '202cb962ac59075b964b07152d234b70', 2);
5 | INSERT INTO water.user (id, username, password, rid) VALUES (8, 'user4', '202cb962ac59075b964b07152d234b70', 3);
--------------------------------------------------------------------------------
/FrontEnd/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["env", {
4 | "modules": false,
5 | "targets": {
6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
7 | }
8 | }],
9 | "stage-2"
10 | ],
11 | "plugins": ["transform-vue-jsx", "transform-runtime"]
12 | }
13 |
--------------------------------------------------------------------------------
/FrontEnd/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/FrontEnd/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | /dist/
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Editor directories and files
9 | .idea
10 | .vscode
11 | *.suo
12 | *.ntvs*
13 | *.njsproj
14 | *.sln
15 |
--------------------------------------------------------------------------------
/FrontEnd/.postcssrc.js:
--------------------------------------------------------------------------------
1 | // https://github.com/michael-ciniawsky/postcss-load-config
2 |
3 | module.exports = {
4 | "plugins": {
5 | "postcss-import": {},
6 | "postcss-url": {},
7 | // to edit target browsers: use "browserslist" field in package.json
8 | "autoprefixer": {}
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/FrontEnd/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:lts-alpine
2 |
3 | # install simple http server for serving static content
4 | RUN npm install -g http-server
5 |
6 | # copy both 'package.json' and 'package-lock.json' (if available)
7 | COPY package*.json ./
8 | # install project dependencies
9 | RUN npm install
10 |
11 | # copy project files and folders to the current working directory (i.e. 'app' folder)
12 | COPY . .
13 |
14 | # build app for production with minification
15 | RUN npm run build
16 |
17 | EXPOSE 8081
18 | CMD http-server dist --port 8081
19 |
--------------------------------------------------------------------------------
/FrontEnd/build/build.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | require('./check-versions')()
3 |
4 | process.env.NODE_ENV = 'production'
5 |
6 | const ora = require('ora')
7 | const rm = require('rimraf')
8 | const path = require('path')
9 | const chalk = require('chalk')
10 | const webpack = require('webpack')
11 | const config = require('../config')
12 | const webpackConfig = require('./webpack.prod.conf')
13 |
14 | const spinner = ora('building for production...')
15 | spinner.start()
16 |
17 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
18 | if (err) throw err
19 | webpack(webpackConfig, (err, stats) => {
20 | spinner.stop()
21 | if (err) throw err
22 | process.stdout.write(stats.toString({
23 | colors: true,
24 | modules: false,
25 | children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
26 | chunks: false,
27 | chunkModules: false
28 | }) + '\n\n')
29 |
30 | if (stats.hasErrors()) {
31 | console.log(chalk.red(' Build failed with errors.\n'))
32 | process.exit(1)
33 | }
34 |
35 | console.log(chalk.cyan(' Build complete.\n'))
36 | console.log(chalk.yellow(
37 | ' Tip: built files are meant to be served over an HTTP server.\n' +
38 | ' Opening index.html over file:// won\'t work.\n'
39 | ))
40 | })
41 | })
42 |
--------------------------------------------------------------------------------
/FrontEnd/build/check-versions.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const chalk = require('chalk')
3 | const semver = require('semver')
4 | const packageConfig = require('../package.json')
5 | const shell = require('shelljs')
6 |
7 | function exec (cmd) {
8 | return require('child_process').execSync(cmd).toString().trim()
9 | }
10 |
11 | const versionRequirements = [
12 | {
13 | name: 'node',
14 | currentVersion: semver.clean(process.version),
15 | versionRequirement: packageConfig.engines.node
16 | }
17 | ]
18 |
19 | if (shell.which('npm')) {
20 | versionRequirements.push({
21 | name: 'npm',
22 | currentVersion: exec('npm --version'),
23 | versionRequirement: packageConfig.engines.npm
24 | })
25 | }
26 |
27 | module.exports = function () {
28 | const warnings = []
29 |
30 | for (let i = 0; i < versionRequirements.length; i++) {
31 | const mod = versionRequirements[i]
32 |
33 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
34 | warnings.push(mod.name + ': ' +
35 | chalk.red(mod.currentVersion) + ' should be ' +
36 | chalk.green(mod.versionRequirement)
37 | )
38 | }
39 | }
40 |
41 | if (warnings.length) {
42 | console.log('')
43 | console.log(chalk.yellow('To use this template, you must update following to modules:'))
44 | console.log()
45 |
46 | for (let i = 0; i < warnings.length; i++) {
47 | const warning = warnings[i]
48 | console.log(' ' + warning)
49 | }
50 |
51 | console.log()
52 | process.exit(1)
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/FrontEnd/build/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/FrontEnd/build/logo.png
--------------------------------------------------------------------------------
/FrontEnd/build/utils.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const config = require('../config')
4 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
5 | const packageConfig = require('../package.json')
6 |
7 | exports.assetsPath = function (_path) {
8 | const assetsSubDirectory = process.env.NODE_ENV === 'production'
9 | ? config.build.assetsSubDirectory
10 | : config.dev.assetsSubDirectory
11 |
12 | return path.posix.join(assetsSubDirectory, _path)
13 | }
14 |
15 | exports.cssLoaders = function (options) {
16 | options = options || {}
17 |
18 | const cssLoader = {
19 | loader: 'css-loader',
20 | options: {
21 | sourceMap: options.sourceMap
22 | }
23 | }
24 |
25 | const postcssLoader = {
26 | loader: 'postcss-loader',
27 | options: {
28 | sourceMap: options.sourceMap
29 | }
30 | }
31 |
32 | // generate loader string to be used with extract text plugin
33 | function generateLoaders (loader, loaderOptions) {
34 | const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
35 |
36 | if (loader) {
37 | loaders.push({
38 | loader: loader + '-loader',
39 | options: Object.assign({}, loaderOptions, {
40 | sourceMap: options.sourceMap
41 | })
42 | })
43 | }
44 |
45 | // Extract CSS when that option is specified
46 | // (which is the case during production build)
47 | if (options.extract) {
48 | return ExtractTextPlugin.extract({
49 | use: loaders,
50 | fallback: 'vue-style-loader'
51 | })
52 | } else {
53 | return ['vue-style-loader'].concat(loaders)
54 | }
55 | }
56 |
57 | // https://vue-loader.vuejs.org/en/configurations/extract-css.html
58 | return {
59 | css: generateLoaders(),
60 | postcss: generateLoaders(),
61 | less: generateLoaders('less'),
62 | sass: generateLoaders('sass', { indentedSyntax: true }),
63 | scss: generateLoaders('sass'),
64 | stylus: generateLoaders('stylus'),
65 | styl: generateLoaders('stylus')
66 | }
67 | }
68 |
69 | // Generate loaders for standalone style files (outside of .vue)
70 | exports.styleLoaders = function (options) {
71 | const output = []
72 | const loaders = exports.cssLoaders(options)
73 |
74 | for (const extension in loaders) {
75 | const loader = loaders[extension]
76 | output.push({
77 | test: new RegExp('\\.' + extension + '$'),
78 | use: loader
79 | })
80 | }
81 |
82 | return output
83 | }
84 |
85 | exports.createNotifierCallback = () => {
86 | const notifier = require('node-notifier')
87 |
88 | return (severity, errors) => {
89 | if (severity !== 'error') return
90 |
91 | const error = errors[0]
92 | const filename = error.file && error.file.split('!').pop()
93 |
94 | notifier.notify({
95 | title: packageConfig.name,
96 | message: severity + ': ' + error.name,
97 | subtitle: filename || '',
98 | icon: path.join(__dirname, 'logo.png')
99 | })
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/FrontEnd/build/vue-loader.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const utils = require('./utils')
3 | const config = require('../config')
4 | const isProduction = process.env.NODE_ENV === 'production'
5 | const sourceMapEnabled = isProduction
6 | ? config.build.productionSourceMap
7 | : config.dev.cssSourceMap
8 |
9 | module.exports = {
10 | loaders: utils.cssLoaders({
11 | sourceMap: sourceMapEnabled,
12 | extract: isProduction
13 | }),
14 | cssSourceMap: sourceMapEnabled,
15 | cacheBusting: config.dev.cacheBusting,
16 | transformToRequire: {
17 | video: ['src', 'poster'],
18 | source: 'src',
19 | img: 'src',
20 | image: 'xlink:href'
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/FrontEnd/build/webpack.base.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const utils = require('./utils')
4 | const config = require('../config')
5 | const vueLoaderConfig = require('./vue-loader.conf')
6 |
7 | function resolve (dir) {
8 | return path.join(__dirname, '..', dir)
9 | }
10 |
11 |
12 |
13 | module.exports = {
14 | context: path.resolve(__dirname, '../'),
15 | entry: {
16 | app: './src/main.js'
17 | },
18 | output: {
19 | path: config.build.assetsRoot,
20 | filename: '[name].js',
21 | publicPath: process.env.NODE_ENV === 'production'
22 | ? config.build.assetsPublicPath
23 | : config.dev.assetsPublicPath
24 | },
25 | resolve: {
26 | extensions: ['.js', '.vue', '.json'],
27 | alias: {
28 | 'vue$': 'vue/dist/vue.esm.js',
29 | '@': resolve('src'),
30 | }
31 | },
32 | module: {
33 | rules: [
34 | {
35 | test: /\.vue$/,
36 | loader: 'vue-loader',
37 | options: vueLoaderConfig
38 | },
39 | {
40 | test: /\.js$/,
41 | loader: 'babel-loader',
42 | include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
43 | },
44 | {
45 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
46 | loader: 'url-loader',
47 | options: {
48 | limit: 10000,
49 | name: utils.assetsPath('img/[name].[hash:7].[ext]')
50 | }
51 | },
52 | {
53 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
54 | loader: 'url-loader',
55 | options: {
56 | limit: 10000,
57 | name: utils.assetsPath('media/[name].[hash:7].[ext]')
58 | }
59 | },
60 | {
61 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
62 | loader: 'url-loader',
63 | options: {
64 | limit: 10000,
65 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
66 | }
67 | }
68 | ]
69 | },
70 | node: {
71 | // prevent webpack from injecting useless setImmediate polyfill because Vue
72 | // source contains it (although only uses it if it's native).
73 | setImmediate: false,
74 | // prevent webpack from injecting mocks to Node native modules
75 | // that does not make sense for the client
76 | dgram: 'empty',
77 | fs: 'empty',
78 | net: 'empty',
79 | tls: 'empty',
80 | child_process: 'empty'
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/FrontEnd/build/webpack.dev.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const utils = require('./utils')
3 | const webpack = require('webpack')
4 | const config = require('../config')
5 | const merge = require('webpack-merge')
6 | const path = require('path')
7 | const baseWebpackConfig = require('./webpack.base.conf')
8 | const CopyWebpackPlugin = require('copy-webpack-plugin')
9 | const HtmlWebpackPlugin = require('html-webpack-plugin')
10 | const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
11 | const portfinder = require('portfinder')
12 |
13 | const HOST = process.env.HOST
14 | const PORT = process.env.PORT && Number(process.env.PORT)
15 |
16 | const devWebpackConfig = merge(baseWebpackConfig, {
17 | module: {
18 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
19 | },
20 | // cheap-module-eval-source-map is faster for development
21 | devtool: config.dev.devtool,
22 |
23 | // these devServer options should be customized in /config/index.js
24 | devServer: {
25 | clientLogLevel: 'warning',
26 | historyApiFallback: {
27 | rewrites: [
28 | { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
29 | ],
30 | },
31 | hot: true,
32 | contentBase: false, // since we use CopyWebpackPlugin.
33 | compress: true,
34 | host: HOST || config.dev.host,
35 | port: PORT || config.dev.port,
36 | open: config.dev.autoOpenBrowser,
37 | overlay: config.dev.errorOverlay
38 | ? { warnings: false, errors: true }
39 | : false,
40 | publicPath: config.dev.assetsPublicPath,
41 | proxy: config.dev.proxyTable,
42 | quiet: true, // necessary for FriendlyErrorsPlugin
43 | watchOptions: {
44 | poll: config.dev.poll,
45 | }
46 | },
47 | plugins: [
48 | new webpack.DefinePlugin({
49 | 'process.env': require('../config/dev.env')
50 | }),
51 | new webpack.HotModuleReplacementPlugin(),
52 | new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
53 | new webpack.NoEmitOnErrorsPlugin(),
54 | // https://github.com/ampedandwired/html-webpack-plugin
55 | new HtmlWebpackPlugin({
56 | filename: 'index.html',
57 | template: 'index.html',
58 | inject: true
59 | }),
60 | // copy custom static assets
61 | new CopyWebpackPlugin([
62 | {
63 | from: path.resolve(__dirname, '../static'),
64 | to: config.dev.assetsSubDirectory,
65 | ignore: ['.*']
66 | }
67 | ])
68 | ]
69 | })
70 |
71 | module.exports = new Promise((resolve, reject) => {
72 | portfinder.basePort = process.env.PORT || config.dev.port
73 | portfinder.getPort((err, port) => {
74 | if (err) {
75 | reject(err)
76 | } else {
77 | // publish the new Port, necessary for e2e tests
78 | process.env.PORT = port
79 | // add port to devServer config
80 | devWebpackConfig.devServer.port = port
81 |
82 | // Add FriendlyErrorsPlugin
83 | devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
84 | compilationSuccessInfo: {
85 | messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
86 | },
87 | onErrors: config.dev.notifyOnErrors
88 | ? utils.createNotifierCallback()
89 | : undefined
90 | }))
91 |
92 | resolve(devWebpackConfig)
93 | }
94 | })
95 | })
96 |
--------------------------------------------------------------------------------
/FrontEnd/build/webpack.prod.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const utils = require('./utils')
4 | const webpack = require('webpack')
5 | const config = require('../config')
6 | const merge = require('webpack-merge')
7 | const baseWebpackConfig = require('./webpack.base.conf')
8 | const CopyWebpackPlugin = require('copy-webpack-plugin')
9 | const HtmlWebpackPlugin = require('html-webpack-plugin')
10 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
11 | const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
12 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
13 |
14 | const env = require('../config/prod.env')
15 |
16 | const webpackConfig = merge(baseWebpackConfig, {
17 | module: {
18 | rules: utils.styleLoaders({
19 | sourceMap: config.build.productionSourceMap,
20 | extract: true,
21 | usePostCSS: true
22 | })
23 | },
24 | devtool: config.build.productionSourceMap ? config.build.devtool : false,
25 | output: {
26 | path: config.build.assetsRoot,
27 | filename: utils.assetsPath('js/[name].[chunkhash].js'),
28 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
29 | },
30 | plugins: [
31 | // http://vuejs.github.io/vue-loader/en/workflow/production.html
32 | new webpack.DefinePlugin({
33 | 'process.env': env
34 | }),
35 | new UglifyJsPlugin({
36 | uglifyOptions: {
37 | compress: {
38 | warnings: false
39 | }
40 | },
41 | sourceMap: config.build.productionSourceMap,
42 | parallel: true
43 | }),
44 | // extract css into its own file
45 | new ExtractTextPlugin({
46 | filename: utils.assetsPath('css/[name].[contenthash].css'),
47 | // Setting the following option to `false` will not extract CSS from codesplit chunks.
48 | // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
49 | // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
50 | // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
51 | allChunks: true,
52 | }),
53 | // Compress extracted CSS. We are using this plugin so that possible
54 | // duplicated CSS from different components can be deduped.
55 | new OptimizeCSSPlugin({
56 | cssProcessorOptions: config.build.productionSourceMap
57 | ? { safe: true, map: { inline: false } }
58 | : { safe: true }
59 | }),
60 | // generate dist index.html with correct asset hash for caching.
61 | // you can customize output by editing /index.html
62 | // see https://github.com/ampedandwired/html-webpack-plugin
63 | new HtmlWebpackPlugin({
64 | filename: config.build.index,
65 | template: 'index.html',
66 | inject: true,
67 | minify: {
68 | removeComments: true,
69 | collapseWhitespace: true,
70 | removeAttributeQuotes: true
71 | // more options:
72 | // https://github.com/kangax/html-minifier#options-quick-reference
73 | },
74 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin
75 | chunksSortMode: 'dependency'
76 | }),
77 | // keep module.id stable when vendor modules does not change
78 | new webpack.HashedModuleIdsPlugin(),
79 | // enable scope hoisting
80 | new webpack.optimize.ModuleConcatenationPlugin(),
81 | // split vendor js into its own file
82 | new webpack.optimize.CommonsChunkPlugin({
83 | name: 'vendor',
84 | minChunks (module) {
85 | // any required modules inside node_modules are extracted to vendor
86 | return (
87 | module.resource &&
88 | /\.js$/.test(module.resource) &&
89 | module.resource.indexOf(
90 | path.join(__dirname, '../node_modules')
91 | ) === 0
92 | )
93 | }
94 | }),
95 | // extract webpack runtime and module manifest to its own file in order to
96 | // prevent vendor hash from being updated whenever app bundle is updated
97 | new webpack.optimize.CommonsChunkPlugin({
98 | name: 'manifest',
99 | minChunks: Infinity
100 | }),
101 | // This instance extracts shared chunks from code splitted chunks and bundles them
102 | // in a separate chunk, similar to the vendor chunk
103 | // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
104 | new webpack.optimize.CommonsChunkPlugin({
105 | name: 'app',
106 | async: 'vendor-async',
107 | children: true,
108 | minChunks: 3
109 | }),
110 |
111 | // copy custom static assets
112 | new CopyWebpackPlugin([
113 | {
114 | from: path.resolve(__dirname, '../static'),
115 | to: config.build.assetsSubDirectory,
116 | ignore: ['.*']
117 | }
118 | ])
119 | ]
120 | })
121 |
122 | if (config.build.productionGzip) {
123 | const CompressionWebpackPlugin = require('compression-webpack-plugin')
124 |
125 | webpackConfig.plugins.push(
126 | new CompressionWebpackPlugin({
127 | asset: '[path].gz[query]',
128 | algorithm: 'gzip',
129 | test: new RegExp(
130 | '\\.(' +
131 | config.build.productionGzipExtensions.join('|') +
132 | ')$'
133 | ),
134 | threshold: 10240,
135 | minRatio: 0.8
136 | })
137 | )
138 | }
139 |
140 | if (config.build.bundleAnalyzerReport) {
141 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
142 | webpackConfig.plugins.push(new BundleAnalyzerPlugin())
143 | }
144 |
145 | module.exports = webpackConfig
146 |
--------------------------------------------------------------------------------
/FrontEnd/config/dev.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const merge = require('webpack-merge')
3 | const prodEnv = require('./prod.env')
4 |
5 | module.exports = merge(prodEnv, {
6 | NODE_ENV: '"development"'
7 | })
8 |
--------------------------------------------------------------------------------
/FrontEnd/config/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | // Template version: 1.3.1
3 | // see http://vuejs-templates.github.io/webpack for documentation.
4 |
5 | const path = require('path')
6 |
7 | module.exports = {
8 | dev: {
9 |
10 | // Paths
11 | assetsSubDirectory: 'static',
12 | assetsPublicPath: '/',
13 | proxyTable: {},
14 |
15 | // Various Dev Server settings
16 | host: 'localhost', // can be overwritten by process.env.HOST
17 | port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
18 | autoOpenBrowser: false,
19 | errorOverlay: true,
20 | notifyOnErrors: true,
21 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
22 |
23 |
24 | /**
25 | * Source Maps
26 | */
27 |
28 | // https://webpack.js.org/configuration/devtool/#development
29 | devtool: 'cheap-module-eval-source-map',
30 |
31 | // If you have problems debugging vue-files in devtools,
32 | // set this to false - it *may* help
33 | // https://vue-loader.vuejs.org/en/options.html#cachebusting
34 | cacheBusting: true,
35 |
36 | cssSourceMap: true
37 | },
38 |
39 | build: {
40 | // Template for index.html
41 | index: path.resolve(__dirname, '../dist/index.html'),
42 |
43 | // Paths
44 | assetsRoot: path.resolve(__dirname, '../dist'),
45 | assetsSubDirectory: 'static',
46 | assetsPublicPath: '/',
47 |
48 | /**
49 | * Source Maps
50 | */
51 |
52 | productionSourceMap: true,
53 | // https://webpack.js.org/configuration/devtool/#production
54 | devtool: '#source-map',
55 |
56 | // Gzip off by default as many popular static hosts such as
57 | // Surge or Netlify already gzip all static assets for you.
58 | // Before setting to `true`, make sure to:
59 | // npm install --save-dev compression-webpack-plugin
60 | productionGzip: false,
61 | productionGzipExtensions: ['js', 'css'],
62 |
63 | // Run the build command with an extra argument to
64 | // View the bundle analyzer report after build finishes:
65 | // `npm run build --report`
66 | // Set to `true` or `false` to always turn it on or off
67 | bundleAnalyzerReport: process.env.npm_config_report
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/FrontEnd/config/prod.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | module.exports = {
3 | NODE_ENV: '"production"'
4 | }
5 |
--------------------------------------------------------------------------------
/FrontEnd/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Water Quality Management and Forecasting System
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/FrontEnd/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "wqms",
3 | "version": "1.0.0",
4 | "description": "Water Quality Management System Front End",
5 | "author": "sctpan ",
6 | "private": true,
7 | "scripts": {
8 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
9 | "start": "npm run dev",
10 | "build": "node build/build.js"
11 | },
12 | "dependencies": {
13 | "axios": "^0.18.0",
14 | "echarts": "^4.2.1",
15 | "iview": "^3.3.3",
16 | "qs": "^6.7.0",
17 | "vue": "^2.5.2",
18 | "vue-router": "^3.0.1"
19 | },
20 | "devDependencies": {
21 | "autoprefixer": "^7.1.2",
22 | "babel-core": "^6.22.1",
23 | "babel-helper-vue-jsx-merge-props": "^2.0.3",
24 | "babel-loader": "^7.1.1",
25 | "babel-plugin-syntax-jsx": "^6.18.0",
26 | "babel-plugin-transform-runtime": "^6.22.0",
27 | "babel-plugin-transform-vue-jsx": "^3.5.0",
28 | "babel-preset-env": "^1.3.2",
29 | "babel-preset-stage-2": "^6.22.0",
30 | "chalk": "^2.0.1",
31 | "copy-webpack-plugin": "^4.0.1",
32 | "css-loader": "^0.28.0",
33 | "extract-text-webpack-plugin": "^3.0.0",
34 | "file-loader": "^1.1.4",
35 | "friendly-errors-webpack-plugin": "^1.6.1",
36 | "html-webpack-plugin": "^2.30.1",
37 | "node-notifier": "^5.1.2",
38 | "optimize-css-assets-webpack-plugin": "^3.2.0",
39 | "ora": "^1.2.0",
40 | "portfinder": "^1.0.13",
41 | "postcss-import": "^11.0.0",
42 | "postcss-loader": "^2.0.8",
43 | "postcss-url": "^7.2.1",
44 | "rimraf": "^2.6.0",
45 | "semver": "^5.3.0",
46 | "shelljs": "^0.7.6",
47 | "uglifyjs-webpack-plugin": "^1.1.1",
48 | "url-loader": "^0.5.8",
49 | "vue-loader": "^13.3.0",
50 | "vue-style-loader": "^3.0.1",
51 | "vue-template-compiler": "^2.5.2",
52 | "webpack": "^3.6.0",
53 | "webpack-bundle-analyzer": "^2.9.0",
54 | "webpack-dev-server": "^2.9.1",
55 | "webpack-merge": "^4.1.0"
56 | },
57 | "engines": {
58 | "node": ">= 6.0.0",
59 | "npm": ">= 3.0.0"
60 | },
61 | "browserslist": [
62 | "> 1%",
63 | "last 2 versions",
64 | "not ie <= 8"
65 | ]
66 | }
67 |
--------------------------------------------------------------------------------
/FrontEnd/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
28 |
--------------------------------------------------------------------------------
/FrontEnd/src/assets/drop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/FrontEnd/src/assets/drop.png
--------------------------------------------------------------------------------
/FrontEnd/src/assets/drop_big.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/FrontEnd/src/assets/drop_big.png
--------------------------------------------------------------------------------
/FrontEnd/src/assets/drop_medium.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/FrontEnd/src/assets/drop_medium.png
--------------------------------------------------------------------------------
/FrontEnd/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/FrontEnd/src/assets/logo.png
--------------------------------------------------------------------------------
/FrontEnd/src/components/HelloWorld.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ msg }}
4 |
Essential Links
5 |
48 |
Ecosystem
49 |
83 |
84 |
85 |
86 |
96 |
97 |
98 |
114 |
--------------------------------------------------------------------------------
/FrontEnd/src/components/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Water Quality Management and Forecasting System
7 |
8 |
9 |
10 | {{currentUser.username}}
11 |
12 |
13 |
14 | User Info
15 | Update Password
16 | Log Out
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
52 |
53 |
54 |
55 |
56 |
57 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | Username
67 |
68 |
69 | {{currentUser.username}}
70 |
71 |
72 |
73 |
74 | Role
75 |
76 |
77 | {{currentUser.role}}
78 |
79 |
80 |
81 |
82 | Authority
83 |
84 |
85 | {{currentUser.authority}}
86 |
87 |
88 |
89 |
90 |
91 |
92 | Password
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 | New Password
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 | Confirm Password
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
224 |
225 |
258 |
--------------------------------------------------------------------------------
/FrontEnd/src/components/Login.vue:
--------------------------------------------------------------------------------
1 |
2 |
57 |
58 |
59 |
158 |
159 |
219 |
--------------------------------------------------------------------------------
/FrontEnd/src/main.js:
--------------------------------------------------------------------------------
1 | // The Vue build version to load with the `import` command
2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
3 | import Vue from 'vue'
4 | import App from './App'
5 | import router from './router'
6 | import iView from 'iview'
7 | import axios from 'axios'
8 | import qs from 'qs'
9 | import echarts from 'echarts'
10 | import 'iview/dist/styles/iview.css'
11 |
12 | axios.defaults.baseURL = 'http://localhost:8080'
13 | axios.defaults.withCredentials = true
14 | Vue.prototype.axios = axios
15 | Vue.prototype.qs = qs
16 | Vue.prototype.echarts = echarts
17 | Vue.config.productionTip = false
18 | Vue.use(iView)
19 | /* eslint-disable no-new */
20 | new Vue({
21 | el: '#app',
22 | router,
23 | components: { App },
24 | template: ''
25 | })
26 |
--------------------------------------------------------------------------------
/FrontEnd/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 | import Home from '@/components/Home'
4 | import WaterManagement from '@/components/WaterManagement'
5 | import RecentCollection from '@/components/RecentCollection'
6 | import WaterTrend from '@/components/WaterTrend'
7 | import WaterPrediction from '@/components/WaterPrediction'
8 | import ModelTraining from '@/components/ModelTraining'
9 | import Login from '@/components/Login'
10 | import UserManagement from '@/components/UserManagement'
11 |
12 | Vue.use(Router)
13 |
14 | export default new Router({
15 | routes: [
16 | {
17 | path: '/',
18 | name: '登录',
19 | component: Login
20 | },
21 | {
22 | path: '/home',
23 | name: '主页',
24 | component: Home,
25 | children: [
26 | {
27 | path: '/recent',
28 | name: '近日收集',
29 | component: RecentCollection
30 | },
31 | {
32 | path: '/manage',
33 | name: '历史数据',
34 | component: WaterManagement
35 | },
36 | {
37 | path: '/trend',
38 | name: '数据走势',
39 | component: WaterTrend
40 | },
41 | {
42 | path: '/predict',
43 | name: '下月预测',
44 | component: WaterPrediction
45 | },
46 | {
47 | path: '/train',
48 | name: '模型更新',
49 | component: ModelTraining
50 | },
51 | {
52 | path: '/user',
53 | name: '用户管理',
54 | component: UserManagement
55 | }
56 | ]
57 | }
58 | ]
59 | })
60 |
--------------------------------------------------------------------------------
/FrontEnd/static/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/FrontEnd/static/.gitkeep
--------------------------------------------------------------------------------
/FrontEnd/static/drop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/FrontEnd/static/drop.png
--------------------------------------------------------------------------------
/FrontEnd/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/FrontEnd/static/favicon.ico
--------------------------------------------------------------------------------
/FrontEnd/static/water.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/FrontEnd/static/water.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Springboot_Vue_Python_Water_quality_management_prediction
2 | 基于Springboot+Vue+Python深度神经网络学习算法水质管理预测系统设计毕业源码案例设计
3 |
4 | 程序开发软件:Eclipse/Idea + WebStorm/VsCode + Pycharm 数据库:mysql
5 | 开发技术:Springboot + Vue + Python
6 | 这个是一个水质管理和预报系统,它是一个全栈Web应用程序,使用机器学习和深度神经网络算法来预测未来的水质。系统一共有2个身份包括管理员和用户。管理员登录后可以查询最新水质检测数据,也可以上报新的水质数据,可以查询管理历史水质数据,查询历史水质趋势图,训练自己的模型参数,选择一个算法模型结果预测下个月的水质信息,管理所有的用户信息;用户登录后比管理员就少了个用户管理功能。
7 |
8 | 管理员账号密码: admin/123
9 | 用户账号密码:user1/123
10 |
--------------------------------------------------------------------------------
/WQMS/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | /target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 |
5 | ### STS ###
6 | .apt_generated
7 | .classpath
8 | .factorypath
9 | .project
10 | .settings
11 | .springBeans
12 | .sts4-cache
13 |
14 | ### IntelliJ IDEA ###
15 | .idea
16 | *.iws
17 | *.iml
18 | *.ipr
19 |
20 | ### NetBeans ###
21 | /nbproject/private/
22 | /nbbuild/
23 | /dist/
24 | /nbdist/
25 | /.nb-gradle/
26 | /build/
27 |
28 | ### VS Code ###
29 | .vscode/
30 |
--------------------------------------------------------------------------------
/WQMS/.mvn/wrapper/MavenWrapperDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | https://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 |
20 | import java.io.File;
21 | import java.io.FileInputStream;
22 | import java.io.FileOutputStream;
23 | import java.io.IOException;
24 | import java.net.URL;
25 | import java.nio.channels.Channels;
26 | import java.nio.channels.ReadableByteChannel;
27 | import java.util.Properties;
28 |
29 | public class MavenWrapperDownloader {
30 |
31 | /**
32 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
33 | */
34 | private static final String DEFAULT_DOWNLOAD_URL =
35 | "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
36 |
37 | /**
38 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
39 | * use instead of the default one.
40 | */
41 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
42 | ".mvn/wrapper/maven-wrapper.properties";
43 |
44 | /**
45 | * Path where the maven-wrapper.jar will be saved to.
46 | */
47 | private static final String MAVEN_WRAPPER_JAR_PATH =
48 | ".mvn/wrapper/maven-wrapper.jar";
49 |
50 | /**
51 | * Name of the property which should be used to override the default download url for the wrapper.
52 | */
53 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
54 |
55 | public static void main(String args[]) {
56 | System.out.println("- Downloader started");
57 | File baseDirectory = new File(args[0]);
58 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
59 |
60 | // If the maven-wrapper.properties exists, read it and check if it contains a custom
61 | // wrapperUrl parameter.
62 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
63 | String url = DEFAULT_DOWNLOAD_URL;
64 | if (mavenWrapperPropertyFile.exists()) {
65 | FileInputStream mavenWrapperPropertyFileInputStream = null;
66 | try {
67 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
68 | Properties mavenWrapperProperties = new Properties();
69 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
70 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
71 | } catch (IOException e) {
72 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
73 | } finally {
74 | try {
75 | if (mavenWrapperPropertyFileInputStream != null) {
76 | mavenWrapperPropertyFileInputStream.close();
77 | }
78 | } catch (IOException e) {
79 | // Ignore ...
80 | }
81 | }
82 | }
83 | System.out.println("- Downloading from: : " + url);
84 |
85 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
86 | if (!outputFile.getParentFile().exists()) {
87 | if (!outputFile.getParentFile().mkdirs()) {
88 | System.out.println(
89 | "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
90 | }
91 | }
92 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
93 | try {
94 | downloadFileFromURL(url, outputFile);
95 | System.out.println("Done");
96 | System.exit(0);
97 | } catch (Throwable e) {
98 | System.out.println("- Error downloading");
99 | e.printStackTrace();
100 | System.exit(1);
101 | }
102 | }
103 |
104 | private static void downloadFileFromURL(String urlString, File destination) throws Exception {
105 | URL website = new URL(urlString);
106 | ReadableByteChannel rbc;
107 | rbc = Channels.newChannel(website.openStream());
108 | FileOutputStream fos = new FileOutputStream(destination);
109 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
110 | fos.close();
111 | rbc.close();
112 | }
113 |
114 | }
115 |
--------------------------------------------------------------------------------
/WQMS/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQMS/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/WQMS/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
2 |
--------------------------------------------------------------------------------
/WQMS/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:8-jdk-alpine
2 | ARG JAR_FILE=target/*.jar
3 | COPY ${JAR_FILE} app.jar
4 | ENTRYPOINT ["java","-jar","/app.jar"]
5 | EXPOSE 8080
--------------------------------------------------------------------------------
/WQMS/mvnw:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # ----------------------------------------------------------------------------
3 | # Licensed to the Apache Software Foundation (ASF) under one
4 | # or more contributor license agreements. See the NOTICE file
5 | # distributed with this work for additional information
6 | # regarding copyright ownership. The ASF licenses this file
7 | # to you under the Apache License, Version 2.0 (the
8 | # "License"); you may not use this file except in compliance
9 | # with the License. You may obtain a copy of the License at
10 | #
11 | # https://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing,
14 | # software distributed under the License is distributed on an
15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | # KIND, either express or implied. See the License for the
17 | # specific language governing permissions and limitations
18 | # under the License.
19 | # ----------------------------------------------------------------------------
20 |
21 | # ----------------------------------------------------------------------------
22 | # Maven2 Start Up Batch script
23 | #
24 | # Required ENV vars:
25 | # ------------------
26 | # JAVA_HOME - location of a JDK home dir
27 | #
28 | # Optional ENV vars
29 | # -----------------
30 | # M2_HOME - location of maven2's installed home dir
31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven
32 | # e.g. to debug Maven itself, use
33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files
35 | # ----------------------------------------------------------------------------
36 |
37 | if [ -z "$MAVEN_SKIP_RC" ] ; then
38 |
39 | if [ -f /etc/mavenrc ] ; then
40 | . /etc/mavenrc
41 | fi
42 |
43 | if [ -f "$HOME/.mavenrc" ] ; then
44 | . "$HOME/.mavenrc"
45 | fi
46 |
47 | fi
48 |
49 | # OS specific support. $var _must_ be set to either true or false.
50 | cygwin=false;
51 | darwin=false;
52 | mingw=false
53 | case "`uname`" in
54 | CYGWIN*) cygwin=true ;;
55 | MINGW*) mingw=true;;
56 | Darwin*) darwin=true
57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
59 | if [ -z "$JAVA_HOME" ]; then
60 | if [ -x "/usr/libexec/java_home" ]; then
61 | export JAVA_HOME="`/usr/libexec/java_home`"
62 | else
63 | export JAVA_HOME="/Library/Java/Home"
64 | fi
65 | fi
66 | ;;
67 | esac
68 |
69 | if [ -z "$JAVA_HOME" ] ; then
70 | if [ -r /etc/gentoo-release ] ; then
71 | JAVA_HOME=`java-config --jre-home`
72 | fi
73 | fi
74 |
75 | if [ -z "$M2_HOME" ] ; then
76 | ## resolve links - $0 may be a link to maven's home
77 | PRG="$0"
78 |
79 | # need this for relative symlinks
80 | while [ -h "$PRG" ] ; do
81 | ls=`ls -ld "$PRG"`
82 | link=`expr "$ls" : '.*-> \(.*\)$'`
83 | if expr "$link" : '/.*' > /dev/null; then
84 | PRG="$link"
85 | else
86 | PRG="`dirname "$PRG"`/$link"
87 | fi
88 | done
89 |
90 | saveddir=`pwd`
91 |
92 | M2_HOME=`dirname "$PRG"`/..
93 |
94 | # make it fully qualified
95 | M2_HOME=`cd "$M2_HOME" && pwd`
96 |
97 | cd "$saveddir"
98 | # echo Using m2 at $M2_HOME
99 | fi
100 |
101 | # For Cygwin, ensure paths are in UNIX format before anything is touched
102 | if $cygwin ; then
103 | [ -n "$M2_HOME" ] &&
104 | M2_HOME=`cygpath --unix "$M2_HOME"`
105 | [ -n "$JAVA_HOME" ] &&
106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
107 | [ -n "$CLASSPATH" ] &&
108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
109 | fi
110 |
111 | # For Mingw, ensure paths are in UNIX format before anything is touched
112 | if $mingw ; then
113 | [ -n "$M2_HOME" ] &&
114 | M2_HOME="`(cd "$M2_HOME"; pwd)`"
115 | [ -n "$JAVA_HOME" ] &&
116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
117 | # TODO classpath?
118 | fi
119 |
120 | if [ -z "$JAVA_HOME" ]; then
121 | javaExecutable="`which javac`"
122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
123 | # readlink(1) is not available as standard on Solaris 10.
124 | readLink=`which readlink`
125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
126 | if $darwin ; then
127 | javaHome="`dirname \"$javaExecutable\"`"
128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
129 | else
130 | javaExecutable="`readlink -f \"$javaExecutable\"`"
131 | fi
132 | javaHome="`dirname \"$javaExecutable\"`"
133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'`
134 | JAVA_HOME="$javaHome"
135 | export JAVA_HOME
136 | fi
137 | fi
138 | fi
139 |
140 | if [ -z "$JAVACMD" ] ; then
141 | if [ -n "$JAVA_HOME" ] ; then
142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
143 | # IBM's JDK on AIX uses strange locations for the executables
144 | JAVACMD="$JAVA_HOME/jre/sh/java"
145 | else
146 | JAVACMD="$JAVA_HOME/bin/java"
147 | fi
148 | else
149 | JAVACMD="`which java`"
150 | fi
151 | fi
152 |
153 | if [ ! -x "$JAVACMD" ] ; then
154 | echo "Error: JAVA_HOME is not defined correctly." >&2
155 | echo " We cannot execute $JAVACMD" >&2
156 | exit 1
157 | fi
158 |
159 | if [ -z "$JAVA_HOME" ] ; then
160 | echo "Warning: JAVA_HOME environment variable is not set."
161 | fi
162 |
163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
164 |
165 | # traverses directory structure from process work directory to filesystem root
166 | # first directory with .mvn subdirectory is considered project base directory
167 | find_maven_basedir() {
168 |
169 | if [ -z "$1" ]
170 | then
171 | echo "Path not specified to find_maven_basedir"
172 | return 1
173 | fi
174 |
175 | basedir="$1"
176 | wdir="$1"
177 | while [ "$wdir" != '/' ] ; do
178 | if [ -d "$wdir"/.mvn ] ; then
179 | basedir=$wdir
180 | break
181 | fi
182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc)
183 | if [ -d "${wdir}" ]; then
184 | wdir=`cd "$wdir/.."; pwd`
185 | fi
186 | # end of workaround
187 | done
188 | echo "${basedir}"
189 | }
190 |
191 | # concatenates all lines of a file
192 | concat_lines() {
193 | if [ -f "$1" ]; then
194 | echo "$(tr -s '\n' ' ' < "$1")"
195 | fi
196 | }
197 |
198 | BASE_DIR=`find_maven_basedir "$(pwd)"`
199 | if [ -z "$BASE_DIR" ]; then
200 | exit 1;
201 | fi
202 |
203 | ##########################################################################################
204 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
205 | # This allows using the maven wrapper in projects that prohibit checking in binary data.
206 | ##########################################################################################
207 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
208 | if [ "$MVNW_VERBOSE" = true ]; then
209 | echo "Found .mvn/wrapper/maven-wrapper.jar"
210 | fi
211 | else
212 | if [ "$MVNW_VERBOSE" = true ]; then
213 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
214 | fi
215 | jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
216 | while IFS="=" read key value; do
217 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
218 | esac
219 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
220 | if [ "$MVNW_VERBOSE" = true ]; then
221 | echo "Downloading from: $jarUrl"
222 | fi
223 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
224 |
225 | if command -v wget > /dev/null; then
226 | if [ "$MVNW_VERBOSE" = true ]; then
227 | echo "Found wget ... using wget"
228 | fi
229 | wget "$jarUrl" -O "$wrapperJarPath"
230 | elif command -v curl > /dev/null; then
231 | if [ "$MVNW_VERBOSE" = true ]; then
232 | echo "Found curl ... using curl"
233 | fi
234 | curl -o "$wrapperJarPath" "$jarUrl"
235 | else
236 | if [ "$MVNW_VERBOSE" = true ]; then
237 | echo "Falling back to using Java to download"
238 | fi
239 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
240 | if [ -e "$javaClass" ]; then
241 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
242 | if [ "$MVNW_VERBOSE" = true ]; then
243 | echo " - Compiling MavenWrapperDownloader.java ..."
244 | fi
245 | # Compiling the Java class
246 | ("$JAVA_HOME/bin/javac" "$javaClass")
247 | fi
248 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
249 | # Running the downloader
250 | if [ "$MVNW_VERBOSE" = true ]; then
251 | echo " - Running MavenWrapperDownloader.java ..."
252 | fi
253 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
254 | fi
255 | fi
256 | fi
257 | fi
258 | ##########################################################################################
259 | # End of extension
260 | ##########################################################################################
261 |
262 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
263 | if [ "$MVNW_VERBOSE" = true ]; then
264 | echo $MAVEN_PROJECTBASEDIR
265 | fi
266 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
267 |
268 | # For Cygwin, switch paths to Windows format before running java
269 | if $cygwin; then
270 | [ -n "$M2_HOME" ] &&
271 | M2_HOME=`cygpath --path --windows "$M2_HOME"`
272 | [ -n "$JAVA_HOME" ] &&
273 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
274 | [ -n "$CLASSPATH" ] &&
275 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
276 | [ -n "$MAVEN_PROJECTBASEDIR" ] &&
277 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
278 | fi
279 |
280 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
281 |
282 | exec "$JAVACMD" \
283 | $MAVEN_OPTS \
284 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
285 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
286 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
287 |
--------------------------------------------------------------------------------
/WQMS/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM https://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven2 Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM set title of command window
39 | title %0
40 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
42 |
43 | @REM set %HOME% to equivalent of $HOME
44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
45 |
46 | @REM Execute a user defined script before this one
47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
51 | :skipRcPre
52 |
53 | @setlocal
54 |
55 | set ERROR_CODE=0
56 |
57 | @REM To isolate internal variables from possible post scripts, we use another setlocal
58 | @setlocal
59 |
60 | @REM ==== START VALIDATION ====
61 | if not "%JAVA_HOME%" == "" goto OkJHome
62 |
63 | echo.
64 | echo Error: JAVA_HOME not found in your environment. >&2
65 | echo Please set the JAVA_HOME variable in your environment to match the >&2
66 | echo location of your Java installation. >&2
67 | echo.
68 | goto error
69 |
70 | :OkJHome
71 | if exist "%JAVA_HOME%\bin\java.exe" goto init
72 |
73 | echo.
74 | echo Error: JAVA_HOME is set to an invalid directory. >&2
75 | echo JAVA_HOME = "%JAVA_HOME%" >&2
76 | echo Please set the JAVA_HOME variable in your environment to match the >&2
77 | echo location of your Java installation. >&2
78 | echo.
79 | goto error
80 |
81 | @REM ==== END VALIDATION ====
82 |
83 | :init
84 |
85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
86 | @REM Fallback to current working directory if not found.
87 |
88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
90 |
91 | set EXEC_DIR=%CD%
92 | set WDIR=%EXEC_DIR%
93 | :findBaseDir
94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
95 | cd ..
96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
97 | set WDIR=%CD%
98 | goto findBaseDir
99 |
100 | :baseDirFound
101 | set MAVEN_PROJECTBASEDIR=%WDIR%
102 | cd "%EXEC_DIR%"
103 | goto endDetectBaseDir
104 |
105 | :baseDirNotFound
106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
107 | cd "%EXEC_DIR%"
108 |
109 | :endDetectBaseDir
110 |
111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
112 |
113 | @setlocal EnableExtensions EnableDelayedExpansion
114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
116 |
117 | :endReadAdditionalConfig
118 |
119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
122 |
123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
124 | FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO (
125 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
126 | )
127 |
128 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
129 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data.
130 | if exist %WRAPPER_JAR% (
131 | echo Found %WRAPPER_JAR%
132 | ) else (
133 | echo Couldn't find %WRAPPER_JAR%, downloading it ...
134 | echo Downloading from: %DOWNLOAD_URL%
135 | powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"
136 | echo Finished downloading %WRAPPER_JAR%
137 | )
138 | @REM End of extension
139 |
140 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
141 | if ERRORLEVEL 1 goto error
142 | goto end
143 |
144 | :error
145 | set ERROR_CODE=1
146 |
147 | :end
148 | @endlocal & set ERROR_CODE=%ERROR_CODE%
149 |
150 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
151 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
152 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
153 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
154 | :skipRcPost
155 |
156 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
157 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
158 |
159 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
160 |
161 | exit /B %ERROR_CODE%
162 |
--------------------------------------------------------------------------------
/WQMS/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.1.4.RELEASE
9 |
10 |
11 | cn.edu.njupt.sctpan
12 | wqms
13 | 0.0.1-SNAPSHOT
14 | wqms
15 | Water Quality Management System
16 |
17 |
18 | 1.8
19 |
20 |
21 |
22 |
23 | org.springframework.boot
24 | spring-boot-starter-data-jpa
25 |
26 |
27 | org.springframework.boot
28 | spring-boot-starter-security
29 |
30 |
31 | org.springframework.boot
32 | spring-boot-starter-web
33 |
34 |
35 |
36 | mysql
37 | mysql-connector-java
38 | runtime
39 |
40 |
41 | org.springframework.boot
42 | spring-boot-starter-test
43 | test
44 |
45 |
46 | org.springframework.security
47 | spring-security-test
48 | test
49 |
50 |
51 | org.apache.httpcomponents
52 | httpclient
53 | 4.5.6
54 |
55 |
56 |
57 |
58 |
59 |
60 | org.springframework.boot
61 | spring-boot-maven-plugin
62 |
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/WQMS/src/main/java/cn/edu/njupt/sctpan/wqms/WqmsApplication.java:
--------------------------------------------------------------------------------
1 | package cn.edu.njupt.sctpan.wqms;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
5 | import org.springframework.boot.autoconfigure.SpringBootApplication;
6 | import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
7 | import org.springframework.boot.web.servlet.ServletComponentScan;
8 |
9 |
10 | @SpringBootApplication
11 | //@ServletComponentScan(basePackages = {"cn.edu.njupt.sctpan.wqms.filter"})
12 | public class WqmsApplication {
13 |
14 | public static void main(String[] args) {
15 | SpringApplication.run(WqmsApplication.class, args);
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/WQMS/src/main/java/cn/edu/njupt/sctpan/wqms/config/CORSFilter.java:
--------------------------------------------------------------------------------
1 | package cn.edu.njupt.sctpan.wqms.config;
2 |
3 | import javax.servlet.*;
4 | import javax.servlet.http.HttpServletRequest;
5 | import javax.servlet.http.HttpServletResponse;
6 | import java.io.IOException;
7 |
8 | public class CORSFilter implements Filter {
9 |
10 | @Override
11 | public void init(FilterConfig filterConfig) throws ServletException {
12 |
13 | }
14 |
15 | @Override
16 | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
17 | HttpServletResponse response = (HttpServletResponse) servletResponse;
18 | HttpServletRequest request= (HttpServletRequest) servletRequest;
19 |
20 | response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
21 | response.setHeader("Access-Control-Allow-Methods", "GET,POST,DELETE,PUT,OPTIONS");
22 | response.setHeader("Access-Control-Allow-Headers", "*");
23 | response.setHeader("Access-Control-Allow-Credentials", "true");
24 | response.setHeader("Access-Control-Max-Age", "180");
25 | filterChain.doFilter(servletRequest, servletResponse);
26 | }
27 |
28 |
29 | @Override
30 | public void destroy() {
31 |
32 | }
33 | }
--------------------------------------------------------------------------------
/WQMS/src/main/java/cn/edu/njupt/sctpan/wqms/config/SecurityConfig.java:
--------------------------------------------------------------------------------
1 | package cn.edu.njupt.sctpan.wqms.config;
2 |
3 | import cn.edu.njupt.sctpan.wqms.service.UserService;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.context.annotation.Configuration;
7 | import org.springframework.security.access.AccessDeniedException;
8 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
9 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
10 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
11 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
12 | import org.springframework.security.config.http.SessionCreationPolicy;
13 | import org.springframework.security.core.Authentication;
14 | import org.springframework.security.core.AuthenticationException;
15 | import org.springframework.security.core.context.SecurityContextHolder;
16 | import org.springframework.security.crypto.password.PasswordEncoder;
17 | import org.springframework.security.web.access.AccessDeniedHandler;
18 | import org.springframework.security.web.authentication.AuthenticationFailureHandler;
19 | import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
20 | import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
21 | import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
22 | import org.springframework.security.web.session.SessionManagementFilter;
23 | import org.springframework.util.DigestUtils;
24 | import org.springframework.web.cors.CorsUtils;
25 |
26 | import javax.servlet.FilterChain;
27 | import javax.servlet.ServletException;
28 | import javax.servlet.ServletRequest;
29 | import javax.servlet.http.HttpServletRequest;
30 | import javax.servlet.http.HttpServletResponse;
31 | import java.io.IOException;
32 | import java.io.PrintWriter;
33 |
34 | @Configuration
35 | @EnableWebSecurity
36 | public class SecurityConfig extends WebSecurityConfigurerAdapter {
37 | @Autowired
38 | UserService userService;
39 |
40 |
41 | @Bean
42 | CORSFilter corsFilter() {
43 | CORSFilter filter = new CORSFilter();
44 | return filter;
45 | }
46 |
47 | @Override
48 | protected void configure(AuthenticationManagerBuilder auth) throws Exception {
49 | auth.userDetailsService(userService).passwordEncoder(new PasswordEncoder() {
50 | @Override
51 | public String encode(CharSequence charSequence) {
52 | return DigestUtils.md5DigestAsHex(charSequence.toString().getBytes());
53 | }
54 |
55 | @Override
56 | public boolean matches(CharSequence charSequence, String s) {
57 | return s.equals(DigestUtils.md5DigestAsHex(charSequence.toString().getBytes()));
58 | }
59 | });
60 | }
61 |
62 | private PrintWriter setCorsAndGetWriter(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException, ServletException{
63 | httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
64 | httpServletResponse.setHeader("Access-Control-Allow-Origin", httpServletRequest.getHeader("Origin"));
65 | httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,DELETE,PUT,OPTIONS");
66 | httpServletResponse.setHeader("Access-Control-Allow-Headers", "*");
67 | httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
68 | httpServletResponse.setHeader("Access-Control-Max-Age", "180");
69 | httpServletResponse.setContentType("application/json;charset=utf-8");
70 | PrintWriter out = httpServletResponse.getWriter();
71 | return out;
72 | }
73 |
74 | @Override
75 | protected void configure(HttpSecurity http) throws Exception {
76 | http.addFilterBefore(corsFilter(), SessionManagementFilter.class)
77 | .authorizeRequests()
78 | .requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
79 | .antMatchers("/waterquality/add","/waterquality/delete/*","/waterquality/update/*","/model/delete/*","/model/training")
80 | .hasAnyRole("admin","vip")
81 | .antMatchers("/user/delete/*", "/user/grant/*", "/user/query").hasRole("admin")
82 | .antMatchers("status/**").permitAll()
83 | .antMatchers("/user/register").permitAll()
84 | .anyRequest().authenticated()
85 | .and()
86 | .formLogin()
87 | .loginPage("/status/noLogin")
88 | .loginProcessingUrl("/login")
89 | .successHandler(new AuthenticationSuccessHandler() {
90 | @Override
91 | public void onAuthenticationSuccess(HttpServletRequest httpServletRequest,
92 | HttpServletResponse httpServletResponse,
93 | Authentication authentication) throws IOException, ServletException {
94 | // SecurityContextHolder.getContext().setAuthentication(authentication);
95 | // httpServletRequest.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext());
96 | PrintWriter out = setCorsAndGetWriter(httpServletRequest, httpServletResponse);
97 | out.write("{\"status\":\"success\"}");
98 | out.flush();
99 | out.close();
100 | }
101 | })
102 | .failureHandler(new AuthenticationFailureHandler() {
103 | @Override
104 | public void onAuthenticationFailure(HttpServletRequest httpServletRequest,
105 | HttpServletResponse httpServletResponse, AuthenticationException e)
106 | throws IOException, ServletException {
107 | PrintWriter out = setCorsAndGetWriter(httpServletRequest, httpServletResponse);
108 | out.write("{\"status\":\"failure\"}");
109 | out.flush();
110 | out.close();
111 | }
112 | })
113 | .usernameParameter("username").passwordParameter("password")
114 | .permitAll()
115 |
116 | .and()
117 | .logout()
118 | .logoutSuccessHandler(new LogoutSuccessHandler() {
119 | @Override
120 | public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
121 | PrintWriter out = setCorsAndGetWriter(httpServletRequest, httpServletResponse);
122 | out.write("{\"status\":\"success\"}");
123 | out.flush();
124 | out.close();
125 | }
126 | })
127 | .permitAll()
128 | .and().csrf().disable().exceptionHandling().accessDeniedHandler(new AccessDeniedHandler() {
129 | @Override
130 | public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
131 | PrintWriter out = setCorsAndGetWriter(httpServletRequest, httpServletResponse);
132 | out.write("{\"status\":\"deny\"}");
133 | out.flush();
134 | out.close();
135 | }
136 | });
137 |
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/WQMS/src/main/java/cn/edu/njupt/sctpan/wqms/controller/ErrorController.java:
--------------------------------------------------------------------------------
1 | package cn.edu.njupt.sctpan.wqms.controller;
2 |
3 | import cn.edu.njupt.sctpan.wqms.service.UserService;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 | import org.springframework.web.bind.annotation.GetMapping;
6 | import org.springframework.web.bind.annotation.RequestMapping;
7 | import org.springframework.web.bind.annotation.RestController;
8 |
9 | import java.util.HashMap;
10 | import java.util.Map;
11 |
12 | @RestController
13 | @RequestMapping("/status")
14 | public class ErrorController {
15 |
16 | @Autowired
17 | private UserService userService;
18 |
19 | @GetMapping("/noLogin")
20 | public Map noLogin() {
21 | Map resp = new HashMap<>();
22 | resp.put("status", "noLogin");
23 | return resp;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/WQMS/src/main/java/cn/edu/njupt/sctpan/wqms/controller/UserController.java:
--------------------------------------------------------------------------------
1 | package cn.edu.njupt.sctpan.wqms.controller;
2 |
3 |
4 | import cn.edu.njupt.sctpan.wqms.model.User;
5 | import cn.edu.njupt.sctpan.wqms.service.UserService;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.web.bind.annotation.*;
8 |
9 | import java.util.HashMap;
10 | import java.util.List;
11 | import java.util.Map;
12 |
13 | @RestController
14 | @RequestMapping("/user")
15 | public class UserController {
16 | @Autowired
17 | private UserService userService;
18 |
19 | @GetMapping("/current")
20 | public User getCurrentUser() {
21 | return userService.getCurrentUser();
22 | }
23 |
24 | @PostMapping("/editPassword/{id}")
25 | public Map editPassword(String originPassword, String newPassword, @PathVariable("id") int id) {
26 | Map resp = new HashMap<>();
27 | if(userService.checkPassword(originPassword, id)) {
28 | if(userService.editPassword(newPassword, id)) {
29 | resp.put("status", "success");
30 | } else {
31 | resp.put("status", "failure");
32 | }
33 | } else {
34 | resp.put("status", "error");
35 | }
36 | return resp;
37 | }
38 |
39 | @GetMapping("/all")
40 | public List getAllUsers() {
41 | return userService.getAllUsers();
42 | }
43 |
44 | @PostMapping("/grant/{id}")
45 | public Map grantAuthority(@PathVariable int id, String roleName) {
46 | Map resp = new HashMap<>();
47 | if(userService.grantAuthority(id, roleName)) {
48 | resp.put("status", "success");
49 | } else {
50 | resp.put("status", "failure");
51 | }
52 | return resp;
53 | }
54 |
55 | @PostMapping("/delete/{id}")
56 | public Map delete(@PathVariable int id) {
57 | Map resp = new HashMap<>();
58 | if(userService.delete(id)) {
59 | resp.put("status", "success");
60 | } else {
61 | resp.put("status", "failure");
62 | }
63 | return resp;
64 | }
65 |
66 | @PostMapping("/register")
67 | public Map register(String username, String password) {
68 | Map resp = new HashMap<>();
69 | if(userService.exists(username)) {
70 | resp.put("status", "duplicate");
71 | } else {
72 | if(userService.register(username, password)) {
73 | resp.put("status", "success");
74 | } else {
75 | resp.put("status", "failure");
76 | }
77 | }
78 | return resp;
79 | }
80 |
81 | @GetMapping("/query")
82 | public List getQueriedUsers(String username) {
83 | return userService.getQueriedUsers(username);
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/WQMS/src/main/java/cn/edu/njupt/sctpan/wqms/model/Model.java:
--------------------------------------------------------------------------------
1 | package cn.edu.njupt.sctpan.wqms.model;
2 |
3 | import com.fasterxml.jackson.annotation.JsonIgnore;
4 |
5 | import javax.persistence.*;
6 | import java.io.Serializable;
7 | import java.util.Date;
8 |
9 | @Entity
10 | @Table(name = "model")
11 | public class Model implements Serializable {
12 | @Id
13 | @GeneratedValue(strategy = GenerationType.IDENTITY)
14 | private Integer id;
15 | private String name;
16 | private String target;
17 | private String method;
18 | private Date date;
19 | private Float rmse;
20 |
21 | @ManyToOne
22 | @JoinColumn(name = "uid")
23 | private User user;
24 |
25 | public Integer getId() {
26 | return id;
27 | }
28 |
29 | public void setId(Integer id) {
30 | this.id = id;
31 | }
32 |
33 | public String getName() {
34 | return name;
35 | }
36 |
37 | public void setName(String name) {
38 | this.name = name;
39 | }
40 |
41 | public String getTarget() {
42 | return target;
43 | }
44 |
45 | public void setTarget(String target) {
46 | this.target = target;
47 | }
48 |
49 | public Date getDate() {
50 | return date;
51 | }
52 |
53 | public void setDate(Date date) {
54 | this.date = date;
55 | }
56 |
57 | public Float getRmse() {
58 | return rmse;
59 | }
60 |
61 | public void setRmse(Float rmse) {
62 | this.rmse = rmse;
63 | }
64 |
65 | public User getUser() {
66 | return user;
67 | }
68 |
69 | public void setUser(User user) {
70 | this.user = user;
71 | }
72 |
73 | public String getMethod() {
74 | return method;
75 | }
76 |
77 | public void setMethod(String method) {
78 | this.method = method;
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/WQMS/src/main/java/cn/edu/njupt/sctpan/wqms/model/Role.java:
--------------------------------------------------------------------------------
1 | package cn.edu.njupt.sctpan.wqms.model;
2 |
3 | import com.fasterxml.jackson.annotation.JsonIgnore;
4 | import org.hibernate.annotations.GeneratorType;
5 |
6 | import javax.persistence.*;
7 | import java.util.HashSet;
8 | import java.util.Set;
9 |
10 | @Entity
11 | @Table(name = "role")
12 | public class Role {
13 | @Id
14 | @GeneratedValue(strategy = GenerationType.IDENTITY)
15 | private Integer id;
16 | private String name;
17 |
18 |
19 | @JsonIgnore
20 | @OneToMany(cascade = CascadeType.ALL, mappedBy = "role")
21 | private Set users;
22 |
23 | public Integer getId() {
24 | return id;
25 | }
26 |
27 | public void setId(Integer id) {
28 | this.id = id;
29 | }
30 |
31 | public String getName() {
32 | return name;
33 | }
34 |
35 | public void setName(String name) {
36 | this.name = name;
37 | }
38 |
39 | public Set getUsers() {
40 | if(users == null) {
41 | return new HashSet();
42 | }
43 | return users;
44 | }
45 |
46 | public void setUsers(Set users) {
47 | this.users = users;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/WQMS/src/main/java/cn/edu/njupt/sctpan/wqms/model/User.java:
--------------------------------------------------------------------------------
1 | package cn.edu.njupt.sctpan.wqms.model;
2 |
3 | import com.fasterxml.jackson.annotation.JsonIgnore;
4 | import org.springframework.security.core.GrantedAuthority;
5 | import org.springframework.security.core.authority.SimpleGrantedAuthority;
6 | import org.springframework.security.core.userdetails.UserDetails;
7 |
8 | import javax.persistence.*;
9 | import java.io.Serializable;
10 | import java.util.*;
11 |
12 | @Entity
13 | @Table(name = "user")
14 | public class User implements Serializable, UserDetails {
15 | @Id
16 | @GeneratedValue(strategy = GenerationType.IDENTITY)
17 | private Integer id;
18 | private String username;
19 | @JsonIgnore
20 | private String password;
21 |
22 | @JsonIgnore
23 | @OneToMany(cascade = CascadeType.ALL, mappedBy = "user")
24 | private Set models;
25 |
26 | @ManyToOne
27 | @JoinColumn(name = "rid")
28 | private Role role;
29 |
30 | public Integer getId() {
31 | return id;
32 | }
33 |
34 | public void setId(Integer id) {
35 | this.id = id;
36 | }
37 |
38 | public String getUsername() {
39 | return username;
40 | }
41 |
42 | @Override
43 | public boolean isAccountNonExpired() {
44 | return true;
45 | }
46 |
47 | @Override
48 | public boolean isAccountNonLocked() {
49 | return true;
50 | }
51 |
52 | @Override
53 | public boolean isCredentialsNonExpired() {
54 | return true;
55 | }
56 |
57 | @Override
58 | public boolean isEnabled() {
59 | return true;
60 | }
61 |
62 | public void setUsername(String username) {
63 | this.username = username;
64 | }
65 |
66 | @Override
67 | public Collection extends GrantedAuthority> getAuthorities() {
68 | List authorities = new ArrayList<>();
69 | authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getName()));
70 | return authorities;
71 | }
72 |
73 | public String getPassword() {
74 | return password;
75 | }
76 |
77 | public void setPassword(String password) {
78 | this.password = password;
79 | }
80 |
81 |
82 | @Override
83 | public String toString() {
84 | return "User{" +
85 | "id=" + id +
86 | ", username='" + username + '\'' +
87 | ", password='" + password + '\'' +
88 | '}';
89 | }
90 |
91 | public Set getModels() {
92 | if(models == null) {
93 | models = new HashSet<>();
94 | }
95 | return models;
96 | }
97 |
98 | public void setModels(Set models) {
99 | this.models = models;
100 | }
101 |
102 | public Role getRole() {
103 | return role;
104 | }
105 |
106 | public void setRole(Role role) {
107 | this.role = role;
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/WQMS/src/main/java/cn/edu/njupt/sctpan/wqms/model/WaterQuality.java:
--------------------------------------------------------------------------------
1 | package cn.edu.njupt.sctpan.wqms.model;
2 |
3 | import com.fasterxml.jackson.annotation.JsonIgnore;
4 | import net.bytebuddy.dynamic.loading.InjectionClassLoader;
5 |
6 | import javax.persistence.*;
7 | import java.io.Serializable;
8 | import java.util.Date;
9 |
10 | @Entity
11 | @Table(name = "waterquality")
12 | public class WaterQuality implements Serializable {
13 | @Id
14 | @GeneratedValue(strategy = GenerationType.IDENTITY)
15 | private Integer id;
16 | private Float PH;
17 | private Float DO;
18 | private Float NH3N;
19 | private Date date;
20 | private Integer station;
21 |
22 | @Override
23 | public String toString() {
24 | return "WaterQuality{" +
25 | "id=" + id +
26 | ", PH=" + PH +
27 | ", DO=" + DO +
28 | ", NH3N=" + NH3N +
29 | ", date=" + date +
30 | ", station=" + station +
31 | '}';
32 | }
33 |
34 | public Integer getId() {
35 | return id;
36 | }
37 |
38 | public void setId(Integer id) {
39 | this.id = id;
40 | }
41 |
42 | public Float getPH() {
43 | return PH;
44 | }
45 |
46 | public void setPH(Float PH) {
47 | this.PH = PH;
48 | }
49 |
50 | public Float getDO() {
51 | return DO;
52 | }
53 |
54 | public void setDO(Float DO) {
55 | this.DO = DO;
56 | }
57 |
58 | public Float getNH3N() {
59 | return NH3N;
60 | }
61 |
62 | public void setNH3N(Float NH3N) {
63 | this.NH3N = NH3N;
64 | }
65 |
66 | public Date getDate() {
67 | return date;
68 | }
69 |
70 | public void setDate(Date date) {
71 | this.date = date;
72 | }
73 |
74 | public Integer getStation() {
75 | return station;
76 | }
77 |
78 | public void setStation(Integer station) {
79 | this.station = station;
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/WQMS/src/main/java/cn/edu/njupt/sctpan/wqms/model/WaterQualityHelper.java:
--------------------------------------------------------------------------------
1 | package cn.edu.njupt.sctpan.wqms.model;
2 |
3 | import java.text.DateFormat;
4 | import java.text.ParseException;
5 |
6 | public class WaterQualityHelper {
7 |
8 | private Integer id;
9 | private Float PH;
10 | private Float DO;
11 | private Float NH3N;
12 | private String date;
13 | private Integer station;
14 |
15 |
16 | public Integer getId() {
17 | return id;
18 | }
19 |
20 | public void setId(Integer id) {
21 | this.id = id;
22 | }
23 |
24 | public Float getPH() {
25 | return PH;
26 | }
27 |
28 | public void setPH(Float PH) {
29 | this.PH= PH;
30 | }
31 |
32 | public Float getDO() {
33 | return DO;
34 | }
35 |
36 | public void setDO(Float DO) {
37 | this.DO = DO;
38 | }
39 |
40 | public Float getNH3N() {
41 | return NH3N;
42 | }
43 |
44 | public void setNH3N(Float NH3N) {
45 | this.NH3N = NH3N;
46 | }
47 |
48 | public String getDate() {
49 | return date;
50 | }
51 |
52 | public void setDate(String date) {
53 | this.date = date;
54 | }
55 |
56 | public Integer getStation() {
57 | return station;
58 | }
59 |
60 | public void setStation(Integer station) {
61 | this.station = station;
62 | }
63 |
64 | public WaterQuality convert() {
65 | WaterQuality waterQuality = new WaterQuality();
66 | DateFormat dateFormat = DateFormat.getDateInstance();
67 | try {
68 | waterQuality.setDate(dateFormat.parse(date));
69 | } catch (ParseException e) {
70 | e.printStackTrace();
71 | return null;
72 | }
73 | waterQuality.setPH(PH);
74 | waterQuality.setNH3N(NH3N);
75 | waterQuality.setDO(DO);
76 | waterQuality.setStation(station);
77 | return waterQuality;
78 | }
79 |
80 | @Override
81 | public String toString() {
82 | return "WaterQualityHelper{" +
83 | "id=" + id +
84 | ", PH=" + PH +
85 | ", DO=" + DO +
86 | ", NH3N=" + NH3N +
87 | ", date='" + date + '\'' +
88 | ", station=" + station +
89 | '}';
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/WQMS/src/main/java/cn/edu/njupt/sctpan/wqms/repository/ModelRepository.java:
--------------------------------------------------------------------------------
1 | package cn.edu.njupt.sctpan.wqms.repository;
2 |
3 | import cn.edu.njupt.sctpan.wqms.model.Model;
4 | import org.springframework.data.jpa.repository.Query;
5 | import org.springframework.data.repository.Repository;
6 |
7 | import java.util.List;
8 |
9 | public interface ModelRepository extends Repository {
10 | public Model save(Model model);
11 | public List findModelByTargetOrderByRmseAsc(String target);
12 | public List findModelByTargetAndMethodOrderByRmseAsc(String target, String method);
13 | public void delete(Model model);
14 | @Query("select distinct method from Model m where m.target = ?1")
15 | public List findAllModelsByTarget(String target);
16 | public Model findModelById(Integer id);
17 | }
18 |
--------------------------------------------------------------------------------
/WQMS/src/main/java/cn/edu/njupt/sctpan/wqms/repository/RoleRepository.java:
--------------------------------------------------------------------------------
1 | package cn.edu.njupt.sctpan.wqms.repository;
2 |
3 | import cn.edu.njupt.sctpan.wqms.model.Role;
4 | import org.springframework.data.repository.Repository;
5 |
6 | public interface RoleRepository extends Repository {
7 | public Role save(Role role);
8 | public Role findRoleByName(String name);
9 | }
10 |
--------------------------------------------------------------------------------
/WQMS/src/main/java/cn/edu/njupt/sctpan/wqms/repository/UserRepository.java:
--------------------------------------------------------------------------------
1 | package cn.edu.njupt.sctpan.wqms.repository;
2 |
3 | import cn.edu.njupt.sctpan.wqms.model.User;
4 | import org.springframework.data.repository.Repository;
5 |
6 | import java.util.List;
7 |
8 | public interface UserRepository extends Repository {
9 | public User findUserByUsername(String username);
10 | public User findUserById(Integer id);
11 | public User save(User user);
12 | public List findAll();
13 | public boolean existsUserByUsername(String username);
14 | public void deleteById(int id);
15 | public List findByUsernameContaining(String username);
16 | }
17 |
--------------------------------------------------------------------------------
/WQMS/src/main/java/cn/edu/njupt/sctpan/wqms/repository/WaterQualityRepository.java:
--------------------------------------------------------------------------------
1 | package cn.edu.njupt.sctpan.wqms.repository;
2 |
3 | import cn.edu.njupt.sctpan.wqms.model.WaterQuality;
4 | import org.springframework.data.domain.Pageable;
5 | import org.springframework.data.jpa.repository.Query;
6 | import org.springframework.data.repository.Repository;
7 |
8 | import java.util.Date;
9 | import java.util.List;
10 |
11 | public interface WaterQualityRepository extends Repository {
12 | public List findAllByOrderByDate();
13 | public void save(WaterQuality waterQuality);
14 | public void deleteById(Integer id);
15 | public List findByDateBetweenOrderByDate(Date start, Date end);
16 | public List findByDateBetweenAndStationOrderByDate(Date start, Date end, Integer station);
17 |
18 | @Query("select distinct station from WaterQuality")
19 | public List findAllStations();
20 | public List findByStationOrderByDateDesc(Integer station, Pageable pageable);
21 | public List findAllByOrderByDateDesc(Pageable pageable);
22 |
23 | @Query("select distinct DATE_FORMAT(date,'%Y-%m-%d') AS puredate from WaterQuality order by DATE_FORMAT(date,'%Y-%m-%d') desc")
24 | public List findLastDates(Pageable pageable);
25 |
26 | @Query("select w from WaterQuality w where w.date between ?1 and ?2")
27 | public List findBySpecificDate(Date start, Date end);
28 | }
29 |
--------------------------------------------------------------------------------
/WQMS/src/main/java/cn/edu/njupt/sctpan/wqms/service/ModelService.java:
--------------------------------------------------------------------------------
1 | package cn.edu.njupt.sctpan.wqms.service;
2 |
3 | import cn.edu.njupt.sctpan.wqms.model.Model;
4 | import cn.edu.njupt.sctpan.wqms.repository.ModelRepository;
5 | import cn.edu.njupt.sctpan.wqms.repository.UserRepository;
6 | import cn.edu.njupt.sctpan.wqms.repository.WaterQualityRepository;
7 | import com.fasterxml.jackson.databind.JsonNode;
8 | import com.fasterxml.jackson.databind.ObjectMapper;
9 | import org.apache.http.HttpEntity;
10 | import org.apache.http.HttpResponse;
11 | import org.apache.http.client.ClientProtocolException;
12 | import org.apache.http.client.HttpClient;
13 | import org.apache.http.client.methods.HttpGet;
14 | import org.apache.http.impl.client.HttpClients;
15 | import org.apache.http.util.EntityUtils;
16 | import org.springframework.beans.factory.annotation.Autowired;
17 | import org.springframework.stereotype.Service;
18 |
19 | import java.io.IOException;
20 | import java.text.DateFormat;
21 | import java.text.ParseException;
22 | import java.text.SimpleDateFormat;
23 | import java.util.*;
24 |
25 | @Service
26 | public class ModelService {
27 | @Autowired
28 | private ModelRepository modelRepository;
29 | @Autowired
30 | private UserRepository userRepository;
31 | @Autowired
32 | private WaterQualityService waterQualityService;
33 |
34 | private Map parseTrainingResponse(String response) {
35 | ObjectMapper objectMapper = new ObjectMapper();
36 | Map resp = new HashMap<>();
37 | Map data = new HashMap<>();
38 | JsonNode rootNode = null;
39 | try {
40 | rootNode = objectMapper.readTree(response);
41 | } catch (IOException e) {
42 | e.printStackTrace();
43 | resp.put("status", "failure");
44 | return resp;
45 | }
46 | String status = rootNode.path("status").asText();
47 | if(!status.equalsIgnoreCase("success")) {
48 | resp.put("status", "failure");
49 | return resp;
50 | }
51 | JsonNode dataNode = rootNode.path("data");
52 | Double rmse = dataNode.path("rmse").asDouble();
53 | List pred = new ArrayList<>();
54 | List real = new ArrayList<>();
55 | JsonNode predNode = dataNode.path("pred");
56 | JsonNode realNode = dataNode.path("real");
57 | for(int i=0; i parsePredictionResponse(String response) {
71 | ObjectMapper objectMapper = new ObjectMapper();
72 | Map resp = new HashMap<>();
73 | JsonNode rootNode = null;
74 | try {
75 | rootNode = objectMapper.readTree(response);
76 | } catch (IOException e) {
77 | e.printStackTrace();
78 | resp.put("status", "failure");
79 | return resp;
80 | }
81 | String status = rootNode.path("status").asText();
82 | if(status.equalsIgnoreCase("failure")) {
83 | resp.put("status", "failure");
84 | return resp;
85 | }
86 | JsonNode dataNode = rootNode.path("data");
87 | Double prediction = dataNode.path("pred").asDouble();
88 | resp.put("pred", prediction);
89 | return resp;
90 | }
91 |
92 | private String sendRequest(String url) {
93 | HttpClient httpclient = HttpClients.createDefault();
94 | HttpGet httpget = new HttpGet(url);
95 | String resp = null;
96 | try {
97 | HttpResponse response = httpclient.execute(httpget);
98 | HttpEntity entity = response.getEntity();
99 | if (entity != null) {
100 | resp = EntityUtils.toString(entity, "UTF-8").trim();
101 |
102 | }
103 | } catch (ClientProtocolException e) {
104 | e.printStackTrace();
105 | return null;
106 | } catch (IOException e) {
107 | e.printStackTrace();
108 | return null;
109 | } finally {
110 | httpget.abort();
111 | }
112 | return resp;
113 | }
114 |
115 | private Map sendTrainingRequest(int modelId) {
116 | String url = "http://localhost:8000/api/training?id=" + modelId;
117 | String jsonResp = sendRequest(url);
118 | return parseTrainingResponse(jsonResp);
119 | }
120 |
121 | private Map sendPredictionRequest(int modelId, String indicator) {
122 | Map map = waterQualityService.getDateForPrediction(indicator);
123 | List forPlot = (List) map.get("forPlot");
124 | List forPrediction = (List) map.get("forPrediction");
125 | List dates = (List) map.get("dates");
126 | String startDate = dates.get(2);
127 | DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
128 | dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
129 | Date date = null;
130 | try {
131 | date = dateFormat.parse(startDate);
132 | } catch (ParseException e) {
133 | e.printStackTrace();
134 | }
135 | Calendar calendar = Calendar.getInstance();
136 | calendar.setTime(date);
137 | int startMonth = calendar.get(Calendar.MONTH) + 1;
138 | String url = "http://localhost:8000/api/prediction?id=" + modelId;
139 | url = url + "&one=" + forPrediction.get(0) + "&two=" +
140 | forPrediction.get(1) + "&three=" + forPrediction.get(2) + "&startMonth=" + startMonth;
141 | System.out.println(url);
142 | String jsonResp = sendRequest(url);
143 | Map resp = parsePredictionResponse(jsonResp);
144 | Double d = (Double) resp.get("pred");
145 | forPlot.add(d.floatValue());
146 | calendar.add(Calendar.MONTH, 3);
147 | SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
148 | dates.add(df.format(calendar.getTime()));
149 | resp.put("forPlot", forPlot);
150 | resp.put("dates", dates);
151 | return resp;
152 | }
153 |
154 | public Map predictNextMonth(int modelId, String indicator) {
155 | Map resp = null;
156 | try {
157 | resp = sendPredictionRequest(modelId, indicator);
158 | } catch (RuntimeException e) {
159 | e.printStackTrace();
160 | resp = new HashMap<>();
161 | resp.put("status", "failure");
162 | return resp;
163 | }
164 | if(!resp.containsKey("status")) {
165 | resp.put("status", "success");
166 | }
167 | return resp;
168 | }
169 |
170 | public Map trainModel(String indicator, String method, Integer uid) {
171 | String modelName = indicator + "_" + method;
172 | Model model = new Model();
173 | Map resp = null;
174 | try {
175 | model.setDate(new Date());
176 | model.setName(modelName);
177 | model.setTarget(indicator);
178 | model.setMethod(method);
179 | model.setUser(userRepository.findUserById(uid));
180 | model = modelRepository.save(model);
181 | resp = sendTrainingRequest(model.getId());
182 | if(resp == null) {
183 | resp = new HashMap<>();
184 | resp.put("status", "failure");
185 | modelRepository.delete(model);
186 | } else {
187 | Map data = (Map)resp.get("data");
188 | Double rmse = (Double)data.get("rmse");
189 | model.setRmse(rmse.floatValue());
190 | modelRepository.save(model);
191 | }
192 | } catch (Exception e) {
193 | e.printStackTrace();
194 | resp = new HashMap<>();
195 | resp.put("status", "failure");
196 | modelRepository.delete(model);
197 | }
198 | if(!resp.containsKey("status")) {
199 | resp.put("status", "success");
200 | }
201 | return resp;
202 | }
203 |
204 | public List getAvailableModel(String indicator) {
205 | return modelRepository.findModelByTargetOrderByRmseAsc(indicator);
206 | }
207 |
208 | public List getAvailableModel(String indicator, String method) {
209 | return modelRepository.findModelByTargetAndMethodOrderByRmseAsc(indicator, method);
210 | }
211 |
212 | public Boolean deleteModel(int id) {
213 | try {
214 | Model model = modelRepository.findModelById(id);
215 | modelRepository.delete(model);
216 | } catch (Exception e) {
217 | return false;
218 | }
219 | return true;
220 | }
221 |
222 | public List getAllModelsByTarget(String target) {
223 | return modelRepository.findAllModelsByTarget(target);
224 | }
225 | }
226 |
--------------------------------------------------------------------------------
/WQMS/src/main/java/cn/edu/njupt/sctpan/wqms/service/UserService.java:
--------------------------------------------------------------------------------
1 | package cn.edu.njupt.sctpan.wqms.service;
2 |
3 | import cn.edu.njupt.sctpan.wqms.model.Role;
4 | import cn.edu.njupt.sctpan.wqms.model.User;
5 | import cn.edu.njupt.sctpan.wqms.repository.RoleRepository;
6 | import cn.edu.njupt.sctpan.wqms.repository.UserRepository;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.security.core.context.SecurityContextHolder;
9 | import org.springframework.security.core.userdetails.UserDetails;
10 | import org.springframework.security.core.userdetails.UserDetailsService;
11 | import org.springframework.security.core.userdetails.UsernameNotFoundException;
12 | import org.springframework.stereotype.Service;
13 | import org.springframework.util.DigestUtils;
14 |
15 | import java.util.List;
16 |
17 | @Service
18 | public class UserService implements UserDetailsService {
19 | @Autowired
20 | private UserRepository userRepository;
21 |
22 | @Autowired
23 | private RoleRepository roleRepository;
24 |
25 | @Override
26 | public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
27 | User user = userRepository.findUserByUsername(s);
28 | if(user == null) {
29 | return new User();
30 | }
31 | return user;
32 | }
33 |
34 | public Boolean addUser(User user) {
35 | try {
36 | userRepository.save(user);
37 | } catch (Exception e) {
38 | return false;
39 | }
40 | return true;
41 | }
42 |
43 | public User getCurrentUser() {
44 | User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
45 | return user;
46 | }
47 |
48 | public Boolean editPassword(String password, int id) {
49 | try{
50 | User user = userRepository.findUserById(id);
51 | user.setPassword(DigestUtils.md5DigestAsHex(password.getBytes()));
52 | userRepository.save(user);
53 | return true;
54 | } catch (Exception e) {
55 | e.printStackTrace();
56 | return false;
57 | }
58 | }
59 |
60 | public Boolean checkPassword(String password, int id) {
61 | User user = userRepository.findUserById(id);
62 | if(user.getPassword().equals(DigestUtils.md5DigestAsHex(password.getBytes()))) {
63 | return true;
64 | } else {
65 | return false;
66 | }
67 | }
68 |
69 | public List getAllUsers() {
70 | return userRepository.findAll();
71 | }
72 |
73 | public Boolean grantAuthority(int uid, String roleName) {
74 | try {
75 | Role role = roleRepository.findRoleByName(roleName);
76 | User user = userRepository.findUserById(uid);
77 | user.setRole(role);
78 | userRepository.save(user);
79 | return true;
80 | } catch (Exception e){
81 | e.printStackTrace();
82 | return false;
83 | }
84 | }
85 |
86 | public Boolean exists(String username) {
87 | return userRepository.existsUserByUsername(username);
88 | }
89 |
90 | public Boolean register(String username, String password) {
91 | try {
92 | String encodedPassword = DigestUtils.md5DigestAsHex(password.getBytes());
93 | User user = new User();
94 | user.setUsername(username);
95 | user.setPassword(encodedPassword);
96 | user.setRole(roleRepository.findRoleByName("user"));
97 | userRepository.save(user);
98 | return true;
99 | } catch (Exception e) {
100 | e.printStackTrace();
101 | return false;
102 | }
103 | }
104 |
105 | public Boolean delete(int id) {
106 | try {
107 | userRepository.deleteById(id);
108 | return true;
109 | } catch (Exception e) {
110 | e.printStackTrace();
111 | return false;
112 | }
113 | }
114 |
115 | public List getQueriedUsers(String username) {
116 | return userRepository.findByUsernameContaining(username);
117 | }
118 |
119 | }
120 |
--------------------------------------------------------------------------------
/WQMS/src/main/java/cn/edu/njupt/sctpan/wqms/service/WaterQualityService.java:
--------------------------------------------------------------------------------
1 | package cn.edu.njupt.sctpan.wqms.service;
2 |
3 | import cn.edu.njupt.sctpan.wqms.model.WaterQuality;
4 | import cn.edu.njupt.sctpan.wqms.repository.WaterQualityRepository;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.data.domain.PageRequest;
7 | import org.springframework.data.domain.Pageable;
8 | import org.springframework.stereotype.Service;
9 |
10 | import java.math.BigDecimal;
11 | import java.text.DateFormat;
12 | import java.text.ParseException;
13 | import java.text.SimpleDateFormat;
14 | import java.util.*;
15 |
16 | @Service
17 | public class WaterQualityService {
18 | @Autowired
19 | private WaterQualityRepository waterQualityRepository;
20 |
21 | public List findAllWaterQualities() {
22 | List res = waterQualityRepository.findAllByOrderByDate();
23 | return res;
24 | }
25 |
26 | public List findQueriedWaterQualities(String startDateStr, String endDateStr, Integer station) {
27 | DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
28 | Date startDate = null;
29 | Date endDate = null;
30 | try {
31 | startDate = df.parse(startDateStr);
32 | endDate = df.parse(endDateStr);
33 | } catch (ParseException e) {
34 | e.printStackTrace();
35 | }
36 | if(station == -1) {
37 | return waterQualityRepository.findByDateBetweenOrderByDate(startDate, endDate);
38 | }
39 | return waterQualityRepository.findByDateBetweenAndStationOrderByDate(startDate, endDate, station);
40 | }
41 |
42 | public Boolean updateWaterQuality(WaterQuality waterQuality) {
43 | try {
44 | waterQualityRepository.save(waterQuality);
45 | } catch (RuntimeException e) {
46 | e.printStackTrace();
47 | return false;
48 | }
49 | return true;
50 | }
51 |
52 | public Boolean deleteWaterQuality(Integer id) {
53 | try {
54 | waterQualityRepository.deleteById(id);
55 | } catch (RuntimeException e) {
56 | e.printStackTrace();
57 | return false;
58 | }
59 | return true;
60 | }
61 |
62 | public Boolean addWaterQuality(WaterQuality waterQuality) {
63 | try {
64 | waterQualityRepository.save(waterQuality);
65 | } catch (RuntimeException e) {
66 | e.printStackTrace();
67 | return false;
68 | }
69 | return true;
70 | }
71 |
72 | public List getAllStations() {
73 | return waterQualityRepository.findAllStations();
74 | }
75 |
76 | public Map getDataForPlot(int station, int period, String indicator) {
77 | Pageable pageable = PageRequest.of(0, period * 12);
78 | List total = waterQualityRepository.findByStationOrderByDateDesc(station, pageable);
79 | List specWaterQualities = new ArrayList<>();
80 | List dates = new ArrayList<>();
81 | for(WaterQuality waterQuality : total) {
82 | Calendar calendar = Calendar.getInstance();
83 | calendar.setTime(waterQuality.getDate());
84 | String dateStr = calendar.get(Calendar.YEAR) + "-" + (calendar.get(Calendar.MONTH) + 1);
85 | dates.add(dateStr);
86 | if(indicator.equalsIgnoreCase("ph")) {
87 | specWaterQualities.add(waterQuality.getPH());
88 | } else if(indicator.equalsIgnoreCase("do")) {
89 | specWaterQualities.add(waterQuality.getDO());
90 | } else {
91 | specWaterQualities.add(waterQuality.getNH3N());
92 | }
93 | }
94 | Collections.reverse(specWaterQualities);
95 | Collections.reverse(dates);
96 | Map res = new HashMap<>();
97 | res.put("waterquality", specWaterQualities);
98 | res.put("dates", dates);
99 | return res;
100 | }
101 |
102 | public Map getMeanDataForPredictionPlot(String indicator) {
103 | return null;
104 | }
105 |
106 | public List getRecentWaterQualities(int num) {
107 | Pageable pageable = PageRequest.of(0, num);
108 | List recent = waterQualityRepository.findAllByOrderByDateDesc(pageable);
109 | return recent;
110 | }
111 |
112 | public Map getDateForPrediction(String indicator) {
113 | Map res = new HashMap<>();
114 | Pageable pageable = PageRequest.of(0, 5);
115 | List dateStrs = waterQualityRepository.findLastDates(pageable);
116 | // for(String dateStr : dateStrs) {
117 | // DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
118 | // dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
119 | // try {
120 | // System.out.println("parsed date: " + dateFormat.parse(dateStr));
121 | // } catch (ParseException e){
122 | // e.printStackTrace();
123 | // }
124 | //
125 | // }
126 | List forPlot = new ArrayList<>();
127 | List forPrediction = new ArrayList<>();
128 | for(String dateStr : dateStrs) {
129 | List waterQualitiesByDate = getWaterQaulitiesBySpecificDate(dateStr);
130 | //System.out.println("size: " + waterQualitiesByDate.size());
131 | Float average = calAverage(indicator, waterQualitiesByDate);
132 | BigDecimal bigDecimal = new BigDecimal(average);
133 | forPlot.add(bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP).floatValue());
134 | }
135 | for(int i=0; i<3; i++) {
136 | forPrediction.add(forPlot.get(i));
137 | }
138 | Collections.reverse(dateStrs);
139 | Collections.reverse(forPlot);
140 | Collections.reverse(forPrediction);
141 | res.put("dates", dateStrs);
142 | res.put("forPlot", forPlot);
143 | res.put("forPrediction", forPrediction);
144 | return res;
145 | }
146 |
147 | private float calAverage(String indicator, List waterQualities) {
148 | float sum = 0;
149 | for (WaterQuality waterQuality : waterQualities) {
150 | if(indicator.equalsIgnoreCase("PH")) {
151 | sum = sum + waterQuality.getPH();
152 | } else if(indicator.equalsIgnoreCase("DO")) {
153 | sum = sum + waterQuality.getDO();
154 | } else {
155 | sum = sum + waterQuality.getNH3N();
156 | }
157 | }
158 | return sum / waterQualities.size();
159 | }
160 |
161 | private List getWaterQaulitiesBySpecificDate(String dateStr) {
162 | String startDateStr = dateStr + " 00:00:00";
163 | String endDateStr = dateStr + " 23:59:59";
164 | System.out.println(startDateStr);
165 | DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
166 | dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
167 | Date startDate = null;
168 | Date endDate = null;
169 | try {
170 | startDate = dateFormat.parse(startDateStr);
171 | System.out.println("startDate: " + startDate);
172 | endDate = dateFormat.parse(endDateStr);
173 | System.out.println("endDate: " + endDate);
174 | } catch (ParseException e) {
175 | e.printStackTrace();
176 | }
177 | List res = waterQualityRepository.findBySpecificDate(startDate, endDate);
178 | System.out.println("specific dates size: " + res.size());
179 | return res;
180 | }
181 |
182 | }
183 |
--------------------------------------------------------------------------------
/WQMS/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | #通用数据源配置
2 | spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
3 | # spring.datasource.url=jdbc:mysql://cdb-9tkqohpo.bj.tencentcdb.com:10099/water?serverTimezone=CTT
4 | spring.datasource.url=jdbc:mysql://127.0.0.1:3306/water?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8
5 | spring.datasource.username=root
6 | spring.datasource.password=123456
7 | # Hikari 数据源专用配置
8 |
9 | spring.datasource.hikari.minimum-idle=3
10 | spring.datasource.hikari.maximum-pool-size=10
11 | spring.datasource.hikari.max-lifetime = 30000
12 | spring.datasource.hikari.connection-test-query=SELECT 1
13 |
14 | # JPA 相关配置
15 | spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
16 | spring.jpa.show-sql=true
17 | spring.jpa.hibernate.ddl-auto=update
18 |
19 |
20 | logging.level.org.springframework.security=ERROR
21 |
22 |
--------------------------------------------------------------------------------
/WQMS/src/test/java/cn/edu/njupt/sctpan/wqms/WqmsApplicationTests.java:
--------------------------------------------------------------------------------
1 | package cn.edu.njupt.sctpan.wqms;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.test.context.junit4.SpringRunner;
7 |
8 | @RunWith(SpringRunner.class)
9 | @SpringBootTest
10 | public class WqmsApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/WQMS/src/test/java/cn/edu/njupt/sctpan/wqms/repository/RoleRepositoryTest.java:
--------------------------------------------------------------------------------
1 | package cn.edu.njupt.sctpan.wqms.repository;
2 |
3 | import cn.edu.njupt.sctpan.wqms.model.Role;
4 | import cn.edu.njupt.sctpan.wqms.model.User;
5 | import org.junit.Test;
6 | import org.junit.runner.RunWith;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.boot.test.context.SpringBootTest;
9 | import org.springframework.test.context.junit4.SpringRunner;
10 |
11 | @RunWith(SpringRunner.class)
12 | @SpringBootTest
13 | public class RoleRepositoryTest {
14 | @Autowired
15 | private RoleRepository roleRepository;
16 |
17 | @Autowired
18 | private UserRepository userRepository;
19 |
20 | @Test
21 | public void saveRole() {
22 | Role role = new Role();
23 | role.setName("admin");
24 | User user = userRepository.findUserById(1);
25 | user.setRole(role);
26 | roleRepository.save(role);
27 | userRepository.save(user);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/WQMS/src/test/java/cn/edu/njupt/sctpan/wqms/repository/UserRepositoryTest.java:
--------------------------------------------------------------------------------
1 | package cn.edu.njupt.sctpan.wqms.repository;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.boot.test.context.SpringBootTest;
7 | import org.springframework.test.context.junit4.SpringRunner;
8 |
9 | @RunWith(SpringRunner.class)
10 | @SpringBootTest
11 | public class UserRepositoryTest {
12 | @Autowired
13 | private UserRepository userRepository;
14 | @Test
15 | public void findUserById() {
16 | int id = 1;
17 | System.out.println(userRepository.findUserById(id));
18 | }
19 |
20 | @Test
21 | public void findUserByName() {
22 |
23 | }
24 |
25 |
26 | }
--------------------------------------------------------------------------------
/WQMS/src/test/java/cn/edu/njupt/sctpan/wqms/repository/WaterQualityRepositoryTest.java:
--------------------------------------------------------------------------------
1 | package cn.edu.njupt.sctpan.wqms.repository;
2 |
3 | import cn.edu.njupt.sctpan.wqms.model.WaterQuality;
4 | import org.junit.Test;
5 | import org.junit.runner.RunWith;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.boot.test.context.SpringBootTest;
8 | import org.springframework.data.domain.PageRequest;
9 | import org.springframework.data.domain.Pageable;
10 | import org.springframework.test.context.junit4.SpringRunner;
11 |
12 | import java.text.DateFormat;
13 | import java.text.ParseException;
14 | import java.text.SimpleDateFormat;
15 | import java.util.Calendar;
16 | import java.util.Collections;
17 | import java.util.Date;
18 | import java.util.List;
19 |
20 | @RunWith(SpringRunner.class)
21 | @SpringBootTest
22 | public class WaterQualityRepositoryTest {
23 | @Autowired
24 | private WaterQualityRepository waterQualityRepository;
25 | @Test
26 | public void findByDateBetweenAndStation() {
27 | Date start = null;
28 | Date end = null;
29 | try {
30 | start = DateFormat.getDateInstance().parse("2002-01-22");
31 | end = DateFormat.getDateInstance().parse("2006-10-22");
32 | } catch (Exception e) {
33 | e.printStackTrace();
34 | }
35 | List res = waterQualityRepository
36 | .findByDateBetweenAndStationOrderByDate(start, end, 8);
37 | for(WaterQuality waterQuality : res) {
38 | System.out.println(waterQuality);
39 | }
40 | }
41 |
42 | @Test
43 | public void findAllStations() {
44 | List stations = waterQualityRepository.findAllStations();
45 | for(Integer station : stations) {
46 | System.out.println(station);
47 | }
48 | }
49 |
50 | @Test
51 | public void findByStationOrderByDateDesc() {
52 | Pageable p = PageRequest.of(0, 12);
53 | List res = waterQualityRepository.findByStationOrderByDateDesc(5, p);
54 | Collections.reverse(res);
55 | for(WaterQuality waterQuality : res) {
56 | System.out.println(waterQuality);
57 | }
58 | }
59 |
60 | @Test
61 | public void findLastDates() {
62 | Pageable p = PageRequest.of(0, 5);
63 | List res = waterQualityRepository.findLastDates(p);
64 | for(String s : res) {
65 | System.out.println(s);
66 | }
67 | }
68 |
69 | @Test
70 | public void findBySpecificDate() {
71 | String dateStr = "2006-11-01";
72 | String startDateStr = "2006-11-01" + " 00:00:00";
73 | String endDateStr = "2006-12-01" + " 23:59:59";
74 | DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
75 | Date startDate = null;
76 | Date endDate = null;
77 | try {
78 | startDate = dateFormat.parse(startDateStr);
79 | endDate = dateFormat.parse(endDateStr);
80 | } catch (ParseException e) {
81 | e.printStackTrace();
82 | }
83 | System.out.println(startDateStr);
84 | System.out.println(endDateStr);
85 | List res = waterQualityRepository.findBySpecificDate(startDate, endDate);
86 | for (WaterQuality waterQuality : res) {
87 | System.out.println("water quality: " + waterQuality);
88 | }
89 | }
90 | }
--------------------------------------------------------------------------------
/WQMS/src/test/java/cn/edu/njupt/sctpan/wqms/security/SecurityTest.java:
--------------------------------------------------------------------------------
1 | package cn.edu.njupt.sctpan.wqms.security;
2 |
3 |
4 | import org.junit.Test;
5 | import org.springframework.util.DigestUtils;
6 |
7 | public class SecurityTest {
8 | @Test
9 | public void md5Test() {
10 | String password = "123";
11 | System.out.println(DigestUtils.md5DigestAsHex(password.getBytes()));
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/WQMS/src/test/java/cn/edu/njupt/sctpan/wqms/service/ModelServiceTest.java:
--------------------------------------------------------------------------------
1 | package cn.edu.njupt.sctpan.wqms.service;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.boot.test.context.SpringBootTest;
7 | import org.springframework.test.context.junit4.SpringRunner;
8 |
9 | import java.text.DateFormat;
10 | import java.text.ParseException;
11 | import java.util.Calendar;
12 | import java.util.Date;
13 |
14 | @RunWith(SpringRunner.class)
15 | @SpringBootTest
16 | public class ModelServiceTest {
17 | @Autowired
18 | private ModelService modelService;
19 |
20 | @Test
21 | public void trainModel() {
22 | String indicator = "DO";
23 | String method = "SVM";
24 | int uid = 1;
25 | modelService.trainModel(indicator, method, uid);
26 | }
27 | }
--------------------------------------------------------------------------------
/WQMS/src/test/java/cn/edu/njupt/sctpan/wqms/service/UserServiceTest.java:
--------------------------------------------------------------------------------
1 | package cn.edu.njupt.sctpan.wqms.service;
2 |
3 | import cn.edu.njupt.sctpan.wqms.model.User;
4 | import cn.edu.njupt.sctpan.wqms.repository.RoleRepository;
5 | import org.junit.Test;
6 | import org.junit.runner.RunWith;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.boot.test.context.SpringBootTest;
9 | import org.springframework.test.context.junit4.SpringRunner;
10 | import org.springframework.util.DigestUtils;
11 |
12 | @RunWith(SpringRunner.class)
13 | @SpringBootTest
14 | public class UserServiceTest {
15 | @Autowired
16 | private UserService userService;
17 | @Autowired
18 | private RoleRepository roleRepository;
19 |
20 | @Test
21 | public void addUser() {
22 | User user = new User();
23 | String password = "1234";
24 | user.setRole(roleRepository.findRoleByName("user"));
25 | user.setUsername("user1");
26 | user.setPassword(DigestUtils.md5DigestAsHex(password.getBytes()));
27 | System.out.println(userService.addUser(user));
28 | }
29 | }
--------------------------------------------------------------------------------
/WQMS/src/test/java/cn/edu/njupt/sctpan/wqms/service/WaterQualityServiceTest.java:
--------------------------------------------------------------------------------
1 | package cn.edu.njupt.sctpan.wqms.service;
2 |
3 | import cn.edu.njupt.sctpan.wqms.model.WaterQuality;
4 | import org.junit.Test;
5 | import org.junit.runner.RunWith;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.boot.test.context.SpringBootTest;
8 | import org.springframework.test.context.junit4.SpringRunner;
9 |
10 | import java.util.List;
11 |
12 | @RunWith(SpringRunner.class)
13 | @SpringBootTest
14 | public class WaterQualityServiceTest {
15 | @Autowired
16 | private WaterQualityService waterQualityService;
17 | @Test
18 | public void findAllWaterQualities() {
19 | List res = waterQualityService.findAllWaterQualities();
20 | for(WaterQuality waterQuality : res) {
21 | System.out.println(waterQuality);
22 | }
23 | }
24 |
25 | }
--------------------------------------------------------------------------------
/WQPS/.idea/WQPS.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/WQPS/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/WQPS/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/WQPS/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/WQPS/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/WQPS/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/WQPS/Dockerfile:
--------------------------------------------------------------------------------
1 | # set the base image
2 | FROM python:3.6
3 | #add project files
4 | ADD WQPS WQPS
5 | ADD predicter predicter
6 | ADD Model Model
7 | COPY requirements.txt ./
8 | COPY manage.py ./
9 | # Get pip to download and install requirements:
10 | RUN pip install -r requirements.txt
11 | RUN pip install https://github.com/JamesRitchie/scikit-rvm/archive/master.zip
12 | # Expose ports
13 | EXPOSE 8000
14 | # default command to execute
15 | CMD python manage.py runserver 0.0.0.0:8000
--------------------------------------------------------------------------------
/WQPS/Model/ADABOOST/PH/4.model:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/Model/ADABOOST/PH/4.model
--------------------------------------------------------------------------------
/WQPS/Model/ADABOOST/PH/5.model:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/Model/ADABOOST/PH/5.model
--------------------------------------------------------------------------------
/WQPS/Model/LSTM/DO/20.h5:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/Model/LSTM/DO/20.h5
--------------------------------------------------------------------------------
/WQPS/Model/LSTM/DO/21.h5:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/Model/LSTM/DO/21.h5
--------------------------------------------------------------------------------
/WQPS/Model/LSTM/PH/2.h5:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/Model/LSTM/PH/2.h5
--------------------------------------------------------------------------------
/WQPS/Model/SVM/DO/22.model:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/Model/SVM/DO/22.model
--------------------------------------------------------------------------------
/WQPS/Model/SVM/PH/1.model:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/Model/SVM/PH/1.model
--------------------------------------------------------------------------------
/WQPS/Model/SVM/PH/3.model:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/Model/SVM/PH/3.model
--------------------------------------------------------------------------------
/WQPS/WQPS/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/WQPS/__init__.py
--------------------------------------------------------------------------------
/WQPS/WQPS/__pycache__/__init__.cpython-35.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/WQPS/__pycache__/__init__.cpython-35.pyc
--------------------------------------------------------------------------------
/WQPS/WQPS/__pycache__/__init__.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/WQPS/__pycache__/__init__.cpython-36.pyc
--------------------------------------------------------------------------------
/WQPS/WQPS/__pycache__/settings.cpython-35.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/WQPS/__pycache__/settings.cpython-35.pyc
--------------------------------------------------------------------------------
/WQPS/WQPS/__pycache__/settings.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/WQPS/__pycache__/settings.cpython-36.pyc
--------------------------------------------------------------------------------
/WQPS/WQPS/__pycache__/urls.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/WQPS/__pycache__/urls.cpython-36.pyc
--------------------------------------------------------------------------------
/WQPS/WQPS/__pycache__/wsgi.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/WQPS/__pycache__/wsgi.cpython-36.pyc
--------------------------------------------------------------------------------
/WQPS/WQPS/settings.py:
--------------------------------------------------------------------------------
1 | """
2 | Django settings for WQPS project.
3 |
4 | Generated by 'django-admin startproject' using Django 2.1.7.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/2.1/topics/settings/
8 |
9 | For the full list of settings and their values, see
10 | https://docs.djangoproject.com/en/2.1/ref/settings/
11 | """
12 |
13 | import os
14 |
15 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
16 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
17 |
18 |
19 | # Quick-start development settings - unsuitable for production
20 | # See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/
21 |
22 | # SECURITY WARNING: keep the secret key used in production secret!
23 | SECRET_KEY = 'ft@8x0uktnll9j3^u2q+3u=m1+x-n+iop$q3r(z@$hq8gbhya9'
24 |
25 | # SECURITY WARNING: don't run with debug turned on in production!
26 | DEBUG = True
27 |
28 | ALLOWED_HOSTS = ['*']
29 |
30 |
31 | # Application definition
32 |
33 | INSTALLED_APPS = [
34 | 'django.contrib.admin',
35 | 'django.contrib.auth',
36 | 'django.contrib.contenttypes',
37 | 'django.contrib.sessions',
38 | 'django.contrib.messages',
39 | 'django.contrib.staticfiles',
40 | 'predicter',
41 | ]
42 |
43 | MIDDLEWARE = [
44 | 'django.middleware.security.SecurityMiddleware',
45 | 'django.contrib.sessions.middleware.SessionMiddleware',
46 | 'django.middleware.common.CommonMiddleware',
47 | #'django.middleware.csrf.CsrfViewMiddleware',
48 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
49 | 'django.contrib.messages.middleware.MessageMiddleware',
50 | 'django.middleware.clickjacking.XFrameOptionsMiddleware',
51 | ]
52 |
53 | ROOT_URLCONF = 'WQPS.urls'
54 |
55 | TEMPLATES = [
56 | {
57 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
58 | 'DIRS': [os.path.join(BASE_DIR, 'templates')]
59 | ,
60 | 'APP_DIRS': True,
61 | 'OPTIONS': {
62 | 'context_processors': [
63 | 'django.template.context_processors.debug',
64 | 'django.template.context_processors.request',
65 | 'django.contrib.auth.context_processors.auth',
66 | 'django.contrib.messages.context_processors.messages',
67 | ],
68 | },
69 | },
70 | ]
71 |
72 | WSGI_APPLICATION = 'WQPS.wsgi.application'
73 |
74 |
75 | # Database
76 | # https://docs.djangoproject.com/en/2.1/ref/settings/#databases
77 |
78 | DATABASES = {
79 | 'default': {
80 | 'ENGINE': 'django.db.backends.mysql',
81 | 'NAME': 'water',
82 | 'USER': username,
83 | 'PASSWORD': password,
84 | 'HOST': host,
85 | 'PORT': 3306
86 |
87 | }
88 | }
89 |
90 |
91 | # Password validation
92 | # https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators
93 |
94 | AUTH_PASSWORD_VALIDATORS = [
95 | {
96 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
97 | },
98 | {
99 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
100 | },
101 | {
102 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
103 | },
104 | {
105 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
106 | },
107 | ]
108 |
109 |
110 | # Internationalization
111 | # https://docs.djangoproject.com/en/2.1/topics/i18n/
112 |
113 | LANGUAGE_CODE = 'en-us'
114 |
115 | TIME_ZONE = 'UTC'
116 |
117 | USE_I18N = True
118 |
119 | USE_L10N = True
120 |
121 | USE_TZ = True
122 |
123 |
124 | # Static files (CSS, JavaScript, Images)
125 | # https://docs.djangoproject.com/en/2.1/howto/static-files/
126 |
127 | STATIC_URL = '/static/'
128 |
--------------------------------------------------------------------------------
/WQPS/WQPS/urls.py:
--------------------------------------------------------------------------------
1 | """WQPS URL Configuration
2 |
3 | The `urlpatterns` list routes URLs to views. For more information please see:
4 | https://docs.djangoproject.com/en/2.1/topics/http/urls/
5 | Examples:
6 | Function views
7 | 1. Add an import: from my_app import views
8 | 2. Add a URL to urlpatterns: path('', views.home, name='home')
9 | Class-based views
10 | 1. Add an import: from other_app.views import Home
11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
12 | Including another URLconf
13 | 1. Import the include() function: from django.urls import include, path
14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
15 | """
16 | from django.contrib import admin
17 | from django.urls import include, path
18 |
19 | urlpatterns = [
20 | path('api/', include('predicter.urls')),
21 | path('admin/', admin.site.urls),
22 | ]
--------------------------------------------------------------------------------
/WQPS/WQPS/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for WQPS project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.wsgi import get_wsgi_application
13 |
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'WQPS.settings')
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------
/WQPS/__pycache__/manage.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/__pycache__/manage.cpython-36.pyc
--------------------------------------------------------------------------------
/WQPS/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import os
3 | import sys
4 |
5 | if __name__ == '__main__':
6 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'WQPS.settings')
7 | try:
8 | from django.core.management import execute_from_command_line
9 | except ImportError as exc:
10 | raise ImportError(
11 | "Couldn't import Django. Are you sure it's installed and "
12 | "available on your PYTHONPATH environment variable? Did you "
13 | "forget to activate a virtual environment?"
14 | ) from exc
15 | execute_from_command_line(sys.argv)
16 |
--------------------------------------------------------------------------------
/WQPS/predicter/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/predicter/__init__.py
--------------------------------------------------------------------------------
/WQPS/predicter/__pycache__/__init__.cpython-35.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/predicter/__pycache__/__init__.cpython-35.pyc
--------------------------------------------------------------------------------
/WQPS/predicter/__pycache__/__init__.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/predicter/__pycache__/__init__.cpython-36.pyc
--------------------------------------------------------------------------------
/WQPS/predicter/__pycache__/adaboost.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/predicter/__pycache__/adaboost.cpython-36.pyc
--------------------------------------------------------------------------------
/WQPS/predicter/__pycache__/admin.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/predicter/__pycache__/admin.cpython-36.pyc
--------------------------------------------------------------------------------
/WQPS/predicter/__pycache__/bp.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/predicter/__pycache__/bp.cpython-36.pyc
--------------------------------------------------------------------------------
/WQPS/predicter/__pycache__/data_processor.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/predicter/__pycache__/data_processor.cpython-36.pyc
--------------------------------------------------------------------------------
/WQPS/predicter/__pycache__/lstm.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/predicter/__pycache__/lstm.cpython-36.pyc
--------------------------------------------------------------------------------
/WQPS/predicter/__pycache__/model_handler.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/predicter/__pycache__/model_handler.cpython-36.pyc
--------------------------------------------------------------------------------
/WQPS/predicter/__pycache__/model_predicter.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/predicter/__pycache__/model_predicter.cpython-36.pyc
--------------------------------------------------------------------------------
/WQPS/predicter/__pycache__/model_tester.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/predicter/__pycache__/model_tester.cpython-36.pyc
--------------------------------------------------------------------------------
/WQPS/predicter/__pycache__/model_trainer.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/predicter/__pycache__/model_trainer.cpython-36.pyc
--------------------------------------------------------------------------------
/WQPS/predicter/__pycache__/models.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/predicter/__pycache__/models.cpython-36.pyc
--------------------------------------------------------------------------------
/WQPS/predicter/__pycache__/rvr.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/predicter/__pycache__/rvr.cpython-36.pyc
--------------------------------------------------------------------------------
/WQPS/predicter/__pycache__/service.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/predicter/__pycache__/service.cpython-36.pyc
--------------------------------------------------------------------------------
/WQPS/predicter/__pycache__/svm.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/predicter/__pycache__/svm.cpython-36.pyc
--------------------------------------------------------------------------------
/WQPS/predicter/__pycache__/svr.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/predicter/__pycache__/svr.cpython-36.pyc
--------------------------------------------------------------------------------
/WQPS/predicter/__pycache__/urls.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/predicter/__pycache__/urls.cpython-36.pyc
--------------------------------------------------------------------------------
/WQPS/predicter/__pycache__/views.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/predicter/__pycache__/views.cpython-36.pyc
--------------------------------------------------------------------------------
/WQPS/predicter/adaboost.py:
--------------------------------------------------------------------------------
1 | from sklearn.tree import DecisionTreeRegressor
2 | from sklearn.ensemble import AdaBoostRegressor
3 |
4 |
5 | def train(x, y):
6 | max_depth = 8
7 | n_estimators = 400
8 | model = AdaBoostRegressor(DecisionTreeRegressor(max_depth=max_depth), n_estimators=n_estimators)
9 | model.fit(x, y)
10 | return model
11 |
--------------------------------------------------------------------------------
/WQPS/predicter/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 |
3 | # Register your models here.
4 |
--------------------------------------------------------------------------------
/WQPS/predicter/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class PredicterConfig(AppConfig):
5 | name = 'predicter'
6 |
--------------------------------------------------------------------------------
/WQPS/predicter/bp.py:
--------------------------------------------------------------------------------
1 | from sklearn.neural_network.multilayer_perceptron import MLPRegressor
2 |
3 |
4 | def train(x, y):
5 | model = MLPRegressor(hidden_layer_sizes=(12, 6, 3), batch_size=200)
6 | model.fit(x, y)
7 | return model
8 |
9 |
--------------------------------------------------------------------------------
/WQPS/predicter/data_processor.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from sklearn import preprocessing
3 | from .models import Waterquality
4 |
5 |
6 | def load_all_data():
7 | raw_data = Waterquality.objects.order_by('station', 'date')
8 | data = []
9 | for waterquality in raw_data:
10 | month = waterquality.date.month
11 | data.append([month, waterquality.do, waterquality.nh3n, waterquality.ph])
12 | return np.array(data)
13 |
14 |
15 | def select_Y(data, feature_num):
16 | feature_num = feature_num - 1
17 | Y = np.ones(len(data)).reshape(len(data), 1)
18 | for i in range(0, len(data)):
19 | Y[i] = data[i][feature_num]
20 | return Y
21 |
22 |
23 | def select_X(data, feature_lst):
24 | X = select_Y(data, feature_lst[0])
25 | for i in range(1, len(feature_lst)):
26 | X = np.hstack((X, select_Y(data, feature_lst[i])))
27 | return X
28 |
29 |
30 | def loop_feature(data, feature_num, loop):
31 | feature = select_Y(data, feature_num)
32 | length = len(feature)
33 | looped_feature = np.ones([loop, length - loop])
34 | for i in range(0, length - loop):
35 | for j in range(0, loop):
36 | looped_feature[j][i] = feature[i + j]
37 | return looped_feature.T
38 |
39 |
40 | def rearrange(x, loop):
41 | length = len(x)
42 | res = x[:, 0].reshape(length, 1)
43 | for i in range(0, loop):
44 | combined = x[:, i].reshape(length, 1)
45 | for j in range(0, 1):
46 | combined = np.hstack((combined, x[:, i + loop].reshape(length, 1)))
47 | res = np.hstack((res, combined))
48 | return res[:, 1:]
49 |
50 |
51 | def transform_x(x, loop=3):
52 | x = rearrange(x, loop)
53 | x = x.reshape((x.shape[0], loop, 2))
54 | return x
55 |
56 |
57 | def generate_sets(data, obj, mode=1, loop=3):
58 | obj_lst = {'month': 1, 'DO': 2, 'NH3N': 3, 'PH': 4}
59 | obj_num = obj_lst[obj]
60 | month = loop_feature(data, obj_lst['month'], loop)
61 | X = loop_feature(data, obj_num, loop)
62 | Y = select_Y(data, obj_num)
63 | length = len(data)
64 | Y = Y[loop:length, :]
65 | sets = np.hstack((month, X, Y))
66 | if mode == 2:
67 | training_set = build_training_set(sets, 0.6)
68 | valid_set = build_valid_set(sets, 0.6, 0.2)
69 | test_set = build_test_set(sets, 0.2)
70 | return {'training_set': training_set, 'valid_set': valid_set, 'test_set': test_set}
71 | training_set = build_training_set(sets, 0.8)
72 | test_set = build_test_set(sets, 0.2)
73 | return {'training_set': training_set, 'test_set': test_set}
74 |
75 |
76 | def build_training_set(sets, percent):
77 | length = int(len(sets) * percent)
78 | return sets[0:length, :]
79 |
80 |
81 | def build_test_set(sets, percent):
82 | length = int(len(sets) * (1 - percent))
83 | return sets[length:len(sets), :]
84 |
85 |
86 | def build_valid_set(sets, training_set_percent, valid_set_percent):
87 | start = int(len(sets) * training_set_percent)
88 | end = int(len(sets) * (training_set_percent + valid_set_percent))
89 | return sets[start:end, :]
90 |
91 |
92 | def standardize(data):
93 | scaler = preprocessing.StandardScaler().fit(data)
94 | data = scaler.transform(data)
95 | return data
96 |
97 |
98 | def standardize_for_prediction(mean_and_std, data):
99 | obj_mean = mean_and_std["mean"]
100 | obj_std = mean_and_std["std"]
101 | month_mean = 6.5
102 | month_std = 3.6
103 | for i in range(0, 3):
104 | data[0][i] = (data[0][i] - obj_mean) / obj_std
105 | for i in range(3, 6):
106 | data[0][i] = (data[0][i] - month_mean) / month_std
107 | return data
108 |
109 |
110 | def get_mean_and_std(data, obj):
111 | obj_lst = {'month': 0, 'DO': 1, 'NH3N': 2, 'PH': 3}
112 | obj_num = obj_lst[obj]
113 | scaler = preprocessing.StandardScaler().fit(data)
114 | return {'mean': scaler.mean_[obj_num], 'std': np.sqrt(scaler.var_)[obj_num]}
115 |
116 |
117 | def build_x(data, obj):
118 | obj_lst = {'month': 0, 'DO': 1, 'NH3N': 2, 'PH': 3}
119 | date = data[:, obj_lst['month']].T
120 | feature = data[:, obj_lst[obj]].T
121 | X = np.hstack((date, feature))
122 | return X.reshape(1, -1)
123 |
124 |
125 | def get_x(data):
126 | col_num = np.size(data, 1)
127 | x = data[:, 0:col_num - 1]
128 | return x
129 |
130 |
131 | def get_y(data):
132 | col_num = np.size(data, 1)
133 | y = data[:, col_num - 1]
134 | return y
135 |
136 |
137 | def get_last_loop_data(data, loop):
138 | length = np.size(data, 0)
139 | return data[length - loop:length, :]
140 |
141 |
142 | def get_last_months_data(obj, month_num):
143 | obj = str.lower(obj)
144 | raw_data = Waterquality.objects.order_by('-station', '-date')[:month_num]
145 | date = raw_data.values('date')
146 | obj_data = raw_data.values(obj)
147 | month = []
148 | data = []
149 | for i in range(0, len(date)):
150 | month.append(date[i]['date'].month)
151 | data.append(obj_data[i][obj])
152 | return {'month': month, 'data': data}
153 |
154 |
155 | def save_data(data):
156 | water = Waterquality(date=data['date'], do=data['DO'],
157 | ph=data['PH'], nh3n=data['NH3N'], station=10)
158 | water.save()
159 |
160 |
161 | def get_uploaded_data():
162 | raw_data = Waterquality.objects.filter(station=10).order_by('date')
163 | return raw_data
164 |
165 |
166 | def delete(waterquality_id):
167 | Waterquality.objects.filter(id=waterquality_id).delete()
168 |
169 |
170 | def delete_uploaded_data(start, nums):
171 | raw_data = Waterquality.objects.filter(station=10).order_by('date')
172 | index = 0
173 | cnt = 0
174 | flag = False
175 | for waterquality in raw_data:
176 | if index == start:
177 | flag = True
178 | if flag:
179 | waterquality.delete()
180 | cnt = cnt + 1
181 | index = index + 1
182 | if cnt == nums:
183 | break
184 |
185 |
186 |
187 |
188 |
189 |
190 |
--------------------------------------------------------------------------------
/WQPS/predicter/lstm.py:
--------------------------------------------------------------------------------
1 | from keras.models import Sequential
2 | from keras.layers import Dense
3 | from keras.layers import LSTM
4 | from . import data_processor
5 |
6 |
7 | def train(x, y):
8 | x = data_processor.transform_x(x)
9 | model = Sequential()
10 | model.add(LSTM(3, input_shape=(x.shape[1], x.shape[2]),
11 | return_sequences=True))
12 | model.add(LSTM(8, activation='tanh'))
13 | model.add(Dense(1))
14 | model.compile(loss='mae', optimizer='adam')
15 | model.fit(x, y, verbose=1, epochs=70)
16 | return model
17 |
18 |
19 |
--------------------------------------------------------------------------------
/WQPS/predicter/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/predicter/migrations/__init__.py
--------------------------------------------------------------------------------
/WQPS/predicter/migrations/__pycache__/__init__.cpython-36.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/WQPS/predicter/migrations/__pycache__/__init__.cpython-36.pyc
--------------------------------------------------------------------------------
/WQPS/predicter/model_handler.py:
--------------------------------------------------------------------------------
1 | from django.conf import settings
2 | from sklearn.externals import joblib
3 | from .models import Model
4 | from keras import models
5 | import os
6 |
7 |
8 | def load_model(model_info, model_id):
9 | model_path = model_info["path"]
10 | method = model_info["method"]
11 | if method == "LSTM":
12 | model_name = str(model_id) + '.h5'
13 | model = models.load_model(os.path.join(model_path, model_name))
14 | else:
15 | model_name = str(model_id) + '.model'
16 | model = joblib.load(os.path.join(model_path, model_name))
17 | return model
18 |
19 |
20 | def load_vote_model(model_info, model_id):
21 | model_path = model_info["path"]
22 | svm_model_name = str(model_id) + '_' + 'SVM.model'
23 | rvm_model_name = str(model_id) + '_' + 'RVM.model'
24 | bp_model_name = str(model_id) + '_' + 'BP.model'
25 | adaboost_model_name = str(model_id) + '_' + 'Adaboost.model'
26 | svm_model = joblib.load(os.path.join(model_path, svm_model_name))
27 | rvm_model = joblib.load(os.path.join(model_path, rvm_model_name))
28 | bp_model = joblib.load(os.path.join(model_path, bp_model_name))
29 | adaboost_model = joblib.load(os.path.join(model_path, adaboost_model_name))
30 | return svm_model, rvm_model, bp_model, adaboost_model
31 |
32 |
33 | def save_model(model, model_info, model_id):
34 | obj = model_info["obj"]
35 | method = model_info["method"]
36 | model_path = model_info["path"]
37 | if not os.path.exists(model_path):
38 | os.makedirs(model_path)
39 | if method == "LSTM":
40 | model_name = str(model_id) + '.h5'
41 | model.save(os.path.join(model_path, model_name))
42 | else:
43 | model_name = str(model_id) + '.model'
44 | joblib.dump(model, os.path.join(model_path, model_name))
45 |
46 |
47 | def save_vote_model(svm_model, rvm_model, bp_model, adaboost_model, model_info, model_id):
48 | obj = model_info["obj"]
49 | method = model_info["method"]
50 | model_path = model_info["path"]
51 | if not os.path.exists(model_path):
52 | os.makedirs(model_path)
53 | svm_model_name = str(model_id) + '_' + 'SVM.model'
54 | rvm_model_name = str(model_id) + '_' + 'RVM.model'
55 | bp_model_name = str(model_id) + '_' + 'BP.model'
56 | adaboost_model_name = str(model_id) + '_' + 'Adaboost.model'
57 | joblib.dump(svm_model, os.path.join(model_path, svm_model_name))
58 | joblib.dump(rvm_model, os.path.join(model_path, rvm_model_name))
59 | joblib.dump(bp_model, os.path.join(model_path, bp_model_name))
60 | joblib.dump(adaboost_model, os.path.join(model_path, adaboost_model_name))
61 |
62 |
63 | def get_model_by_id(model_id):
64 | return Model.objects.get(id=model_id)
65 |
66 |
67 | def get_model_info(model_id):
68 | model_entity = get_model_by_id(model_id)
69 | obj = model_entity.target
70 | method = model_entity.name.split("_", maxsplit=1)[1]
71 | model_path = os.path.join(settings.BASE_DIR, 'Model', method, obj)
72 | return {"obj": obj, "method": method, "path": model_path}
73 |
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/WQPS/predicter/model_predicter.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from . import data_processor
3 | from keras import backend as K
4 |
5 |
6 | def predict(model, x, mean_and_std, lstm_mode):
7 | if lstm_mode:
8 | x = data_processor.transform_x(x)
9 | raw_pred = model.predict(x)
10 | if lstm_mode:
11 | K.clear_session()
12 | raw_pred = raw_pred.reshape(len(raw_pred), )
13 | mean = mean_and_std['mean']
14 | std = mean_and_std['std']
15 | pred = raw_pred * std + mean
16 | if lstm_mode:
17 | pred = pred.tolist()
18 | return [round(n, 2) for n in pred]
19 | return np.round(pred, 2).tolist()
20 |
21 |
22 | def vote_predict(svm_model, rvm_model, bp_model, adaboost_model, x, mean_and_std):
23 | choose = svm_model.predict(x)
24 | raw_pred = []
25 | col_nums = np.size(x, 1)
26 | for i in range(0, len(choose)):
27 | current_pred = 0
28 | current_x = x[i, :].reshape((1, col_nums))
29 | if choose[i] == 0:
30 | current_pred = rvm_model.predict(current_x)[0]
31 | elif choose[i] == 1:
32 | current_pred = bp_model.predict(current_x)[0]
33 | else:
34 | current_pred = adaboost_model.predict(current_x)[0]
35 | raw_pred.append(current_pred)
36 | mean = mean_and_std['mean']
37 | std = mean_and_std['std']
38 | raw_pred = np.array(raw_pred)
39 | pred = raw_pred * std + mean
40 | return np.round(pred, 2).tolist()
41 |
42 |
--------------------------------------------------------------------------------
/WQPS/predicter/model_tester.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from . import model_predicter
3 | import matplotlib.pyplot as plt
4 |
5 | def rmse(pred, real):
6 | length = len(pred)
7 | res = 0
8 | for i in range(0, length):
9 | res = res + np.square(pred[i] - real[i])
10 | res = np.sqrt(res/length)
11 | return np.round(res, 2)
12 |
13 |
14 | def cor(pred, real):
15 | return np.round(np.corrcoef(pred, real)[0][1], 2)
16 |
17 |
18 | def accuracy(obj, pred, real):
19 | length = len(pred)
20 | res = 0
21 | if obj == 'PH':
22 | limit = 0.3
23 | if obj == 'DO':
24 | limit = 1
25 | if obj == 'CODMn':
26 | limit = 0.5
27 | if obj == 'NH3N':
28 | limit = 0.3
29 | for i in range(0, length):
30 | if np.abs(pred[i] - real[i]) <= limit:
31 | res = res + 1
32 | return np.round(res/length*100, 2)
33 |
34 |
35 | def plot(pred, real):
36 | t = np.arange(0, len(pred))
37 | plt.plot(t, pred, 'b--', t, real, 'r')
38 | plt.show()
39 |
40 |
41 | def test_model(model, test_set, mean_and_std, lstm_mode):
42 | col_num = np.size(test_set, 1)
43 | x = test_set[:, 0:col_num - 1]
44 | y = test_set[:, col_num - 1] * mean_and_std['std'] + mean_and_std['mean']
45 | pred = model_predicter.predict(model, x, mean_and_std, lstm_mode)
46 | return {'rmse': rmse(pred, y),
47 | 'pred': pred,
48 | 'real': np.round(y, 2).tolist()}
49 |
50 |
51 | def test_vote_model(svm_model, rvm_model, bp_model, adaboost_model, test_set, mean_and_std):
52 | col_num = np.size(test_set, 1)
53 | x = test_set[:, 0:col_num - 1]
54 | y = test_set[:, col_num - 1] * mean_and_std['std'] + mean_and_std['mean']
55 | pred = model_predicter.vote_predict(svm_model, rvm_model, bp_model, adaboost_model, x, mean_and_std)
56 | return {'rmse': rmse(pred, y),
57 | 'pred': pred,
58 | 'real': np.round(y, 2).tolist()}
59 |
60 |
61 |
--------------------------------------------------------------------------------
/WQPS/predicter/model_trainer.py:
--------------------------------------------------------------------------------
1 | from . import svr
2 | from . import rvr
3 | from . import bp
4 | from . import adaboost
5 | from . import lstm
6 | from . import svm
7 | from . import data_processor
8 | import numpy as np
9 |
10 |
11 | def get_trained_model(model_name, training_set):
12 | col_num = np.size(training_set, 1)
13 | x = training_set[:, 0:col_num - 1]
14 | y = training_set[:, col_num - 1]
15 | if model_name == 'SVM':
16 | return svr.train(x, y)
17 | if model_name == 'Adaboost':
18 | return adaboost.train(x, y)
19 | if model_name == 'RVM':
20 | return rvr.train(x, y)
21 | if model_name == 'BP':
22 | return bp.train(x, y)
23 | if model_name == 'LSTM':
24 | return lstm.train(x, y)
25 | if model_name == 'SVC':
26 | return svm.train(x, y)
27 | return svr.train(x, y)
28 |
29 |
30 | def build_vote_label(pred, Y):
31 | length = len(Y)
32 | label = np.ones(length)
33 | one_pred = pred[:, 0]
34 | two_pred = pred[:, 1]
35 | three_pred = pred[:, 2]
36 | one_err = np.square(one_pred - Y)
37 | two_err = np.square(two_pred - Y)
38 | three_err = np.square(three_pred - Y)
39 | for i in range(0, length):
40 | lst = [one_err[i], two_err[i], three_err[i]]
41 | lst.sort()
42 | if lst[0] == one_err[i]:
43 | label[i] = 0
44 | elif lst[0] == two_err[i]:
45 | label[i] = 1
46 | else:
47 | label[i] = 2
48 | return label.reshape((-1, 1))
49 |
50 |
51 | def get_trained_vote_model(training_set, valid_set):
52 | rvm_model = get_trained_model("RVM", training_set)
53 | bp_model = get_trained_model("BP", training_set)
54 | adaboost_model = get_trained_model("Adaboost", training_set)
55 |
56 | valid_x = data_processor.get_x(valid_set)
57 | valid_y = data_processor.get_y(valid_set)
58 | rvm_valid_pred = rvm_model.predict(valid_x)
59 | bp_model_pred = bp_model.predict(valid_x)
60 | adaboost_pred = adaboost_model.predict(valid_x)
61 | valid_pred = np.vstack((rvm_valid_pred, bp_model_pred, adaboost_pred)).T
62 | # print(np.shape(valid_pred))
63 | # print(np.shape(valid_y))
64 | label = build_vote_label(valid_pred, valid_y)
65 | svm_model = get_trained_model("SVC", np.hstack((valid_x, label)))
66 | return svm_model, rvm_model, bp_model, adaboost_model
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/WQPS/predicter/models.py:
--------------------------------------------------------------------------------
1 |
2 | # Create your models here.
3 | # This is an auto-generated Django Model module.
4 | # You'll have to do the following manually to clean this up:
5 | # * Rearrange models' order
6 | # * Make sure each Model has one field with primary_key=True
7 | # * Make sure each ForeignKey has `on_delete` set to the desired behavior.
8 | # * Remove `managed = False` lines if you wish to allow Django to create, modify, and delete the table
9 | # Feel free to rename the models, but don't rename db_table values or field names.
10 | from django.db import models
11 |
12 |
13 | class Waterquality(models.Model):
14 | id = models.IntegerField(db_column='id', primary_key=True)
15 | ph = models.FloatField(db_column='PH', blank=True, null=True) # Field name made lowercase.
16 | do = models.FloatField(db_column='DO', blank=True, null=True) # Field name made lowercase.
17 | nh3n = models.FloatField(db_column='NH3N', blank=True, null=True) # Field name made lowercase.
18 | date = models.DateTimeField()
19 | station = models.IntegerField(blank=True, null=True)
20 |
21 | class Meta:
22 | # managed = False
23 | db_table = 'waterquality'
24 |
25 |
26 | class Model(models.Model):
27 | id = models.IntegerField(db_column='id', primary_key=True)
28 | name = models.CharField(max_length=50)
29 | target = models.CharField(max_length=50)
30 | date = models.DateTimeField()
31 | rmse = models.FloatField()
32 |
33 | class Meta:
34 | db_table = "model"
35 |
--------------------------------------------------------------------------------
/WQPS/predicter/my_tests.py:
--------------------------------------------------------------------------------
1 | import os, django
2 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "WQPS.settings")
3 | django.setup()
4 | from unittest import TestCase
5 | from . import data_processor
6 | from . import service
7 | from . import model_handler
8 | from . import model_trainer
9 | from . import model_tester
10 |
11 |
12 |
13 | class Test(TestCase):
14 | def test_load_data(self):
15 | print(data_processor.load_all_data())
16 |
17 | def test_train_model(self):
18 | print(service.train_model('DO'))
19 |
20 | def test_predict_next_month(self):
21 | print(service.predict_next_month('DO'))
22 |
23 | def test_get_last_months_data(self):
24 | print(data_processor.get_last_months_data('DO', 5))
25 |
26 | def test_save_data(self):
27 | data = {'date': '2019-03-01 00:00:00', 'PH': 7.02, 'DO': 7.02, 'NH3N': 7.02}
28 | data_processor.save_data(data)
29 |
30 | def test_get_next_month(self):
31 | print(data_processor.get_next_month_num())
32 |
33 | def test_get_model_by_id(self):
34 | model = model_handler.get_model_by_id(1)
35 | print(model.name)
36 |
37 | def test_service_train_model(self):
38 | print(service.train_model(1))
39 |
40 | def test_predict_next_month(self):
41 | print(service.predict_next_month(1))
42 |
43 | def test_train_model(self):
44 | obj = 'DO'
45 | loop = 3
46 | method = 'LSTM'
47 | lstm_mode = False
48 | if method == 'LSTM':
49 | lstm_mode = True
50 | raw_data = data_processor.load_all_data()
51 | mean_and_std = data_processor.get_mean_and_std(raw_data, obj)
52 | data = data_processor.standardize(raw_data)
53 | sets = data_processor.generate_sets(data, obj, loop)
54 | training_set = sets['training_set']
55 | test_set = sets['test_set']
56 | model = model_trainer.get_trained_model(method, training_set)
57 | print(model_tester.test_model(model, test_set, mean_and_std, lstm_mode))
58 |
59 | def test_train_vote_model(self):
60 | obj = 'DO'
61 | service.train_vote_model(obj)
62 |
--------------------------------------------------------------------------------
/WQPS/predicter/rvr.py:
--------------------------------------------------------------------------------
1 | from skrvm import RVR
2 |
3 |
4 | def train(x, y):
5 | model = RVR(kernel='rbf')
6 | model.fit(x, y)
7 | return model
8 |
9 |
--------------------------------------------------------------------------------
/WQPS/predicter/service.py:
--------------------------------------------------------------------------------
1 | from . import data_processor
2 | from . import model_handler
3 | from . import model_trainer
4 | from . import model_tester
5 | from . import model_predicter
6 | import numpy as np
7 |
8 | def train_model(model_id, loop=3):
9 | model_info = model_handler.get_model_info(model_id)
10 | obj = model_info["obj"]
11 | method = model_info["method"]
12 | if method == "Optimization":
13 | return train_vote_model(model_id, model_info)
14 | lstm_mode = False
15 | if method == "LSTM":
16 | lstm_mode = True
17 | raw_data = data_processor.load_all_data()
18 | mean_and_std = data_processor.get_mean_and_std(raw_data, obj)
19 | data = data_processor.standardize(raw_data)
20 | sets = data_processor.generate_sets(data, obj)
21 | training_set = sets['training_set']
22 | test_set = sets['test_set']
23 | model = model_trainer.get_trained_model(method, training_set)
24 | model_handler.save_model(model, model_info, model_id)
25 | return model_tester.test_model(model, test_set, mean_and_std, lstm_mode)
26 |
27 |
28 | def train_vote_model(model_id, model_info):
29 | obj = model_info["obj"]
30 | model_path = model_info["path"]
31 | raw_data = data_processor.load_all_data()
32 | mean_and_std = data_processor.get_mean_and_std(raw_data, obj)
33 | data = data_processor.standardize(raw_data)
34 | sets = data_processor.generate_sets(data, obj, 2)
35 | training_set = sets['training_set']
36 | valid_set = sets['valid_set']
37 | test_set = sets['test_set']
38 | svm_model, rvm_model, bp_model, adaboost_model = model_trainer.get_trained_vote_model(training_set, valid_set)
39 | model_handler.save_vote_model(svm_model, rvm_model, bp_model, adaboost_model, model_info, model_id)
40 | res = model_tester.test_vote_model(svm_model, rvm_model, bp_model, adaboost_model, test_set, mean_and_std)
41 | print(res)
42 | return res
43 |
44 |
45 | def predict_next_month(model_id, data):
46 | model_info = model_handler.get_model_info(model_id)
47 | obj = model_info["obj"]
48 | method = model_info["method"]
49 | lstm_mode = False
50 | if method == "LSTM":
51 | lstm_mode = True
52 | raw_data = data_processor.load_all_data()
53 | mean_and_std = data_processor.get_mean_and_std(raw_data, obj)
54 | x = data_processor.standardize_for_prediction(mean_and_std, np.array(data))
55 | # x = data_processor.build_x(data, obj)
56 | if method == "Optimization":
57 | svm_model, rvm_model, bp_model, adaboost_model = model_handler.load_vote_model(model_info, model_id)
58 | pred = model_predicter.vote_predict(svm_model, rvm_model, bp_model, adaboost_model, x, mean_and_std)[0]
59 | return {'pred': pred}
60 | model = model_handler.load_model(model_info, model_id)
61 | pred = model_predicter.predict(model, x, mean_and_std, lstm_mode)[0]
62 | return {'pred': pred}
63 |
64 |
65 | def get_last_months_data(obj, month_num=5):
66 | return data_processor.get_last_months_data(obj, month_num)
67 |
68 |
69 | def save_one_waterquality(data):
70 | data_processor.save_data(data)
71 |
72 |
73 | def get_uploaded_waterquality():
74 | return data_processor.get_uploaded_data()
75 |
76 |
77 | def delete_uploaded_waterquality(start, nums):
78 | return data_processor.delete_uploaded_data(start, nums)
79 |
80 |
81 | def delete(id):
82 | data_processor.delete(id)
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/WQPS/predicter/svm.py:
--------------------------------------------------------------------------------
1 | from sklearn.svm import SVC
2 |
3 |
4 | def train(x, y):
5 | model = SVC(kernel='rbf')
6 | model.fit(x, y)
7 | return model
8 |
9 |
--------------------------------------------------------------------------------
/WQPS/predicter/svr.py:
--------------------------------------------------------------------------------
1 | from sklearn.svm import SVR
2 |
3 |
4 | def train(x, y):
5 | model = SVR(kernel='rbf')
6 | model.fit(x, y)
7 | return model
8 |
9 |
--------------------------------------------------------------------------------
/WQPS/predicter/urls.py:
--------------------------------------------------------------------------------
1 | from django.urls import path
2 |
3 | from . import views
4 |
5 | urlpatterns = [
6 | path('', views.index, name='index'),
7 | path('training/', views.train, name='train'),
8 | path('prediction/', views.predict, name='predict'),
9 | ]
--------------------------------------------------------------------------------
/WQPS/predicter/views.py:
--------------------------------------------------------------------------------
1 | from django.http import HttpResponse
2 | from django.http import JsonResponse
3 | from django.shortcuts import render, redirect
4 | from . import service
5 |
6 |
7 | def index(request):
8 | return HttpResponse("Hello")
9 |
10 |
11 | def train(request):
12 | if request.method == 'GET':
13 | model_id = request.GET.get("id")
14 | try:
15 | data = service.train_model(model_id)
16 | return JsonResponse({'status': 'success', 'data': data})
17 | except Exception as e:
18 | return JsonResponse({'status': str(e)})
19 |
20 |
21 | def predict(request):
22 | if request.method == 'GET':
23 | model_id = request.GET.get("id")
24 | one = float(request.GET.get("one"))
25 | two = float(request.GET.get("two"))
26 | three = float(request.GET.get("three"))
27 | first_month = eval(request.GET.get("startMonth"))
28 | second_month = (first_month + 1) % 12
29 | if first_month + 1 == 12:
30 | second_month = 12
31 | third_month = (second_month + 1) % 12
32 | if second_month + 1 == 12:
33 | third_month = 12
34 | try:
35 | print("raw_data----------")
36 | print([[one, two, three, first_month, second_month, third_month]])
37 | data = service.predict_next_month(model_id, [[one, two, three, first_month, second_month, third_month]])
38 | return JsonResponse({'status': 'success', 'data': data})
39 | except Exception as e:
40 | print(e)
41 | return JsonResponse({'status': str(e)})
42 |
43 |
44 | def waterquality(request):
45 | if request.method == 'GET':
46 | obj = request.GET.get('obj', 'nothing')
47 | month_num = eval(request.GET.get('month_num', '5'))
48 | if obj == 'nothing':
49 | return JsonResponse({'status': 'param error'})
50 | try:
51 | data = service.get_last_months_data(obj, month_num)
52 | return JsonResponse({'status': 'success', 'data': data})
53 | except Exception as e:
54 | return JsonResponse({'status': str(e)})
55 | if request.method == 'POST':
56 | date = request.POST.get('date', 'nothing')
57 | ph = eval(request.POST.get('PH', '-1'))
58 | do = eval(request.POST.get('DO', '-1'))
59 | nh3n = eval(request.POST.get('NH3N', '-1'))
60 | if date == 'nothing' or ph == -1 or do == -1 or nh3n == -1:
61 | return JsonResponse({'status': 'param error'})
62 | try:
63 | data = {'date': date, 'PH': ph, 'DO': do, 'NH3N': nh3n}
64 | service.save_one_waterquality(data)
65 | return JsonResponse({'status': 'success'})
66 | except Exception as e:
67 | return JsonResponse({'status': str(e)})
68 |
69 |
70 | def test(request):
71 | data = service.get_uploaded_waterquality()
72 | print(data)
73 | return render(request, 'test.html', {'data': data})
74 |
75 |
76 | def delete(request):
77 | id = request.GET.get('id')
78 | service.delete(id)
79 | return redirect('/predicter/test/')
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/WQPS/requirements.txt:
--------------------------------------------------------------------------------
1 | absl-py==0.7.1
2 | appnope==0.1.0
3 | astor==0.7.1
4 | backcall==0.1.0
5 | certifi==2019.3.9
6 | configparser==3.7.3
7 | cycler==0.10.0
8 | decorator==4.4.0
9 | Django==2.1.7
10 | gast==0.2.2
11 | grpcio==1.19.0
12 | h5py==2.9.0
13 | ipython==7.3.0
14 | ipython-genutils==0.2.0
15 | jedi==0.13.3
16 | Keras==2.2.4
17 | Keras-Applications==1.0.7
18 | Keras-Preprocessing==1.0.9
19 | kiwisolver==1.0.1
20 | Markdown==3.0.1
21 | matplotlib==3.0.3
22 | mock==2.0.0
23 | mysqlclient==1.4.2.post1
24 | ndg-httpsclient==0.5.1
25 | numpy==1.16.2
26 | pandas==0.24.2
27 | parso==0.3.4
28 | pbr==5.1.3
29 | pexpect==4.6.0
30 | pickleshare==0.7.5
31 | prompt-toolkit==2.0.9
32 | protobuf==3.7.0
33 | ptyprocess==0.6.0
34 | Pygments==2.3.1
35 | PyMySQL==0.9.3
36 | pyparsing==2.3.1
37 | python-dateutil==2.8.0
38 | pytz==2018.9
39 | PyYAML==5.1
40 | scikit-learn==0.20.3
41 | scipy==1.2.1
42 | six==1.12.0
43 | tensorboard==1.13.1
44 | tensorflow==1.13.1
45 | tensorflow-estimator==1.13.0
46 | termcolor==1.1.0
47 | traitlets==4.3.2
48 | wcwidth==0.1.7
49 | Werkzeug==0.14.1
50 |
--------------------------------------------------------------------------------
/WQPS/templates/test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 数据测试
6 | 上传的数据
7 |
8 |
9 | PH |
10 | DO |
11 | NH3N |
12 | 上传日期 |
13 | 操作 |
14 |
15 | {% for waterquality in data %}
16 |
17 | {{ waterquality.ph }} |
18 | {{ waterquality.do }} |
19 | {{ waterquality.nh3n }} |
20 | {{ waterquality.date }} |
21 |
22 | 删除
23 | |
24 |
25 | {% endfor %}
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.4'
2 | services:
3 | wqps:
4 | build: ./WQPS
5 | container_name: wqps
6 | network_mode: host
7 |
8 | wqms:
9 | build: ./WQMS
10 | container_name: wqms
11 | network_mode: host
12 |
13 | web:
14 | build: ./FrontEnd
15 | container_name: web
16 | network_mode: host
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/pics/下月预测.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/pics/下月预测.png
--------------------------------------------------------------------------------
/pics/修改密码.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/pics/修改密码.png
--------------------------------------------------------------------------------
/pics/历史数据.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/pics/历史数据.png
--------------------------------------------------------------------------------
/pics/数据趋势.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/pics/数据趋势.png
--------------------------------------------------------------------------------
/pics/模型训练.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/pics/模型训练.png
--------------------------------------------------------------------------------
/pics/水质数据添加.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/pics/水质数据添加.png
--------------------------------------------------------------------------------
/pics/水质数据编辑.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/pics/水质数据编辑.png
--------------------------------------------------------------------------------
/pics/注册.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/pics/注册.png
--------------------------------------------------------------------------------
/pics/用例图.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/pics/用例图.jpg
--------------------------------------------------------------------------------
/pics/用户信息.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/pics/用户信息.png
--------------------------------------------------------------------------------
/pics/用户授权.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/pics/用户授权.png
--------------------------------------------------------------------------------
/pics/用户管理.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/pics/用户管理.png
--------------------------------------------------------------------------------
/pics/用户菜单.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/pics/用户菜单.png
--------------------------------------------------------------------------------
/pics/登录.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/pics/登录.png
--------------------------------------------------------------------------------
/pics/系统架构.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/pics/系统架构.jpg
--------------------------------------------------------------------------------
/pics/近日监测.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/pics/近日监测.png
--------------------------------------------------------------------------------
/关于系统.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangjianlin1985/Springboot_Vue_Python_Water_quality_management_prediction/59adddb621895f851bb357da6fff2d5f655cf08f/关于系统.txt
--------------------------------------------------------------------------------