├── 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 | 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 | 85 | 86 | 96 | 97 | 98 | 114 | -------------------------------------------------------------------------------- /FrontEnd/src/components/Home.vue: -------------------------------------------------------------------------------- 1 | 117 | 118 | 224 | 225 | 258 | -------------------------------------------------------------------------------- /FrontEnd/src/components/Login.vue: -------------------------------------------------------------------------------- 1 | 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 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 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 30 | 31 | 32 | 34 | -------------------------------------------------------------------------------- /WQPS/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /WQPS/.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 22 | -------------------------------------------------------------------------------- /WQPS/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 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 | 10 | 11 | 12 | 13 | 14 | 15 | {% for waterquality in data %} 16 | 17 | 18 | 19 | 20 | 21 | 24 | 25 | {% endfor %} 26 | 27 |
PHDONH3N上传日期操作
{{ waterquality.ph }}{{ waterquality.do }}{{ waterquality.nh3n }}{{ waterquality.date }} 22 | 删除 23 |
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 --------------------------------------------------------------------------------