├── hardware-monitor-ui ├── .env ├── .browserslistrc ├── public │ ├── robots.txt │ ├── favicon.ico │ ├── img │ │ └── icons │ │ │ ├── favicon-16x16.png │ │ │ ├── favicon-32x32.png │ │ │ ├── favicon-192x192.png.png │ │ │ ├── android-chrome-192x192.png │ │ │ └── android-chrome-512x512.png │ ├── manifest.json │ └── index.html ├── .eslintignore ├── cypress.json ├── babel.config.js ├── tests │ └── unit │ │ ├── .eslintrc.js │ │ ├── utils │ │ └── validate.spec.ts │ │ └── components │ │ └── Breadcrumb.spec.ts ├── postcss.config.js ├── src │ ├── styles │ │ ├── _variables.min.css │ │ ├── _variables.css │ │ ├── _mixins.scss │ │ ├── _variables.scss.d.ts │ │ ├── _svgicon.scss │ │ ├── element-variables.scss │ │ ├── _variables.scss │ │ ├── _transition.scss │ │ ├── index.scss │ │ └── font-icon.scss │ ├── shims-vue.d.ts │ ├── assets │ │ ├── nodata.png │ │ ├── img │ │ │ ├── map.png │ │ │ ├── Avatar.png │ │ │ ├── mapBlue.png │ │ │ ├── mapGray.png │ │ │ ├── mapIcon │ │ │ │ ├── map.png │ │ │ │ ├── mapblue.png │ │ │ │ └── mapgray.png │ │ │ ├── waterMarkalarmLog.png │ │ │ ├── waterMarkDatainfo1.png │ │ │ ├── waterMarkDatainfo2.png │ │ │ ├── waterMarkDatainfo3.png │ │ │ ├── watermarkfingerItem.png │ │ │ ├── waterMarkEquipmentBot.png │ │ │ ├── waterMarkEquipmentTop.png │ │ │ └── watermarkalarmLogtop.png │ │ ├── background.png │ │ ├── loginIcon.png │ │ └── 404-images │ │ │ ├── 404.png │ │ │ └── 404-cloud.png │ ├── layout │ │ ├── components │ │ │ ├── index.ts │ │ │ ├── AppMain.vue │ │ │ └── Sidebar │ │ │ │ ├── SidebarItemLink.vue │ │ │ │ └── index.vue │ │ ├── mixin │ │ │ └── resize.ts │ │ └── index.vue │ ├── utils │ │ ├── validate.ts │ │ ├── cookies.ts │ │ └── request.ts │ ├── icons │ │ ├── svg │ │ │ ├── link.svg │ │ │ ├── example.svg │ │ │ ├── user.svg │ │ │ ├── table.svg │ │ │ ├── nested.svg │ │ │ ├── password.svg │ │ │ ├── hamburger.svg │ │ │ ├── eye-off.svg │ │ │ ├── eye-on.svg │ │ │ ├── tree.svg │ │ │ ├── dashboard.svg │ │ │ └── form.svg │ │ ├── components │ │ │ ├── index.ts │ │ │ ├── link.ts │ │ │ ├── user.ts │ │ │ ├── example.ts │ │ │ ├── table.ts │ │ │ ├── nested.ts │ │ │ ├── password.ts │ │ │ ├── hamburger.ts │ │ │ ├── eye-off.ts │ │ │ ├── eye-on.ts │ │ │ ├── tree.ts │ │ │ ├── dashboard.ts │ │ │ └── form.ts │ │ └── README.md │ ├── store │ │ ├── index.ts │ │ └── modules │ │ │ ├── app.ts │ │ │ └── user.ts │ ├── api │ │ ├── equipment.ts │ │ ├── users.ts │ │ ├── alarmManage.ts │ │ ├── fingerMark.ts │ │ └── dashboard.ts │ ├── main.ts │ ├── components │ │ ├── Hamburger │ │ │ └── index.vue │ │ ├── Table │ │ │ └── index.vue │ │ ├── Charts │ │ │ └── mixins │ │ │ │ └── resize.ts │ │ ├── Tabs │ │ │ └── index.vue │ │ └── Breadcrumb │ │ │ └── index.vue │ ├── registerServiceWorker.ts │ ├── views │ │ └── dashboard │ │ │ └── components │ │ │ └── totleCont.vue │ └── permission.ts ├── .gitignore ├── README.md ├── .editorconfig ├── tsconfig.json ├── LICENSE ├── vue.config.js ├── jest.config.js ├── .eslintrc.js └── package.json ├── doc ├── image │ ├── alipays.png │ ├── init-01.png │ ├── init-02.png │ ├── init-03.png │ ├── init-04.png │ ├── init-05.png │ ├── init-06.png │ ├── init-07.png │ └── wechats.png └── docker-compose │ └── docker-compose.yml ├── hardware-monitor-web ├── hardware-monitor-backend │ ├── src │ │ └── main │ │ │ ├── java │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── backend │ │ │ │ ├── mapper │ │ │ │ ├── chain │ │ │ │ │ ├── GpsMapper.java │ │ │ │ │ ├── AlarmMapper.java │ │ │ │ │ ├── BoardMapper.java │ │ │ │ │ └── QuotaMapper.java │ │ │ │ └── admin │ │ │ │ │ └── UserMapper.java │ │ │ │ ├── WebBackendApplication.java │ │ │ │ ├── service │ │ │ │ ├── chain │ │ │ │ │ ├── IBoardService.java │ │ │ │ │ ├── IGpsService.java │ │ │ │ │ ├── IAlarmLogService.java │ │ │ │ │ ├── IDeviceGeoService.java │ │ │ │ │ ├── IAlarmService.java │ │ │ │ │ ├── IReportService.java │ │ │ │ │ ├── impl │ │ │ │ │ │ └── IGpsServiceImpl.java │ │ │ │ │ └── IQuotaService.java │ │ │ │ └── admin │ │ │ │ │ └── IUserService.java │ │ │ │ ├── config │ │ │ │ ├── mybatis │ │ │ │ │ ├── MybatisPlusHandler.java │ │ │ │ │ └── MybatisPlusConfig.java │ │ │ │ ├── web │ │ │ │ │ └── LocalDateTimeSerializerConfig.java │ │ │ │ └── redis │ │ │ │ │ └── RedisConfig.java │ │ │ │ ├── controller │ │ │ │ ├── error │ │ │ │ │ └── Error404Controller.java │ │ │ │ ├── chain │ │ │ │ │ ├── DeviceGeoController.java │ │ │ │ │ ├── AlarmLogController.java │ │ │ │ │ ├── GpsController.java │ │ │ │ │ ├── AlarmController.java │ │ │ │ │ ├── QuotaController.java │ │ │ │ │ ├── BoardController.java │ │ │ │ │ └── ReportController.java │ │ │ │ └── admin │ │ │ │ │ └── UserController.java │ │ │ │ ├── filter │ │ │ │ └── RequestFilter.java │ │ │ │ ├── emq │ │ │ │ ├── client │ │ │ │ │ └── EmqClient.java │ │ │ │ └── config │ │ │ │ │ └── EmqMonitoringConfig.java │ │ │ │ └── handler │ │ │ │ └── GlobalExceptionHandler.java │ │ │ └── resources │ │ │ ├── application.yml │ │ │ └── application-dev.yml │ └── pom.xml ├── hardware-monitor-monitoring │ ├── src │ │ └── main │ │ │ ├── resources │ │ │ └── application.yml │ │ │ └── java │ │ │ └── com │ │ │ └── example │ │ │ └── monitoring │ │ │ ├── WebMonitoringApplication.java │ │ │ └── config │ │ │ └── SecuritySecureConfig.java │ └── pom.xml └── pom.xml ├── .gitignore ├── hardware-monitor-service ├── hardware-monitor-service-admin │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── com │ │ │ └── example │ │ │ └── admin │ │ │ ├── vo │ │ │ ├── LoginVO.java │ │ │ └── UserVO.java │ │ │ ├── dto │ │ │ └── LoginResultDTO.java │ │ │ └── pojo │ │ │ └── User.java │ └── pom.xml ├── hardware-monitor-service-chain │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── com │ │ │ └── example │ │ │ └── chain │ │ │ ├── query │ │ │ ├── QuotaQuery.java │ │ │ ├── DevicesQuery.java │ │ │ ├── AlarmQuery.java │ │ │ ├── BaseQuery.java │ │ │ └── AlarmLogQuery.java │ │ │ ├── pojo │ │ │ ├── DeviceGeo.java │ │ │ ├── AlarmLog.java │ │ │ ├── Board.java │ │ │ ├── Alarm.java │ │ │ ├── Quota.java │ │ │ └── Gps.java │ │ │ ├── dto │ │ │ ├── DeviceMonitorDTO.java │ │ │ ├── DeviceInfoDTO.java │ │ │ ├── GpsDTO.java │ │ │ ├── DevicePieDTO.java │ │ │ ├── DeviceHeapDTO.java │ │ │ ├── DeviceTrendDTO.java │ │ │ ├── BoardDTO.java │ │ │ ├── DeviceGeoDetails.java │ │ │ ├── DevicesDTO.java │ │ │ ├── DeviceQuotaDTO.java │ │ │ ├── AlarmDTO.java │ │ │ ├── AlarmLogDTO.java │ │ │ └── QuotaDTO.java │ │ │ └── vo │ │ │ ├── BoardVO.java │ │ │ ├── GpsVO.java │ │ │ ├── QuotaVO.java │ │ │ ├── DevicesVO.java │ │ │ └── AlarmVO.java │ └── pom.xml └── pom.xml └── hardware-monitor-common ├── src └── main │ └── java │ └── com │ └── example │ └── common │ ├── constant │ ├── RedisConstant.java │ └── ElasticSearchConstant.java │ ├── utils │ ├── SaltUtil.java │ ├── MD5Util.java │ ├── DateUtil.java │ ├── JsonUtil.java │ └── TokenUtil.java │ ├── exception │ └── BusinessException.java │ └── domain │ ├── RestPageResult.java │ └── RestResponse.java └── pom.xml /hardware-monitor-ui/.env: -------------------------------------------------------------------------------- 1 | # VUE_APP_BASE_API = '/api' -------------------------------------------------------------------------------- /hardware-monitor-ui/.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | -------------------------------------------------------------------------------- /hardware-monitor-ui/public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /hardware-monitor-ui/.eslintignore: -------------------------------------------------------------------------------- 1 | dist/*.js 2 | src/assets 3 | tests/unit/coverage 4 | -------------------------------------------------------------------------------- /hardware-monitor-ui/cypress.json: -------------------------------------------------------------------------------- 1 | { 2 | "pluginsFile": "tests/e2e/plugins/index.js" 3 | } 4 | -------------------------------------------------------------------------------- /doc/image/alipays.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/doc/image/alipays.png -------------------------------------------------------------------------------- /doc/image/init-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/doc/image/init-01.png -------------------------------------------------------------------------------- /doc/image/init-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/doc/image/init-02.png -------------------------------------------------------------------------------- /doc/image/init-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/doc/image/init-03.png -------------------------------------------------------------------------------- /doc/image/init-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/doc/image/init-04.png -------------------------------------------------------------------------------- /doc/image/init-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/doc/image/init-05.png -------------------------------------------------------------------------------- /doc/image/init-06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/doc/image/init-06.png -------------------------------------------------------------------------------- /doc/image/init-07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/doc/image/init-07.png -------------------------------------------------------------------------------- /doc/image/wechats.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/doc/image/wechats.png -------------------------------------------------------------------------------- /hardware-monitor-ui/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/app' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /hardware-monitor-ui/tests/unit/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | jest: true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /hardware-monitor-ui/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | autoprefixer: {} 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/styles/_variables.min.css: -------------------------------------------------------------------------------- 1 | :export{menuBg:#304156;menuText:#bfcbd9;menuActiveText:#409EFF} 2 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import Vue from 'vue' 3 | export default Vue 4 | } 5 | -------------------------------------------------------------------------------- /hardware-monitor-ui/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/hardware-monitor-ui/public/favicon.ico -------------------------------------------------------------------------------- /hardware-monitor-ui/src/assets/nodata.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/hardware-monitor-ui/src/assets/nodata.png -------------------------------------------------------------------------------- /hardware-monitor-ui/src/assets/img/map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/hardware-monitor-ui/src/assets/img/map.png -------------------------------------------------------------------------------- /hardware-monitor-ui/src/assets/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/hardware-monitor-ui/src/assets/background.png -------------------------------------------------------------------------------- /hardware-monitor-ui/src/assets/img/Avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/hardware-monitor-ui/src/assets/img/Avatar.png -------------------------------------------------------------------------------- /hardware-monitor-ui/src/assets/img/mapBlue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/hardware-monitor-ui/src/assets/img/mapBlue.png -------------------------------------------------------------------------------- /hardware-monitor-ui/src/assets/img/mapGray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/hardware-monitor-ui/src/assets/img/mapGray.png -------------------------------------------------------------------------------- /hardware-monitor-ui/src/assets/loginIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/hardware-monitor-ui/src/assets/loginIcon.png -------------------------------------------------------------------------------- /hardware-monitor-ui/src/assets/404-images/404.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/hardware-monitor-ui/src/assets/404-images/404.png -------------------------------------------------------------------------------- /hardware-monitor-ui/src/assets/img/mapIcon/map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/hardware-monitor-ui/src/assets/img/mapIcon/map.png -------------------------------------------------------------------------------- /hardware-monitor-ui/src/styles/_variables.css: -------------------------------------------------------------------------------- 1 | /* Variables */ 2 | :export { 3 | menuBg: #304156; 4 | menuText: #bfcbd9; 5 | menuActiveText: #409EFF; 6 | } 7 | -------------------------------------------------------------------------------- /hardware-monitor-ui/public/img/icons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/hardware-monitor-ui/public/img/icons/favicon-16x16.png -------------------------------------------------------------------------------- /hardware-monitor-ui/public/img/icons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/hardware-monitor-ui/public/img/icons/favicon-32x32.png -------------------------------------------------------------------------------- /hardware-monitor-ui/src/assets/404-images/404-cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/hardware-monitor-ui/src/assets/404-images/404-cloud.png -------------------------------------------------------------------------------- /hardware-monitor-ui/src/assets/img/mapIcon/mapblue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/hardware-monitor-ui/src/assets/img/mapIcon/mapblue.png -------------------------------------------------------------------------------- /hardware-monitor-ui/src/assets/img/mapIcon/mapgray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/hardware-monitor-ui/src/assets/img/mapIcon/mapgray.png -------------------------------------------------------------------------------- /hardware-monitor-ui/src/assets/img/waterMarkalarmLog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/hardware-monitor-ui/src/assets/img/waterMarkalarmLog.png -------------------------------------------------------------------------------- /hardware-monitor-ui/src/assets/img/waterMarkDatainfo1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/hardware-monitor-ui/src/assets/img/waterMarkDatainfo1.png -------------------------------------------------------------------------------- /hardware-monitor-ui/src/assets/img/waterMarkDatainfo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/hardware-monitor-ui/src/assets/img/waterMarkDatainfo2.png -------------------------------------------------------------------------------- /hardware-monitor-ui/src/assets/img/waterMarkDatainfo3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/hardware-monitor-ui/src/assets/img/waterMarkDatainfo3.png -------------------------------------------------------------------------------- /hardware-monitor-ui/src/assets/img/watermarkfingerItem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/hardware-monitor-ui/src/assets/img/watermarkfingerItem.png -------------------------------------------------------------------------------- /hardware-monitor-ui/src/styles/_mixins.scss: -------------------------------------------------------------------------------- 1 | /* Mixins */ 2 | @mixin clearfix { 3 | &:after { 4 | content: ""; 5 | display: table; 6 | clear: both; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /hardware-monitor-ui/public/img/icons/favicon-192x192.png.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/hardware-monitor-ui/public/img/icons/favicon-192x192.png.png -------------------------------------------------------------------------------- /hardware-monitor-ui/src/assets/img/waterMarkEquipmentBot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/hardware-monitor-ui/src/assets/img/waterMarkEquipmentBot.png -------------------------------------------------------------------------------- /hardware-monitor-ui/src/assets/img/waterMarkEquipmentTop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/hardware-monitor-ui/src/assets/img/waterMarkEquipmentTop.png -------------------------------------------------------------------------------- /hardware-monitor-ui/src/assets/img/watermarkalarmLogtop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/hardware-monitor-ui/src/assets/img/watermarkalarmLogtop.png -------------------------------------------------------------------------------- /hardware-monitor-ui/public/img/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/hardware-monitor-ui/public/img/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /hardware-monitor-ui/public/img/icons/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikuhuyo/hardware-monitor/HEAD/hardware-monitor-ui/public/img/icons/android-chrome-512x512.png -------------------------------------------------------------------------------- /hardware-monitor-ui/src/layout/components/index.ts: -------------------------------------------------------------------------------- 1 | export {default as AppMain} from './AppMain.vue' 2 | export {default as Navbar} from './Navbar/index.vue' 3 | export {default as Sidebar} from './Sidebar/index.vue' 4 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/styles/_variables.scss.d.ts: -------------------------------------------------------------------------------- 1 | export interface IScssVariables { 2 | menuBg: string 3 | menuText: string 4 | menuActiveText: string 5 | } 6 | 7 | export const variables: IScssVariables 8 | 9 | export default variables 10 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/utils/validate.ts: -------------------------------------------------------------------------------- 1 | // export const isValidUsername = (str: string) => ['admin', 'editor'].indexOf(str.trim()) >= 0 2 | export const isValidUsername = (str: string) => str.trim().length > 0 3 | 4 | export const isExternal = (path: string) => /^(https?:|mailto:|tel:)/.test(path) 5 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/icons/svg/link.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/icons/components/index.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | import './dashboard' 3 | import './example' 4 | import './eye-off' 5 | import './eye-on' 6 | import './form' 7 | import './hamburger' 8 | import './link' 9 | import './nested' 10 | import './password' 11 | import './table' 12 | import './tree' 13 | import './user' 14 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/icons/svg/example.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/icons/svg/user.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /hardware-monitor-ui/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | /tests/e2e/videos/ 6 | /tests/e2e/screenshots/ 7 | /tests/**/coverage/ 8 | 9 | # local env files 10 | .env.local 11 | .env.*.local 12 | 13 | # Log files 14 | npm-debug.log* 15 | yarn-debug.log* 16 | yarn-error.log* 17 | 18 | # Editor directories and files 19 | .idea 20 | .vscode 21 | *.suo 22 | *.ntvs* 23 | *.njsproj 24 | *.sln 25 | *.sw* 26 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/store/index.ts: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import {IAppState} from './modules/app' 4 | import {IUserState} from './modules/user' 5 | 6 | Vue.use(Vuex) 7 | 8 | export interface IRootState { 9 | app: IAppState 10 | user: IUserState 11 | } 12 | 13 | // Declare empty store first, dynamically register all modules later. 14 | export default new Vuex.Store({}) 15 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/mapper/chain/GpsMapper.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.mapper.chain; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.example.chain.pojo.Gps; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | /** 8 | * @author yuelimin 9 | * @version 1.0.0 10 | * @since 11 11 | */ 12 | @Mapper 13 | public interface GpsMapper extends BaseMapper { 14 | } 15 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/mapper/admin/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.mapper.admin; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.example.admin.pojo.User; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | /** 8 | * @author yuelimin 9 | * @version 1.0.0 10 | * @since 11 11 | */ 12 | @Mapper 13 | public interface UserMapper extends BaseMapper { 14 | } 15 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/mapper/chain/AlarmMapper.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.mapper.chain; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.example.chain.pojo.Alarm; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | /** 8 | * @author yuelimin 9 | * @version 1.0.0 10 | * @since 11 11 | */ 12 | @Mapper 13 | public interface AlarmMapper extends BaseMapper { 14 | } 15 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/mapper/chain/BoardMapper.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.mapper.chain; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.example.chain.pojo.Board; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | /** 8 | * @author yuelimin 9 | * @version 1.0.0 10 | * @since 11 11 | */ 12 | @Mapper 13 | public interface BoardMapper extends BaseMapper { 14 | } 15 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/mapper/chain/QuotaMapper.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.mapper.chain; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.example.chain.pojo.Quota; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | /** 8 | * @author yuelimin 9 | * @version 1.0.0 10 | * @since 11 11 | */ 12 | @Mapper 13 | public interface QuotaMapper extends BaseMapper { 14 | } 15 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/icons/components/link.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* tslint:disable */ 3 | // @ts-ignore 4 | import icon from 'vue-svgicon' 5 | 6 | icon.register({ 7 | 'link': { 8 | width: 128, 9 | height: 128, 10 | viewBox: '0 0 128 128', 11 | data: '' 12 | } 13 | }) 14 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/icons/svg/table.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .git 2 | rebel.xml 3 | !.mvn/wrapper/maven-wrapper.jar 4 | log.path_IS_UNDEFINED 5 | .DS_Store 6 | offline_user.md 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | test/ 22 | target/ 23 | logs/ 24 | 25 | ### NetBeans ### 26 | nbproject/private/ 27 | build/ 28 | nbbuild/ 29 | dist/ 30 | nbdist/ 31 | .nb-gradle/ 32 | generatorConfig.xml 33 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-admin/src/main/java/com/example/admin/vo/LoginVO.java: -------------------------------------------------------------------------------- 1 | package com.example.admin.vo; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @author yuelimin 9 | * @version 1.0.0 10 | * @since 11 11 | */ 12 | @Data 13 | public class LoginVO implements Serializable { 14 | 15 | private static final long serialVersionUID = -4717431641998171940L; 16 | 17 | private String loginName; 18 | 19 | private String password; 20 | } 21 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/api/equipment.ts: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | export const getDevice = (data: any) => 4 | request({ 5 | url: '/api/device', 6 | method: 'post', 7 | data 8 | }) 9 | export const deviceStatus = (data: any) => 10 | request({ 11 | url: '/api/device/status', 12 | method: 'put', 13 | data 14 | }) 15 | 16 | export const device = (data: any) => 17 | request({ 18 | url: '/api/device/deviceQuota', 19 | method: 'post', 20 | data 21 | }) 22 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/icons/svg/nested.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/icons/svg/password.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /hardware-monitor-common/src/main/java/com/example/common/constant/RedisConstant.java: -------------------------------------------------------------------------------- 1 | package com.example.common.constant; 2 | 3 | /** 4 | * @author yuelimin 5 | * @version 1.0.0 6 | * @since 11 7 | */ 8 | public class RedisConstant { 9 | /** 10 | * redis-告警信息沉默周期前缀 11 | * cold:storage:device:cycle:${deviceId}:${quotaKey}:${level} 12 | * deviceId: 设备id 13 | * quotaKey: 指标key(例如风扇转速异常指标-fans) 14 | * level: 告警等级 15 | */ 16 | public static final String CYCLE_KEY = "cold:storage:device:cycle:%s:%s:%s"; 17 | } 18 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/utils/cookies.ts: -------------------------------------------------------------------------------- 1 | import Cookies from 'js-cookie' 2 | 3 | // App 4 | const sidebarStatusKey = 'sidebar_status' 5 | export const getSidebarStatus = () => Cookies.get(sidebarStatusKey) 6 | export const setSidebarStatus = (sidebarStatus: string) => Cookies.set(sidebarStatusKey, sidebarStatus) 7 | 8 | // User 9 | const tokenKey = 'token' 10 | export const getToken = () => Cookies.get(tokenKey) 11 | export const setToken = (token: string) => Cookies.set(tokenKey, token) 12 | export const removeToken = () => Cookies.remove(tokenKey) 13 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-chain/src/main/java/com/example/chain/query/QuotaQuery.java: -------------------------------------------------------------------------------- 1 | package com.example.chain.query; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @author yuelimin 9 | * @version 1.0.0 10 | * @since 11 11 | */ 12 | @Data 13 | public class QuotaQuery implements Serializable { 14 | 15 | private static final long serialVersionUID = 443266758153168453L; 16 | 17 | private Long page; 18 | 19 | private Long pageSize; 20 | 21 | private String quotaName; 22 | } 23 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/WebBackendApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.backend; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * @author yuelimin 8 | * @version 1.0.0 9 | * @since 11 10 | */ 11 | @SpringBootApplication 12 | public class WebBackendApplication { 13 | public static void main(String[] args) { 14 | SpringApplication.run(WebBackendApplication.class, args); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /hardware-monitor-ui/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Vue Typescript Admin", 3 | "short_name": "Vue Ts Admin", 4 | "icons": [ 5 | { 6 | "src": "./img/icons/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "./img/icons/android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "start_url": "./index.html", 17 | "display": "standalone", 18 | "background_color": "#fff", 19 | "theme_color": "#4DBA87" 20 | } 21 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/icons/components/user.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* tslint:disable */ 3 | // @ts-ignore 4 | import icon from 'vue-svgicon' 5 | 6 | icon.register({ 7 | 'user': { 8 | width: 130, 9 | height: 130, 10 | viewBox: '0 0 130 130', 11 | data: '' 12 | } 13 | }) 14 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/icons/svg/hamburger.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/icons/components/example.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* tslint:disable */ 3 | // @ts-ignore 4 | import icon from 'vue-svgicon' 5 | 6 | icon.register({ 7 | 'example': { 8 | width: 128, 9 | height: 128, 10 | viewBox: '0 0 128 128', 11 | data: '' 12 | } 13 | }) 14 | -------------------------------------------------------------------------------- /hardware-monitor-ui/tests/unit/utils/validate.spec.ts: -------------------------------------------------------------------------------- 1 | import {isExternal, isValidUsername} from '@/utils/validate' 2 | 3 | describe('Utils:validate', () => { 4 | it('isValidUsername', () => { 5 | expect(isValidUsername('admin')).toBe(true) 6 | expect(isValidUsername('editor')).toBe(true) 7 | expect(isValidUsername('xxxx')).toBe(false) 8 | }) 9 | 10 | it('isExternal', () => { 11 | expect(isExternal('https://www.armour.com/')).toBe(true) 12 | expect(isExternal('mailto:someone@test.com')).toBe(true) 13 | expect(isExternal('123aBC')).toBe(false) 14 | }) 15 | }) 16 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/styles/_svgicon.scss: -------------------------------------------------------------------------------- 1 | /* Recommended css code for vue-svgicon */ 2 | .svg-icon { 3 | display: inline-block; 4 | width: 16px; 5 | height: 16px; 6 | color: inherit; 7 | fill: none; 8 | stroke: currentColor; 9 | vertical-align: -0.15em; 10 | } 11 | 12 | .svg-fill { 13 | fill: currentColor; 14 | stroke: none; 15 | } 16 | 17 | .svg-up { 18 | transform: rotate(0deg); 19 | } 20 | 21 | .svg-right { 22 | transform: rotate(90deg); 23 | } 24 | 25 | .svg-down { 26 | transform: rotate(180deg); 27 | } 28 | 29 | .svg-left { 30 | transform: rotate(-90deg); 31 | } 32 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-chain/src/main/java/com/example/chain/pojo/DeviceGeo.java: -------------------------------------------------------------------------------- 1 | package com.example.chain.pojo; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @author yuelimin 9 | * @version 1.0.0 10 | * @since 11 11 | */ 12 | @Data 13 | public class DeviceGeo implements Serializable { 14 | 15 | private static final long serialVersionUID = -4091269338563002044L; 16 | 17 | /** 18 | * 地理信息 19 | */ 20 | private String location; 21 | 22 | /** 23 | * 设备id 24 | */ 25 | private String deviceId; 26 | } 27 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-admin/src/main/java/com/example/admin/vo/UserVO.java: -------------------------------------------------------------------------------- 1 | package com.example.admin.vo; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @author yuelimin 9 | * @version 1.0.0 10 | * @since 11 11 | */ 12 | @Data 13 | public class UserVO implements Serializable { 14 | 15 | private static final long serialVersionUID = 7566317139854185030L; 16 | 17 | private String loginName; 18 | 19 | private String password; 20 | 21 | private String type; 22 | 23 | private String board; 24 | 25 | private String status; 26 | } 27 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-chain/src/main/java/com/example/chain/query/DevicesQuery.java: -------------------------------------------------------------------------------- 1 | package com.example.chain.query; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @author yuelimin 9 | * @version 1.0.0 10 | * @since 11 11 | */ 12 | @Data 13 | public class DevicesQuery implements Serializable { 14 | 15 | private static final long serialVersionUID = 1504265723139457473L; 16 | 17 | private Long page; 18 | 19 | private Long pageSize; 20 | 21 | private String deviceId; 22 | 23 | private String tag; 24 | 25 | private Integer state; 26 | } 27 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-chain/src/main/java/com/example/chain/dto/DeviceMonitorDTO.java: -------------------------------------------------------------------------------- 1 | package com.example.chain.dto; 2 | 3 | import lombok.Data; 4 | import lombok.experimental.Accessors; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * 报表-设备监控实体类 10 | * 11 | * @author yuelimin 12 | * @version 1.0.0 13 | * @since 11 14 | */ 15 | @Data 16 | @Accessors(chain = true) 17 | public class DeviceMonitorDTO implements Serializable { 18 | 19 | private static final long serialVersionUID = -9081298476645505353L; 20 | 21 | private Long deviceCount; 22 | 23 | private Long alarmCount; 24 | } 25 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/layout/components/AppMain.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 22 | 23 | 29 | -------------------------------------------------------------------------------- /hardware-monitor-ui/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 亿可控 9 | 10 | 11 | 15 |
16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /hardware-monitor-ui/README.md: -------------------------------------------------------------------------------- 1 | ## 亿可控冷链监控 2 | 3 | 4 | ## 预览 5 | 6 | 7 | ### 安装依赖 8 | 9 | ```bash 10 | yarn install 11 | ``` 12 | 13 | ### 启动本地开发环境(自带热启动) 14 | 15 | ```bash 16 | yarn serve 17 | ``` 18 | 19 | ### 构建生产环境 (自带压缩) 20 | 21 | ```bash 22 | yarn build 23 | ``` 24 | 25 | ### 代码格式检查以及自动修复 26 | 27 | ```bash 28 | yarn lint 29 | ``` 30 | 31 | ### 运行单元测试 32 | 33 | ```bash 34 | yarn test:unit 35 | ``` 36 | 37 | ### 运行端对端测试 38 | 39 | ```bash 40 | yarn test:e2e 41 | ``` 42 | 43 | ### 自动生成 svg 组件 44 | 45 | ```bash 46 | yarn svg 47 | ``` 48 | 49 | ### 自定义 Vue 配置 50 | 51 | 看这里 [Configuration Reference](https://cli.vuejs.org/config/). 52 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/styles/element-variables.scss: -------------------------------------------------------------------------------- 1 | /* Element Variables */ 2 | 3 | // Override Element UI variables 4 | $--color-primary: #1890ff; 5 | $--color-success: #13ce66; 6 | $--color-warning: #FFBA00; 7 | $--color-danger: #ff4949; 8 | $--color-info: #5d5d5d; 9 | $--button-font-weight: 400; 10 | $--color-text-regular: #1f2d3d; 11 | $--border-color-light: #dfe4ed; 12 | $--border-color-lighter: #e6ebf5; 13 | $--table-border: 1px solid #dfe6ec; 14 | 15 | // Icon font path, required 16 | $--font-path: '~element-ui/lib/theme-chalk/fonts'; 17 | 18 | // Apply overrided variables in Element UI 19 | @import '~element-ui/packages/theme-chalk/src/index'; 20 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/icons/components/table.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* tslint:disable */ 3 | // @ts-ignore 4 | import icon from 'vue-svgicon' 5 | 6 | icon.register({ 7 | 'table': { 8 | width: 128, 9 | height: 128, 10 | viewBox: '0 0 128 128', 11 | data: '' 12 | } 13 | }) 14 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/icons/svg/eye-off.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-chain/src/main/java/com/example/chain/query/AlarmQuery.java: -------------------------------------------------------------------------------- 1 | package com.example.chain.query; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @author yuelimin 9 | * @version 1.0.0 10 | * @since 11 11 | */ 12 | @Data 13 | public class AlarmQuery implements Serializable { 14 | 15 | private static final long serialVersionUID = 5172487689208831486L; 16 | 17 | private Long page; 18 | 19 | private Long pageSize; 20 | 21 | /** 22 | * 报警名称 23 | */ 24 | private String name; 25 | 26 | /** 27 | * 指标id 28 | */ 29 | private Long quotaId; 30 | } 31 | -------------------------------------------------------------------------------- /hardware-monitor-common/src/main/java/com/example/common/constant/ElasticSearchConstant.java: -------------------------------------------------------------------------------- 1 | package com.example.common.constant; 2 | 3 | /** 4 | * @author yuelimin 5 | * @version 1.0.0 6 | * @since 11 7 | */ 8 | public class ElasticSearchConstant { 9 | /** 10 | * ES中设备索引名称 11 | */ 12 | public static final String ES_DEVICES_INDEX_NAME = "cold_storage_devices"; 13 | 14 | /** 15 | * ES中警告信息索引名称 16 | */ 17 | public static final String ES_ALARM_LOG_INDEX_NAME = "cold_storage_device_alarm_log"; 18 | 19 | /** 20 | * ES中地理信息索引名称 21 | */ 22 | public static final String ES_DEVICE_GEO_INDEX_NAME = "cold_storage_device_geo"; 23 | } 24 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-chain/src/main/java/com/example/chain/vo/BoardVO.java: -------------------------------------------------------------------------------- 1 | package com.example.chain.vo; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @author yuelimin 9 | * @version 1.0.0 10 | * @since 11 11 | */ 12 | @Data 13 | public class BoardVO implements Serializable { 14 | 15 | private static final long serialVersionUID = 7786935748188420868L; 16 | 17 | private Long id; 18 | 19 | private Long userId; 20 | 21 | private String boardName; 22 | 23 | private String quota; 24 | 25 | private String device; 26 | 27 | private String isSystem; 28 | 29 | private String isDisable; 30 | } 31 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/icons/README.md: -------------------------------------------------------------------------------- 1 | # vue-svgicon 2 | 3 | ## English 4 | 5 | * All svg components were generated by `vue-svgicon` using svg files 6 | * After you adding new svg files into `icons/svg` folder, run `yarn svg` to regerenrate all svg components (before this, 7 | you should have `vue-svgicon` installed globally or use `npx`) 8 | * See details at: [https://github.com/MMF-FE/vue-svgicon](https://github.com/MMF-FE/vue-svgicon) 9 | 10 | ## 中文 11 | 12 | * 所有的 svg 组件都是由 `vue-svgicon` 生成的 13 | * 每当在 `icons/svg` 文件夹内添加 icon 之后,可以通过执行 `yarn svg` 来重新生成所有组件 (在此之前需要全局安装 `vue-svgicon` 或使用 `npx`) 14 | * 详细文档请见:[https://github.com/MMF-FE/vue-svgicon](https://github.com/MMF-FE/vue-svgicon) 15 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/layout/components/Sidebar/SidebarItemLink.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 31 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-admin/src/main/java/com/example/admin/dto/LoginResultDTO.java: -------------------------------------------------------------------------------- 1 | package com.example.admin.dto; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @author yuelimin 9 | * @version 1.0.0 10 | * @since 11 11 | */ 12 | @Data 13 | public class LoginResultDTO implements Serializable { 14 | 15 | private static final long serialVersionUID = 832098862168595179L; 16 | 17 | /** 18 | * 登录结果 19 | */ 20 | private Boolean loginSuccess; 21 | 22 | /** 23 | * 管理员Id 24 | */ 25 | private Long userId; 26 | 27 | /** 28 | * jwt token 29 | */ 30 | private String token; 31 | } 32 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/icons/components/nested.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* tslint:disable */ 3 | // @ts-ignore 4 | import icon from 'vue-svgicon' 5 | 6 | icon.register({ 7 | 'nested': { 8 | width: 128, 9 | height: 128, 10 | viewBox: '0 0 128 128', 11 | data: '' 12 | } 13 | }) 14 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/icons/components/password.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* tslint:disable */ 3 | // @ts-ignore 4 | import icon from 'vue-svgicon' 5 | 6 | icon.register({ 7 | 'password': { 8 | width: 128, 9 | height: 128, 10 | viewBox: '0 0 128 128', 11 | data: '' 12 | } 13 | }) 14 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-chain/src/main/java/com/example/chain/dto/DeviceInfoDTO.java: -------------------------------------------------------------------------------- 1 | package com.example.chain.dto; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | import java.util.List; 8 | 9 | /** 10 | *

11 | * 设备信息DTO 12 | *

13 | * 14 | * @author yuelimin 15 | * @version 1.0.0 16 | * @since 11 17 | */ 18 | @Data 19 | @JsonInclude(JsonInclude.Include.NON_NULL) 20 | public class DeviceInfoDTO implements Serializable { 21 | 22 | private static final long serialVersionUID = -5449662632648954039L; 23 | 24 | private DevicesDTO devicesDTO; 25 | 26 | private List deviceQuotaDTOList; 27 | } 28 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-chain/src/main/java/com/example/chain/query/BaseQuery.java: -------------------------------------------------------------------------------- 1 | package com.example.chain.query; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | import java.util.List; 7 | 8 | /** 9 | * @author yuelimin 10 | * @version 1.0.0 11 | * @since 11 12 | */ 13 | @Data 14 | public class BaseQuery implements Serializable { 15 | 16 | private static final long serialVersionUID = -1008096487395117184L; 17 | 18 | private Long id; 19 | 20 | private List stringIds; 21 | 22 | private String startTime; 23 | 24 | private String endTime; 25 | 26 | private String type; 27 | 28 | private Long page; 29 | 30 | private Long pageSize; 31 | } 32 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-chain/src/main/java/com/example/chain/vo/GpsVO.java: -------------------------------------------------------------------------------- 1 | package com.example.chain.vo; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @author yuelimin 9 | * @version 1.0.0 10 | * @since 11 11 | */ 12 | @Data 13 | public class GpsVO implements Serializable { 14 | 15 | private static final long serialVersionUID = 7141753441678923532L; 16 | 17 | private Long id; 18 | 19 | private String subject; 20 | 21 | private String snKey; 22 | 23 | private String singleField; 24 | 25 | private String valueKey; 26 | 27 | private String separation; 28 | 29 | private String longitude; 30 | 31 | private String latitude; 32 | } 33 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-chain/src/main/java/com/example/chain/dto/GpsDTO.java: -------------------------------------------------------------------------------- 1 | package com.example.chain.dto; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @author yuelimin 9 | * @version 1.0.0 10 | * @since 11 11 | */ 12 | @Data 13 | public class GpsDTO implements Serializable { 14 | 15 | private static final long serialVersionUID = 8618789613561924050L; 16 | 17 | private Long id; 18 | 19 | private String subject; 20 | 21 | private String snKey; 22 | 23 | private String singleField; 24 | 25 | private String valueKey; 26 | 27 | private String separation; 28 | 29 | private String longitude; 30 | 31 | private String latitude; 32 | } 33 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/icons/components/hamburger.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* tslint:disable */ 3 | // @ts-ignore 4 | import icon from 'vue-svgicon' 5 | 6 | icon.register({ 7 | 'hamburger': { 8 | width: 64, 9 | height: 64, 10 | viewBox: '0 0 1024 1024', 11 | data: '' 12 | } 13 | }) 14 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/service/chain/IBoardService.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.service.chain; 2 | 3 | import com.example.chain.dto.BoardDTO; 4 | import com.example.chain.vo.BoardVO; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | /** 10 | * @author yuelimin 11 | * @version 1.0.0 12 | * @since 11 13 | */ 14 | public interface IBoardService { 15 | List getMyBoard(Long uid); 16 | 17 | List getSystemBoard(); 18 | 19 | void updateBoardStatus(List> statusMap); 20 | 21 | void updateBoard(BoardVO boardVO); 22 | 23 | void deleteBoardById(Long id); 24 | 25 | void createBoard(BoardVO boardVO); 26 | } 27 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/api/users.ts: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | export const getUserInfo = (data: any) => 4 | request({ 5 | url: '/api/users/info', 6 | method: 'get', 7 | data 8 | }) 9 | 10 | export const login = (data: any) => 11 | request({ 12 | url: '/api/login', 13 | method: 'post', 14 | data 15 | }) 16 | 17 | export const logout = () => 18 | request({ 19 | url: '/api/users/logout', 20 | method: 'delete' 21 | }) 22 | 23 | export const getRsaKey = () => 24 | request({ 25 | url: '/api/rsa-key', 26 | method: 'get' 27 | }) 28 | 29 | export const getPasswordRsa = (password : any) => 30 | request({ 31 | url: `/api/rsa-key/${password}`, 32 | method: 'get' 33 | }) 34 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/main.ts: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | import 'normalize.css' 4 | import ElementUI from 'element-ui' 5 | import SvgIcon from 'vue-svgicon' 6 | import Moment from 'moment' 7 | import '@/styles/element-variables.scss' 8 | import '@/styles/index.scss' 9 | 10 | import App from '@/App.vue' 11 | import store from '@/store' 12 | import router from '@/router' 13 | import '@/icons/components' 14 | import '@/permission' 15 | 16 | 17 | Vue.use(ElementUI) 18 | 19 | Vue.use(SvgIcon, { 20 | tagName: 'svg-icon', 21 | defaultWidth: '1em', 22 | defaultHeight: '1em' 23 | }) 24 | 25 | Vue.config.productionTip = false 26 | Vue.prototype.moment = Moment 27 | new Vue({ 28 | router, 29 | store, 30 | render: (h) => h(App) 31 | }).$mount('#app') 32 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-chain/src/main/java/com/example/chain/dto/DevicePieDTO.java: -------------------------------------------------------------------------------- 1 | package com.example.chain.dto; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import lombok.Data; 5 | import lombok.experimental.Accessors; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * 报表-设备分布实体类 11 | * @Accessors(chain = true)开启链式编程 12 | * 13 | * @author yuelimin 14 | * @version 1.0.0 15 | * @since 11 16 | */ 17 | @Data 18 | @Accessors(chain = true) 19 | @JsonInclude(JsonInclude.Include.NON_NULL) 20 | public class DevicePieDTO implements Serializable { 21 | 22 | private static final long serialVersionUID = 2194033771833803248L; 23 | 24 | private String name; 25 | 26 | private Long value; 27 | } 28 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-chain/src/main/java/com/example/chain/query/AlarmLogQuery.java: -------------------------------------------------------------------------------- 1 | package com.example.chain.query; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @author yuelimin 9 | * @version 1.0.0 10 | * @since 11 11 | */ 12 | @Data 13 | public class AlarmLogQuery implements Serializable { 14 | 15 | private static final long serialVersionUID = -5529631204092689107L; 16 | 17 | private Long page; 18 | 19 | private Long pageSize; 20 | 21 | private String start; 22 | 23 | private String end; 24 | 25 | private String alarmName; 26 | 27 | private String deviceId; 28 | 29 | /** 30 | * 0正常日志 1一般警告日志 2严重警告日志 31 | */ 32 | private Integer alarm; 33 | } 34 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-chain/src/main/java/com/example/chain/vo/QuotaVO.java: -------------------------------------------------------------------------------- 1 | package com.example.chain.vo; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @author yuelimin 9 | * @version 1.0.0 10 | * @since 11 11 | */ 12 | @Data 13 | public class QuotaVO implements Serializable { 14 | 15 | private static final long serialVersionUID = -1118377612058354421L; 16 | 17 | private Long id; 18 | 19 | private String name; 20 | 21 | private String unit; 22 | 23 | private String subject; 24 | 25 | private String valueKey; 26 | 27 | private String snKey; 28 | 29 | private String webhook; 30 | 31 | private String valueType; 32 | 33 | private String referenceValue; 34 | } 35 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-chain/src/main/java/com/example/chain/dto/DeviceHeapDTO.java: -------------------------------------------------------------------------------- 1 | package com.example.chain.dto; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import lombok.Data; 5 | import lombok.experimental.Accessors; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * @author yuelimin 11 | * @version 1.0.0 12 | * @since 11 13 | */ 14 | @Data 15 | @Accessors(chain = true) 16 | @JsonInclude(JsonInclude.Include.NON_NULL) 17 | public class DeviceHeapDTO implements Serializable { 18 | 19 | private static final long serialVersionUID = -4973414434354106271L; 20 | 21 | private String deviceId; 22 | 23 | private String heapValue; 24 | 25 | private String quotaId; 26 | 27 | private String quotaName; 28 | } 29 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/api/alarmManage.ts: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // 获取报警日志 4 | export const getAlarmLog = (data: any) => 5 | request({ 6 | url: '/api/alarm-log/search', 7 | method: 'post', 8 | data 9 | }) 10 | 11 | export const alarm = (data: any) => 12 | request({ 13 | url: '/api/alarm/search', 14 | method: 'post', 15 | data 16 | }) 17 | export const addAlarm = (data: any) => 18 | request({ 19 | url: '/api/alarm', 20 | method: 'post', 21 | data 22 | }) 23 | export const putAlarm = (data: any) => 24 | request({ 25 | url: '/api/alarm', 26 | method: 'put', 27 | data 28 | }) 29 | export const delAlarm = (data: any) => 30 | request({ 31 | url: `/api/alarm/${data}`, 32 | method: 'delete', 33 | }) 34 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/components/Hamburger/index.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 28 | 29 | 38 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-monitoring/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # 配置Tomcat头信息 2 | server: 3 | tomcat: 4 | remote-ip-header: x-forwarded-for 5 | protocol-header: x-forwarded-proto 6 | servlet: 7 | context-path: / 8 | use-forward-headers: true 9 | port: 57000 10 | 11 | # HTTP格式配置 12 | spring: 13 | http: 14 | encoding: 15 | charset: UTF-8 16 | force: true 17 | enabled: true 18 | messages: 19 | encoding: UTF-8 20 | application: 21 | name: hardware-monitor-monitoring 22 | main: 23 | allow-bean-definition-overriding: true 24 | banner-mode: 'off' 25 | security: 26 | user: 27 | name: yueliminvc@outlook.com 28 | password: yueliminvc@outlook.com 29 | 30 | # 日志配置 31 | #logging: 32 | # config: classpath:log4j2.xml 33 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-chain/src/main/java/com/example/chain/dto/DeviceTrendDTO.java: -------------------------------------------------------------------------------- 1 | package com.example.chain.dto; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import lombok.Data; 5 | import lombok.experimental.Accessors; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * 报表-设备趋势实体类 11 | * @author yuelimin 12 | * @version 1.0.0 13 | * @since 11 14 | */ 15 | @Data 16 | @Accessors(chain = true) 17 | @JsonInclude(JsonInclude.Include.NON_NULL) 18 | public class DeviceTrendDTO implements Serializable { 19 | 20 | private static final long serialVersionUID = -1868771922171806517L; 21 | 22 | /** 23 | * y轴(数据) 24 | */ 25 | private String series; 26 | 27 | /** 28 | * x轴(标题)1小时内的分钟 2每日的小时 3每周的天 29 | */ 30 | private String xdata; 31 | } 32 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | tomcat: 3 | remote-ip-header: x-forwarded-for 4 | protocol-header: x-forwarded-proto 5 | servlet: 6 | context-path: / 7 | use-forward-headers: true 8 | port: 57100 9 | 10 | spring: 11 | application: 12 | name: @project.artifactId@ 13 | main: 14 | banner-mode: 'off' 15 | allow-bean-definition-overriding: true 16 | profiles: 17 | active: feature 18 | http: 19 | encoding: 20 | charset: UTF-8 21 | force: true 22 | enabled: true 23 | messages: 24 | encoding: UTF-8 25 | 26 | info: 27 | jdk-version: '@java.version@' 28 | name: '@project.name@' 29 | description: '@project.description@' 30 | version: '@project.version@' 31 | spring-boot-version: '@spring-boot.version@' -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-chain/src/main/java/com/example/chain/dto/BoardDTO.java: -------------------------------------------------------------------------------- 1 | package com.example.chain.dto; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | import java.time.LocalDateTime; 7 | 8 | /** 9 | * @author yuelimin 10 | * @version 1.0.0 11 | * @since 11 12 | */ 13 | @Data 14 | public class BoardDTO implements Serializable { 15 | 16 | private static final long serialVersionUID = -3032234483449186550L; 17 | 18 | private Long id; 19 | 20 | private Long userId; 21 | 22 | private String boardName; 23 | 24 | private String quota; 25 | 26 | private String device; 27 | 28 | private String isSystem; 29 | 30 | private String isDisable; 31 | 32 | private LocalDateTime createTime; 33 | 34 | private LocalDateTime updateTime; 35 | } 36 | -------------------------------------------------------------------------------- /hardware-monitor-common/src/main/java/com/example/common/utils/SaltUtil.java: -------------------------------------------------------------------------------- 1 | package com.example.common.utils; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * @author YueLiMin 7 | * @version 1.0.0 8 | * @since 11 9 | */ 10 | public class SaltUtil { 11 | /** 12 | * 获取指定位数的随机盐 13 | * 14 | * @param x 字符数 15 | * @return 随机盐值 16 | */ 17 | public static String getRandomSalt(int x) { 18 | char[] chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890!@#$%^&*()".toCharArray(); 19 | StringBuilder stringBuilder = new StringBuilder(); 20 | 21 | for (int i = 0; i < x; i ++) { 22 | char c = chars[new Random().nextInt(chars.length)]; 23 | stringBuilder.append(c); 24 | } 25 | 26 | return stringBuilder.toString(); 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/icons/components/eye-off.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* tslint:disable */ 3 | // @ts-ignore 4 | import icon from 'vue-svgicon' 5 | 6 | icon.register({ 7 | 'eye-off': { 8 | width: 128, 9 | height: 64, 10 | viewBox: '0 0 128 64', 11 | data: '' 12 | } 13 | }) 14 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-chain/src/main/java/com/example/chain/dto/DeviceGeoDetails.java: -------------------------------------------------------------------------------- 1 | package com.example.chain.dto; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | import java.util.List; 8 | 9 | /** 10 | * @author yuelimin 11 | * @version 1.0.0 12 | * @since 11 13 | */ 14 | @Data 15 | @JsonInclude(JsonInclude.Include.NON_NULL) 16 | public class DeviceGeoDetails implements Serializable { 17 | 18 | private static final long serialVersionUID = 7013925172323976837L; 19 | 20 | private String deviceId; 21 | 22 | private Integer level; 23 | 24 | private String latitude; 25 | 26 | private String longitude; 27 | 28 | private Boolean alarm; 29 | 30 | private Boolean online; 31 | 32 | private List quotaList; 33 | } 34 | -------------------------------------------------------------------------------- /hardware-monitor-common/src/main/java/com/example/common/exception/BusinessException.java: -------------------------------------------------------------------------------- 1 | package com.example.common.exception; 2 | 3 | /** 4 | * 自定义业务异常 5 | * 6 | * @author yuelimin 7 | * @version 1.0.0 8 | * @since 11 9 | */ 10 | public class BusinessException extends RuntimeException { 11 | private Integer errorCode; 12 | private final String message; 13 | 14 | public BusinessException(Integer errorCode, String message) { 15 | super(message); 16 | this.message = message; 17 | this.errorCode = errorCode; 18 | } 19 | 20 | public BusinessException(String message) { 21 | super(message); 22 | this.message = message; 23 | } 24 | 25 | public Integer getErrorCode() { 26 | return errorCode; 27 | } 28 | 29 | @Override 30 | public String getMessage() { 31 | return message; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /hardware-monitor-ui/.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | charset = utf-8 9 | end_of_line = lf 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | 13 | # Indentation override for js(x), ts(x) and vue files 14 | [*.{js,jsx,ts,tsx,vue}] 15 | indent_size = 2 16 | indent_style = space 17 | 18 | # Indentation override for css related files 19 | [*.{css,styl,scss,less,sass}] 20 | indent_size = 2 21 | indent_style = space 22 | 23 | # Indentation override for html files 24 | [*.html] 25 | indent_size = 2 26 | indent_style = space 27 | 28 | # Trailing space override for markdown file 29 | [*.md] 30 | trim_trailing_whitespace = false 31 | 32 | # Indentation override for config files 33 | [*.{json,yml}] 34 | indent_size = 2 35 | indent_style = space 36 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/styles/_variables.scss: -------------------------------------------------------------------------------- 1 | /* Variables */ 2 | 3 | // Base color 4 | $blue: #324157; 5 | $light-blue: #3A71A8; 6 | $red: #C03639; 7 | $pink: #E65D6E; 8 | $green: #30B08F; 9 | $tiffany: #4AB7BD; 10 | $yellow: #FEC171; 11 | $panGreen: #30B08F; 12 | 13 | // Sidebar 14 | $sideBarWidth: 0px; 15 | $subMenuBg: #1f2d3d; 16 | $subMenuHover: #001528; 17 | $subMenuActiveText: #f4f4f5; 18 | $menuBg: #304156; 19 | $menuText: #bfcbd9; 20 | $menuActiveText: #409EFF; // Also see settings.sidebarTextTheme 21 | 22 | // Login page 23 | $lightGray: #999999; 24 | $darkGray: #889aa4; 25 | $loginBg: #2d3a4b; 26 | $loginCursorColor: #fff; 27 | 28 | // The :export directive is the magic sauce for webpack 29 | // https://mattferderer.com/use-sass-variables-in-typescript-and-javascript 30 | :export { 31 | menuBg: $menuBg; 32 | menuText: $menuText; 33 | menuActiveText: $menuActiveText; 34 | } 35 | -------------------------------------------------------------------------------- /hardware-monitor-ui/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "strict": true, 6 | "jsx": "preserve", 7 | "importHelpers": true, 8 | "moduleResolution": "node", 9 | "experimentalDecorators": true, 10 | "esModuleInterop": true, 11 | "allowSyntheticDefaultImports": true, 12 | "sourceMap": true, 13 | "baseUrl": ".", 14 | "types": [ 15 | "node", 16 | "jest", 17 | "webpack-env" 18 | ], 19 | "paths": { 20 | "@/*": [ 21 | "src/*" 22 | ] 23 | }, 24 | "lib": [ 25 | "esnext", 26 | "dom", 27 | "dom.iterable", 28 | "scripthost" 29 | ] 30 | }, 31 | "include": [ 32 | "src/**/*.ts", 33 | "src/**/*.tsx", 34 | "src/**/*.vue", 35 | "tests/**/*.ts", 36 | "tests/**/*.tsx" 37 | ], 38 | "exclude": [ 39 | "node_modules" 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /hardware-monitor-web/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | hardware-monitor 7 | org.example 8 | 1.0.0 9 | 10 | 4.0.0 11 | 12 | hardware-monitor-web 13 | pom 14 | 15 | hardware-monitor-backend 16 | hardware-monitor-monitoring 17 | 18 | 19 | 20 | 11 21 | 11 22 | 23 | 24 | -------------------------------------------------------------------------------- /hardware-monitor-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | hardware-monitor 7 | org.example 8 | 1.0.0 9 | 10 | 4.0.0 11 | 12 | hardware-monitor-service 13 | pom 14 | 15 | hardware-monitor-service-admin 16 | hardware-monitor-service-chain 17 | 18 | 19 | 20 | 11 21 | 11 22 | 23 | 24 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/service/admin/IUserService.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.service.admin; 2 | 3 | import com.example.admin.dto.LoginResultDTO; 4 | import com.example.admin.vo.LoginVO; 5 | import com.example.admin.vo.UserVO; 6 | import com.example.common.exception.BusinessException; 7 | 8 | /** 9 | * @author yuelimin 10 | * @version 1.0.0 11 | * @since 11 12 | */ 13 | public interface IUserService { 14 | /** 15 | * 用户登录 16 | * 17 | * @param loginVO com.example.admin.vo.LoginVO 18 | * @return com.example.admin.dto.LoginResultDTO 19 | * @throws BusinessException 自定义业务异常 20 | */ 21 | LoginResultDTO userLogin(LoginVO loginVO) throws Exception; 22 | 23 | /** 24 | * 创建用户 25 | * 26 | * @param userVO com.example.admin.vo.UserVO 27 | * @throws BusinessException 自定义业务异常 28 | */ 29 | void userCreate(UserVO userVO) throws BusinessException; 30 | } 31 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/config/mybatis/MybatisPlusHandler.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.config.mybatis; 2 | 3 | import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; 4 | import org.apache.ibatis.reflection.MetaObject; 5 | import org.springframework.stereotype.Component; 6 | 7 | import java.time.LocalDateTime; 8 | 9 | /** 10 | * @author yuelimin 11 | * @version 1.0.0 12 | * @since 11 13 | */ 14 | @Component 15 | public class MybatisPlusHandler implements MetaObjectHandler { 16 | @Override 17 | public void insertFill(MetaObject metaObject) { 18 | this.setFieldValByName("createTime", LocalDateTime.now(), metaObject); 19 | this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject); 20 | } 21 | 22 | @Override 23 | public void updateFill(MetaObject metaObject) { 24 | this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/api/fingerMark.ts: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | export const quota = (data: any) => 4 | request({ 5 | url: '/api/quota/search', 6 | method: 'post', 7 | data 8 | }) 9 | export const addQuota = (data: any) => 10 | request({ 11 | url: '/api/quota', 12 | method: 'post', 13 | data 14 | }) 15 | export const putQuota = (data: any) => 16 | request({ 17 | url: '/api/quota', 18 | method: 'put', 19 | data 20 | }) 21 | export const delQuota = (id: any) => 22 | request({ 23 | url: `/api/quota/${id}`, 24 | method: 'delete' 25 | }) 26 | 27 | export const gps = () => 28 | request({ 29 | url: '/api/gps', 30 | method: 'get' 31 | }) 32 | export const addGps = (data: any) => 33 | request({ 34 | url: '/api/gps', 35 | method: 'post', 36 | data 37 | }) 38 | export const putGps = (data: any) => 39 | request({ 40 | url: '/api/gps', 41 | method: 'put', 42 | data 43 | }) 44 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-chain/src/main/java/com/example/chain/vo/DevicesVO.java: -------------------------------------------------------------------------------- 1 | package com.example.chain.vo; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @author yuelimin 9 | * @version 1.0.0 10 | * @since 11 11 | */ 12 | @Data 13 | public class DevicesVO implements Serializable { 14 | 15 | private static final long serialVersionUID = -7087423248172756901L; 16 | 17 | /** 18 | * 设备编号 19 | */ 20 | private String deviceId; 21 | 22 | /** 23 | * 告警名称 24 | */ 25 | private String alarmName; 26 | 27 | /** 28 | * 标签 29 | */ 30 | private String tag; 31 | 32 | /** 33 | * 告警级别 34 | */ 35 | private Integer level; 36 | 37 | /** 38 | * 是否告警 39 | */ 40 | private Boolean alarm; 41 | 42 | /** 43 | * 是否在线 44 | */ 45 | private Boolean online; 46 | 47 | /** 48 | * 开关状态 49 | */ 50 | private Boolean status; 51 | } 52 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/styles/_transition.scss: -------------------------------------------------------------------------------- 1 | /* Global transition */ 2 | // See https://vuejs.org/v2/guide/transitions.html for detail 3 | 4 | // fade 5 | .fade-enter-active, 6 | .fade-leave-active { 7 | transition: opacity 0.28s; 8 | } 9 | 10 | .fade-enter, 11 | .fade-leave-active { 12 | opacity: 0; 13 | } 14 | 15 | // fade-transform 16 | .fade-transform-leave-active, 17 | .fade-transform-enter-active { 18 | transition: all .5s; 19 | } 20 | 21 | .fade-transform-enter { 22 | opacity: 0; 23 | transform: translateX(-30px); 24 | } 25 | 26 | .fade-transform-leave-to { 27 | opacity: 0; 28 | transform: translateX(30px); 29 | } 30 | 31 | // breadcrumb 32 | .breadcrumb-enter-active, 33 | .breadcrumb-leave-active { 34 | transition: all .5s; 35 | } 36 | 37 | .breadcrumb-enter, 38 | .breadcrumb-leave-active { 39 | opacity: 0; 40 | transform: translateX(20px); 41 | } 42 | 43 | .breadcrumb-move { 44 | transition: all .5s; 45 | } 46 | 47 | .breadcrumb-leave-active { 48 | position: absolute; 49 | } 50 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/icons/svg/eye-on.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-admin/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | hardware-monitor-service 7 | org.example 8 | 1.0.0 9 | 10 | 4.0.0 11 | 12 | hardware-monitor-service-admin 13 | 14 | 15 | 11 16 | 11 17 | 18 | 19 | 20 | 21 | org.example 22 | hardware-monitor-common 23 | 1.0.0 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-chain/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | hardware-monitor-service 7 | org.example 8 | 1.0.0 9 | 10 | 4.0.0 11 | 12 | hardware-monitor-service-chain 13 | 14 | 15 | 11 16 | 11 17 | 18 | 19 | 20 | 21 | org.example 22 | hardware-monitor-common 23 | 1.0.0 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/registerServiceWorker.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import {register} from 'register-service-worker' 4 | 5 | if (process.env.NODE_ENV === 'production') { 6 | register(`${process.env.BASE_URL}service-worker.js`, { 7 | ready() { 8 | console.log( 9 | 'App is being served from cache by a service worker.\n' + 10 | 'For more details, visit https://googl/AFskqB' 11 | ) 12 | }, 13 | registered() { 14 | console.log('Service worker has been registered.') 15 | }, 16 | cached() { 17 | console.log('Content has been cached for offline use.') 18 | }, 19 | updatefound() { 20 | console.log('New content is downloading.') 21 | }, 22 | updated() { 23 | console.log('New content is available; please refresh.') 24 | }, 25 | offline() { 26 | console.log('No internet connection found. App is running in offline mode.') 27 | }, 28 | error(error) { 29 | console.error('Error during service worker registration:', error) 30 | } 31 | }) 32 | } 33 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-chain/src/main/java/com/example/chain/dto/DevicesDTO.java: -------------------------------------------------------------------------------- 1 | package com.example.chain.dto; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * @author yuelimin 10 | * @version 1.0.0 11 | * @since 11 12 | */ 13 | @Data 14 | @JsonInclude(JsonInclude.Include.NON_NULL) 15 | public class DevicesDTO implements Serializable { 16 | 17 | private static final long serialVersionUID = -5785884079354833250L; 18 | 19 | /** 20 | * 设备编号 21 | */ 22 | private String deviceId; 23 | 24 | /** 25 | * 告警名称 26 | */ 27 | private String alarmName; 28 | 29 | /** 30 | * 标签 31 | */ 32 | private String tag; 33 | 34 | /** 35 | * 告警级别 36 | */ 37 | private Integer level; 38 | 39 | /** 40 | * 是否告警 41 | */ 42 | private Boolean alarm; 43 | 44 | /** 45 | * 是否在线 46 | */ 47 | private Boolean online; 48 | 49 | /** 50 | * 开关状态 51 | */ 52 | private Boolean status; 53 | } 54 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/controller/error/Error404Controller.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.controller.error; 2 | 3 | import com.example.common.domain.RestResponse; 4 | import org.springframework.boot.web.servlet.error.ErrorController; 5 | import org.springframework.http.HttpStatus; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.ResponseStatus; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | /** 11 | * @author yuelimin 12 | * @version 1.0.0 13 | * @since 11 14 | */ 15 | @RestController 16 | public class Error404Controller implements ErrorController { 17 | private static final String ERROR_PATH = "/error"; 18 | 19 | @RequestMapping(value = ERROR_PATH) 20 | @ResponseStatus(value = HttpStatus.NOT_FOUND) 21 | public RestResponse handleError() { 22 | return RestResponse.fail("资源丢失, 呜呜呜"); 23 | } 24 | 25 | @Override 26 | public String getErrorPath() { 27 | return ERROR_PATH; 28 | } 29 | } 30 | 31 | 32 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/icons/components/eye-on.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* tslint:disable */ 3 | // @ts-ignore 4 | import icon from 'vue-svgicon' 5 | 6 | icon.register({ 7 | 'eye-on': { 8 | width: 128, 9 | height: 128, 10 | viewBox: '0 0 1024 1024', 11 | data: '' 12 | } 13 | }) 14 | -------------------------------------------------------------------------------- /hardware-monitor-ui/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Chong Guo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/config/web/LocalDateTimeSerializerConfig.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.config.web; 2 | 3 | import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; 4 | import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | import java.time.LocalDateTime; 9 | import java.time.format.DateTimeFormatter; 10 | 11 | /** 12 | * @author yuelimin 13 | * @version 1.0.0 14 | * @since 11 15 | */ 16 | @Configuration 17 | public class LocalDateTimeSerializerConfig { 18 | 19 | @Bean 20 | public LocalDateTimeSerializer localDateTimeDeserializer() { 21 | String pattern = "yyyy-MM-dd HH:mm:ss"; 22 | return new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(pattern)); 23 | } 24 | 25 | @Bean 26 | public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() { 27 | return builder -> builder.serializerByType(LocalDateTime.class, localDateTimeDeserializer()); 28 | } 29 | } 30 | 31 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-chain/src/main/java/com/example/chain/dto/DeviceQuotaDTO.java: -------------------------------------------------------------------------------- 1 | package com.example.chain.dto; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | import java.util.List; 8 | 9 | /** 10 | * @author yuelimin 11 | * @version 1.0.0 12 | * @since 11 13 | */ 14 | @Data 15 | @JsonInclude(JsonInclude.Include.NON_NULL) 16 | public class DeviceQuotaDTO implements Serializable { 17 | 18 | private static final long serialVersionUID = -6387513644132639728L; 19 | 20 | /** 21 | * 设备编号 22 | */ 23 | private String deviceId; 24 | 25 | /** 26 | * 告警名称 27 | */ 28 | private String alarmName; 29 | 30 | /** 31 | * 标签 32 | */ 33 | private String tag; 34 | 35 | /** 36 | * 告警级别 37 | */ 38 | private Integer level; 39 | 40 | /** 41 | * 是否告警 42 | */ 43 | private Boolean alarm; 44 | 45 | /** 46 | * 是否在线 47 | */ 48 | private Boolean online; 49 | 50 | /** 51 | * 开关状态 52 | */ 53 | private Boolean status; 54 | 55 | private List quotaList; 56 | } 57 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/icons/svg/tree.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /hardware-monitor-common/src/main/java/com/example/common/domain/RestPageResult.java: -------------------------------------------------------------------------------- 1 | package com.example.common.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * 分页响应体 10 | * 11 | * @author yuelimin 12 | * @version 1.0.0 13 | * @since 11 14 | */ 15 | @Data 16 | @JsonInclude(JsonInclude.Include.NON_NULL) 17 | public class RestPageResult implements Serializable { 18 | 19 | private static final long serialVersionUID = 8894547939662899733L; 20 | 21 | /** 22 | * 总条数 23 | */ 24 | private Long counts; 25 | /** 26 | * 每页条数 27 | */ 28 | private Long pageSize; 29 | /** 30 | * 总页数 31 | */ 32 | private Long pages; 33 | /** 34 | * 当前页数 35 | */ 36 | private Long page; 37 | 38 | private T items; 39 | 40 | public RestPageResult() { 41 | } 42 | 43 | public RestPageResult(Long counts, Long pageSize, Long pages, Long page, T data) { 44 | this.counts = counts; 45 | this.pageSize = pageSize; 46 | this.pages = pages; 47 | this.page = page; 48 | this.items = data; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-chain/src/main/java/com/example/chain/vo/AlarmVO.java: -------------------------------------------------------------------------------- 1 | package com.example.chain.vo; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @author yuelimin 9 | * @version 1.0.0 10 | * @since 11 11 | */ 12 | @Data 13 | public class AlarmVO implements Serializable { 14 | 15 | private static final long serialVersionUID = 126653584931390426L; 16 | 17 | private Long id; 18 | 19 | /** 20 | * 告警名称 21 | */ 22 | private String name; 23 | 24 | /** 25 | * 指标id 26 | */ 27 | private Long quotaId; 28 | 29 | /** 30 | * 指标名称 31 | */ 32 | private String quotaName; 33 | 34 | /** 35 | * 运算符 > < = 36 | */ 37 | private String operator; 38 | 39 | /** 40 | * 预警值 41 | */ 42 | private String threshold; 43 | 44 | /** 45 | * 级别 0-正常 1-一般 2-严重 46 | */ 47 | private Integer level; 48 | 49 | /** 50 | * 沉默周期-分钟 51 | */ 52 | private Integer cycle; 53 | 54 | /** 55 | * webhook-业务服务地址 56 | */ 57 | private String webhook; 58 | 59 | /** 60 | * 冗余-配合前端(傻狗前端) 61 | */ 62 | private Integer time; 63 | } 64 | -------------------------------------------------------------------------------- /hardware-monitor-ui/vue.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const name = 'Vue Typescript Admin' 3 | 4 | module.exports = { 5 | // TODO: Remember to change this to fit your need 6 | publicPath: process.env.NODE_ENV === 'production' ? './' : './', 7 | // lintOnSave: process.env.NODE_ENV === 'development', 8 | lintOnSave: false, 9 | pwa: { 10 | name: name 11 | }, 12 | pluginOptions: { 13 | 'style-resources-loader': { 14 | preProcessor: 'scss', 15 | patterns: [ 16 | path.resolve(__dirname, 'src/styles/_variables.scss'), 17 | path.resolve(__dirname, 'src/styles/_mixins.scss') 18 | ] 19 | } 20 | }, 21 | chainWebpack(config) { 22 | // Provide the app's title in webpack's name field, so that 23 | // it can be accessed in index.html to inject the correct title. 24 | config.set('name', name) 25 | }, 26 | devServer: { 27 | open: true, 28 | overlay: { 29 | warnings: false, 30 | errors: true 31 | }, 32 | proxy: { 33 | '/api': { 34 | target: `http://127.0.0.1:57100/api`, 35 | changeOrigin: true, 36 | pathRewrite: { 37 | '^/api': '' 38 | } 39 | } 40 | }, 41 | }, 42 | } 43 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-chain/src/main/java/com/example/chain/pojo/AlarmLog.java: -------------------------------------------------------------------------------- 1 | package com.example.chain.pojo; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | *

报警日志elasticsearch pojo类

9 | * 10 | * @author yuelimin 11 | * @version 1.0.0 12 | * @since 11 13 | */ 14 | @Data 15 | public class AlarmLog implements Serializable { 16 | /** 17 | * 设备id 18 | */ 19 | private String deviceId; 20 | 21 | /** 22 | * 指标id 23 | */ 24 | private Long quotaId; 25 | 26 | /** 27 | * 指标名称 28 | */ 29 | private String quotaName; 30 | 31 | /** 32 | * 是否告警 0-不告警 1-告警 33 | */ 34 | private Integer alarm; 35 | 36 | /** 37 | * 告警级别 0-正常 1-一般警报 2-严重警报 38 | */ 39 | private Integer level; 40 | 41 | /** 42 | * 告警名称 43 | */ 44 | private String alarmName; 45 | 46 | /** 47 | * 单位 48 | */ 49 | private String unit; 50 | 51 | /** 52 | * 参考值 53 | */ 54 | private String referenceValue; 55 | 56 | /** 57 | * 数值指标 58 | */ 59 | private String value; 60 | 61 | /** 62 | * 告警时间(秒) 63 | */ 64 | private Long alarmLogTime; 65 | } 66 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-chain/src/main/java/com/example/chain/dto/AlarmDTO.java: -------------------------------------------------------------------------------- 1 | package com.example.chain.dto; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * @author yuelimin 10 | * @version 1.0.0 11 | * @since 11 12 | */ 13 | @Data 14 | @JsonInclude(JsonInclude.Include.NON_NULL) 15 | public class AlarmDTO implements Serializable { 16 | 17 | private static final long serialVersionUID = -9149332207992305704L; 18 | 19 | private Long id; 20 | 21 | /** 22 | * 告警名称 23 | */ 24 | private String name; 25 | 26 | /** 27 | * 指标id 28 | */ 29 | private Long quotaId; 30 | 31 | /** 32 | * 指标名称 33 | */ 34 | private String quotaName; 35 | 36 | /** 37 | * 运算符 > < = 38 | */ 39 | private String operator; 40 | 41 | /** 42 | * 预警值 43 | */ 44 | private String threshold; 45 | 46 | /** 47 | * 级别 0-正常 1-一般 2-严重 48 | */ 49 | private Integer level; 50 | 51 | /** 52 | * 沉默周期-分钟 53 | */ 54 | private Integer cycle; 55 | 56 | /** 57 | * webhook-业务服务地址 58 | */ 59 | private String webhook; 60 | } 61 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/icons/svg/dashboard.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /hardware-monitor-ui/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | moduleFileExtensions: [ 3 | 'js', 4 | 'jsx', 5 | 'json', 6 | 'vue', 7 | 'ts', 8 | 'tsx' 9 | ], 10 | transform: { 11 | '^.+\\.vue$': 'vue-jest', 12 | '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub', 13 | '^.+\\.tsx?$': 'ts-jest' 14 | }, 15 | transformIgnorePatterns: [ 16 | '/node_modules/' 17 | ], 18 | moduleNameMapper: { 19 | '^@/(.*)$': '/src/$1' 20 | }, 21 | snapshotSerializers: [ 22 | 'jest-serializer-vue' 23 | ], 24 | testMatch: [ 25 | '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)' 26 | ], 27 | collectCoverage: true, 28 | collectCoverageFrom: [ 29 | 'src/utils/**/*.{ts,vue}', 30 | '!src/utils/auth.ts', 31 | '!src/utils/request.ts', 32 | 'src/components/**/*.{ts,vue}' 33 | ], 34 | coverageDirectory: '/tests/unit/coverage', 35 | coverageReporters: [ 36 | 'lcov', 37 | 'text-summary' 38 | ], 39 | testURL: 'http://localhost/', 40 | watchPlugins: [ 41 | 'jest-watch-typeahead/filename', 42 | 'jest-watch-typeahead/testname' 43 | ], 44 | globals: { 45 | 'ts-jest': { 46 | babelConfig: true 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/controller/chain/DeviceGeoController.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.controller.chain; 2 | 3 | import com.example.backend.service.chain.IDeviceGeoService; 4 | import com.example.chain.dto.DeviceGeoDetails; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.PathVariable; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * @author yuelimin 15 | * @version 1.0.0 16 | * @since 11 17 | */ 18 | @RestController 19 | @RequestMapping("/api") 20 | public class DeviceGeoController { 21 | @Autowired 22 | private IDeviceGeoService deviceGeoService; 23 | 24 | @GetMapping("/gps/device-details/{latitude}/{longitude}/{distance}") 25 | public List deviceGeoDetailsList(@PathVariable("latitude") Double latitude, @PathVariable("longitude") Double longitude, @PathVariable("distance") String distance) { 26 | return deviceGeoService.searchDeviceGeoLocationDetails(longitude, latitude, distance); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/service/chain/IGpsService.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.service.chain; 2 | 3 | import com.example.chain.dto.GpsDTO; 4 | import com.example.chain.vo.GpsVO; 5 | import com.example.common.exception.BusinessException; 6 | 7 | /** 8 | * @author yuelimin 9 | * @version 1.0.0 10 | * @since 11 11 | */ 12 | public interface IGpsService { 13 | /** 14 | * 获取gps位置信息 15 | * 16 | * @return com.example.chain.dto.GpsDTO 17 | * @throws BusinessException 业务异常 18 | */ 19 | GpsDTO findGps() throws BusinessException; 20 | 21 | /** 22 | * 更新gps位置信息 23 | * 24 | * @param gpsVO 25 | * @throws BusinessException 26 | */ 27 | void updateGpsById(GpsVO gpsVO) throws BusinessException; 28 | 29 | /** 30 | * 移除gps位置信信息 31 | * 32 | * @param id java.lang.Long 33 | * @throws BusinessException 业务异常 34 | */ 35 | void removeGpsById(Long id) throws BusinessException; 36 | 37 | /** 38 | * 新增gps位置信息 39 | * gps位置信息有一点特殊, 实际上只是需要配置一个gps基本信息 40 | * 41 | * @param gpsVO com.example.chain.vo.GpsVO 42 | * @throws BusinessException 业务异常 43 | */ 44 | void creatGps(GpsVO gpsVO) throws BusinessException; 45 | } 46 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/controller/chain/AlarmLogController.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.controller.chain; 2 | 3 | import com.example.backend.service.chain.IAlarmLogService; 4 | import com.example.chain.dto.AlarmLogDTO; 5 | import com.example.chain.query.AlarmLogQuery; 6 | import com.example.common.domain.RestPageResult; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.web.bind.annotation.PostMapping; 9 | import org.springframework.web.bind.annotation.RequestBody; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | import java.io.IOException; 14 | import java.text.ParseException; 15 | import java.util.List; 16 | 17 | /** 18 | * @author yuelimin 19 | * @version 1.0.0 20 | * @since 11 21 | */ 22 | @RestController 23 | @RequestMapping("/api") 24 | public class AlarmLogController { 25 | @Autowired 26 | private IAlarmLogService alarmLogService; 27 | 28 | @PostMapping("/alarm-log/search") 29 | public RestPageResult> searchAlarmLog(@RequestBody AlarmLogQuery alarmLogQuery) throws ParseException, IOException { 30 | return alarmLogService.searchAlarmLog(alarmLogQuery); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-admin/src/main/java/com/example/admin/pojo/User.java: -------------------------------------------------------------------------------- 1 | package com.example.admin.pojo; 2 | 3 | import com.baomidou.mybatisplus.annotation.*; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | import java.time.LocalDateTime; 8 | 9 | /** 10 | * @author yuelimin 11 | * @version 1.0.0 12 | * @since 11 13 | */ 14 | @Data 15 | @TableName(value = "tb_user") 16 | public class User implements Serializable { 17 | 18 | private static final long serialVersionUID = 7910360494957237761L; 19 | 20 | @TableId(value = "id",type = IdType.ID_WORKER) 21 | private Long id; 22 | 23 | @TableField(value = "login_name") 24 | private String loginName; 25 | 26 | @TableField(value = "password") 27 | private String password; 28 | 29 | @TableField(value = "type") 30 | private String type; 31 | 32 | @TableField(value = "board") 33 | private String board; 34 | 35 | @TableField(value = "salt") 36 | private String salt; 37 | 38 | @TableField(value = "status") 39 | private String status; 40 | 41 | @TableField(value = "create_time", fill = FieldFill.INSERT) 42 | private LocalDateTime createTime; 43 | 44 | @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) 45 | private LocalDateTime updateTime; 46 | } 47 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-chain/src/main/java/com/example/chain/dto/AlarmLogDTO.java: -------------------------------------------------------------------------------- 1 | package com.example.chain.dto; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * @author yuelimin 9 | * @version 1.0.0 10 | * @since 11 11 | */ 12 | @Data 13 | public class AlarmLogDTO implements Serializable { 14 | 15 | private static final long serialVersionUID = 290191026653721239L; 16 | 17 | /** 18 | * 设备id 19 | */ 20 | private String deviceId; 21 | 22 | /** 23 | * 指标id 24 | */ 25 | private Long quotaId; 26 | 27 | /** 28 | * 指标名称 29 | */ 30 | private String quotaName; 31 | 32 | /** 33 | * 是否告警 0:不告警 1:告警 34 | */ 35 | private Integer alarm; 36 | 37 | /** 38 | * 告警级别 39 | */ 40 | private Integer level; 41 | 42 | /** 43 | * 告警名称 44 | */ 45 | private String alarmName; 46 | 47 | /** 48 | * 单位 49 | */ 50 | private String unit; 51 | 52 | /** 53 | * 参考值 54 | */ 55 | private String referenceValue; 56 | 57 | /** 58 | * 数值指标 59 | */ 60 | private String value; 61 | 62 | /** 63 | * 告警时间 64 | */ 65 | private String time; 66 | 67 | /** 68 | * 是否在线 69 | */ 70 | private Boolean online; 71 | } 72 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-chain/src/main/java/com/example/chain/pojo/Board.java: -------------------------------------------------------------------------------- 1 | package com.example.chain.pojo; 2 | 3 | import com.baomidou.mybatisplus.annotation.*; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | import java.time.LocalDateTime; 8 | 9 | /** 10 | * @author yuelimin 11 | * @version 1.0.0 12 | * @since 11 13 | */ 14 | @Data 15 | @TableName("tb_board") 16 | public class Board implements Serializable { 17 | 18 | private static final long serialVersionUID = 6823556155875683405L; 19 | 20 | @TableId(value = "id", type = IdType.ID_WORKER) 21 | private Long id; 22 | 23 | @TableField(value = "user_id") 24 | private Long userId; 25 | 26 | @TableField(value = "board_name") 27 | private String boardName; 28 | 29 | @TableField(value = "quota") 30 | private String quota; 31 | 32 | @TableField(value = "device") 33 | private String device; 34 | 35 | @TableField(value = "is_system") 36 | private String isSystem; 37 | 38 | @TableField(value = "is_disable") 39 | private String isDisable; 40 | 41 | @TableField(value = "create_time", fill = FieldFill.INSERT) 42 | private LocalDateTime createTime; 43 | 44 | @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) 45 | private LocalDateTime updateTime; 46 | } 47 | -------------------------------------------------------------------------------- /hardware-monitor-ui/.eslintrc.js: -------------------------------------------------------------------------------- 1 | // module.exports = { 2 | // root: true, 3 | // env: { 4 | // browser: true, 5 | // node: true, 6 | // es6: true 7 | // }, 8 | // parserOptions: { 9 | // parser: '@typescript-eslint/parser', 10 | // sourceType: 'module' 11 | // }, 12 | // plugins: [ 13 | // 'vue' 14 | // ], 15 | // rules: { 16 | // 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 17 | // 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', 18 | // 'space-before-function-paren': [2, 'never'], 19 | // 'vue/array-bracket-spacing': 'error', 20 | // 'vue/arrow-spacing': 'error', 21 | // 'vue/block-spacing': 'error', 22 | // 'vue/brace-style': 'error', 23 | // 'vue/camelcase': 'error', 24 | // 'vue/comma-dangle': 'error', 25 | // 'vue/component-name-in-template-casing': 'error', 26 | // 'vue/eqeqeq': 'error', 27 | // 'vue/key-spacing': 'error', 28 | // 'vue/match-component-file-name': 'error', 29 | // 'vue/object-curly-spacing': 'error', 30 | // 'semi': 0, 31 | // "quotes": [1, "double"], 32 | // "space-before-function-paren": 0, 33 | // }, 34 | // 'extends': [ 35 | // 'eslint:recommended', 36 | // 'plugin:vue/recommended', 37 | // '@vue/standard', 38 | // '@vue/typescript' 39 | // ] 40 | // } 41 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-monitoring/src/main/java/com/example/monitoring/WebMonitoringApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.monitoring; 2 | 3 | import de.codecentric.boot.admin.server.config.EnableAdminServer; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; 7 | import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; 8 | import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration; 9 | import org.springframework.context.annotation.ComponentScan; 10 | 11 | /** 12 | *

13 | * @EnableAdminServer 开启管理端 14 | * @ComponentScan(basePackages = {"com.example.monitoring.config"}) 扫描配置类 15 | *

16 | * 17 | * @author yuelimin 18 | * @version 1.0.0 19 | * @since 11 20 | */ 21 | @EnableAdminServer 22 | @SpringBootApplication(exclude = { 23 | DataSourceAutoConfiguration.class, 24 | RedisAutoConfiguration.class, 25 | MongoAutoConfiguration.class 26 | }) 27 | @ComponentScan(basePackages = {"com.example.monitoring.config"}) 28 | public class WebMonitoringApplication { 29 | public static void main(String[] args) { 30 | SpringApplication.run(WebMonitoringApplication.class, args); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/icons/components/tree.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* tslint:disable */ 3 | // @ts-ignore 4 | import icon from 'vue-svgicon' 5 | 6 | icon.register({ 7 | 'tree': { 8 | width: 128, 9 | height: 128, 10 | viewBox: '0 0 128 128', 11 | data: '' 12 | } 13 | }) 14 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/icons/components/dashboard.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* tslint:disable */ 3 | // @ts-ignore 4 | import icon from 'vue-svgicon' 5 | 6 | icon.register({ 7 | 'dashboard': { 8 | width: 128, 9 | height: 100, 10 | viewBox: '0 0 128 100', 11 | data: '' 12 | } 13 | }) 14 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/controller/chain/GpsController.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.controller.chain; 2 | 3 | import com.example.backend.service.chain.IGpsService; 4 | import com.example.chain.dto.GpsDTO; 5 | import com.example.chain.vo.GpsVO; 6 | import com.example.common.domain.RestResponse; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.web.bind.annotation.*; 9 | 10 | /** 11 | * @author yuelimin 12 | * @version 1.0.0 13 | * @since 11 14 | */ 15 | @RestController 16 | @RequestMapping("/api") 17 | public class GpsController { 18 | @Autowired 19 | private IGpsService gpsService; 20 | 21 | @GetMapping("/gps") 22 | public GpsDTO findGps() { 23 | return gpsService.findGps(); 24 | } 25 | 26 | @PutMapping("/gps") 27 | public RestResponse updateGps(@RequestBody GpsVO gpsVO) { 28 | gpsService.updateGpsById(gpsVO); 29 | 30 | return RestResponse.success(); 31 | } 32 | 33 | @DeleteMapping("/gps/{id}") 34 | public RestResponse removeGps(@PathVariable("id") Long id) { 35 | gpsService.removeGpsById(id); 36 | 37 | return RestResponse.success(); 38 | } 39 | 40 | @PostMapping("/gps") 41 | public RestResponse createGps(@RequestBody GpsVO gpsVO) { 42 | gpsService.creatGps(gpsVO); 43 | return RestResponse.success(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-chain/src/main/java/com/example/chain/pojo/Alarm.java: -------------------------------------------------------------------------------- 1 | package com.example.chain.pojo; 2 | 3 | import com.baomidou.mybatisplus.annotation.*; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | import java.time.LocalDateTime; 8 | 9 | /** 10 | * @author yuelimin 11 | * @version 1.0.0 12 | * @since 11 13 | */ 14 | @Data 15 | @TableName("tb_alarm") 16 | public class Alarm implements Serializable { 17 | 18 | private static final long serialVersionUID = -7831447148841590870L; 19 | 20 | @TableId(value = "id", type = IdType.ID_WORKER) 21 | private Long id; 22 | 23 | @TableField(value = "name") 24 | private String name; 25 | 26 | @TableField(value = "quota_id") 27 | private Long quotaId; 28 | 29 | @TableField(value = "operator") 30 | private String operator; 31 | 32 | @TableField(value = "threshold") 33 | private String threshold; 34 | 35 | @TableField(value = "level") 36 | private Integer level; 37 | 38 | @TableField(value = "cycle") 39 | private Integer cycle; 40 | 41 | @TableField(value = "webhook") 42 | private String webhook; 43 | 44 | @TableField(value = "subject") 45 | private String subject; 46 | 47 | @TableField(value = "create_time", fill = FieldFill.INSERT) 48 | private LocalDateTime createTime; 49 | 50 | @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) 51 | private LocalDateTime updateTime; 52 | } 53 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/service/chain/IAlarmLogService.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.service.chain; 2 | 3 | import com.example.chain.dto.AlarmLogDTO; 4 | import com.example.chain.dto.QuotaDTO; 5 | import com.example.chain.query.AlarmLogQuery; 6 | import com.example.common.domain.RestPageResult; 7 | import com.example.common.exception.BusinessException; 8 | 9 | import java.io.IOException; 10 | import java.text.ParseException; 11 | import java.util.List; 12 | 13 | /** 14 | * @author yuelimin 15 | * @version 1.0.0 16 | * @since 11 17 | */ 18 | public interface IAlarmLogService { 19 | /** 20 | * 根据设备id获取最新一条告警日志 21 | * 22 | * @param deviceId java.lang.String 23 | * @return com.example.chain.dto.AlarmLogDTO 24 | * @throws BusinessException 业务异常 25 | */ 26 | AlarmLogDTO findAlarmLogByTimeDesc(String deviceId) throws BusinessException, IOException, ParseException; 27 | 28 | /** 29 | * 分页条件查询告警日志 30 | * 31 | * @param alarmLogQuery 32 | * @return 33 | * @throws BusinessException 34 | */ 35 | RestPageResult> searchAlarmLog(AlarmLogQuery alarmLogQuery) throws BusinessException, ParseException, IOException; 36 | 37 | /** 38 | * 添加报警日志 39 | * 40 | * @param quotaDTO com.example.chain.dto.QuotaDTO 41 | * @throws BusinessException 业务异常 42 | */ 43 | void createAlarmLog(QuotaDTO quotaDTO) throws BusinessException; 44 | } 45 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/icons/svg/form.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-chain/src/main/java/com/example/chain/pojo/Quota.java: -------------------------------------------------------------------------------- 1 | package com.example.chain.pojo; 2 | 3 | import com.baomidou.mybatisplus.annotation.*; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | import java.time.LocalDateTime; 8 | 9 | /** 10 | * @author yuelimin 11 | * @version 1.0.0 12 | * @since 11 13 | */ 14 | @Data 15 | @TableName("tb_quota") 16 | public class Quota implements Serializable { 17 | 18 | private static final long serialVersionUID = -8622699592160108953L; 19 | 20 | @TableId(value = "id", type = IdType.ID_WORKER) 21 | private Long id; 22 | 23 | @TableField(value = "name") 24 | private String name; 25 | 26 | @TableField(value = "unit") 27 | private String unit; 28 | 29 | @TableField(value = "subject") 30 | private String subject; 31 | 32 | @TableField(value = "value_key") 33 | private String valueKey; 34 | 35 | @TableField(value = "sn_key") 36 | private String snKey; 37 | 38 | @TableField(value = "webhook") 39 | private String webhook; 40 | 41 | @TableField(value = "value_type") 42 | private String valueType; 43 | 44 | @TableField(value = "reference_value") 45 | private String referenceValue; 46 | 47 | @TableField(value = "create_time", fill = FieldFill.INSERT) 48 | private LocalDateTime createTime; 49 | 50 | @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) 51 | private LocalDateTime updateTime; 52 | } 53 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/layout/mixin/resize.ts: -------------------------------------------------------------------------------- 1 | import {Component, Vue, Watch} from 'vue-property-decorator' 2 | import {AppModule, DeviceType} from '@/store/modules/app' 3 | 4 | const WIDTH = 992 // refer to Bootstrap's responsive design 5 | 6 | @Component({ 7 | name: 'ResizeMixin' 8 | }) 9 | export default class extends Vue { 10 | get device() { 11 | return AppModule.device 12 | } 13 | 14 | get sidebar() { 15 | return AppModule.sidebar 16 | } 17 | 18 | @Watch('$route') 19 | private onRouteChange() { 20 | if (this.device === DeviceType.Mobile && this.sidebar.opened) { 21 | AppModule.CloseSideBar(false) 22 | } 23 | } 24 | 25 | beforeMount() { 26 | window.addEventListener('resize', this.resizeHandler) 27 | } 28 | 29 | mounted() { 30 | const isMobile = this.isMobile() 31 | if (isMobile) { 32 | AppModule.ToggleDevice(DeviceType.Mobile) 33 | AppModule.CloseSideBar(true) 34 | } 35 | } 36 | 37 | beforeDestroy() { 38 | window.removeEventListener('resize', this.resizeHandler) 39 | } 40 | 41 | private isMobile() { 42 | const rect = document.body.getBoundingClientRect() 43 | return rect.width - 1 < WIDTH 44 | } 45 | 46 | private resizeHandler() { 47 | if (!document.hidden) { 48 | const isMobile = this.isMobile() 49 | AppModule.ToggleDevice(isMobile ? DeviceType.Mobile : DeviceType.Desktop) 50 | if (isMobile) { 51 | AppModule.CloseSideBar(true) 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /hardware-monitor-common/src/main/java/com/example/common/domain/RestResponse.java: -------------------------------------------------------------------------------- 1 | package com.example.common.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import lombok.Data; 5 | 6 | /** 7 | * 响应体 8 | * 9 | * @author yuelimin 10 | * @version 1.0.0 11 | * @since 11 12 | */ 13 | @Data 14 | @JsonInclude(JsonInclude.Include.NON_NULL) 15 | public class RestResponse { 16 | 17 | private Integer status; 18 | private String msg; 19 | private T result; 20 | 21 | public RestResponse() { 22 | this(0, "success"); 23 | } 24 | 25 | public RestResponse(Integer status, String msg) { 26 | this.status = status; 27 | this.msg = msg; 28 | } 29 | 30 | public static RestResponse success() { 31 | return new RestResponse(); 32 | } 33 | 34 | public static RestResponse success(T result) { 35 | RestResponse response = new RestResponse(); 36 | response.setResult(result); 37 | return response; 38 | } 39 | 40 | public static RestResponse fail(String msg) { 41 | RestResponse response = new RestResponse(); 42 | response.setStatus(400); 43 | response.setMsg(msg); 44 | return response; 45 | } 46 | 47 | public static RestResponse fail(Integer status, String msg) { 48 | RestResponse response = new RestResponse(); 49 | response.setStatus(status); 50 | response.setMsg(msg); 51 | return response; 52 | } 53 | 54 | } 55 | 56 | 57 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-chain/src/main/java/com/example/chain/pojo/Gps.java: -------------------------------------------------------------------------------- 1 | package com.example.chain.pojo; 2 | 3 | import com.baomidou.mybatisplus.annotation.FieldFill; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import lombok.Data; 8 | 9 | import java.io.Serializable; 10 | import java.time.LocalDateTime; 11 | 12 | /** 13 | * @author yuelimin 14 | * @version 1.0.0 15 | * @since 11 16 | */ 17 | @Data 18 | @TableName("tb_gps") 19 | public class Gps implements Serializable { 20 | 21 | private static final long serialVersionUID = 2042406758348642439L; 22 | 23 | @TableId(value = "id") 24 | private Long id; 25 | 26 | @TableField(value = "subject") 27 | private String subject; 28 | 29 | @TableField(value = "sn_key") 30 | private String snKey; 31 | 32 | @TableField(value = "single_field") 33 | private String singleField; 34 | 35 | @TableField(value = "value_key") 36 | private String valueKey; 37 | 38 | @TableField(value = "separation") 39 | private String separation; 40 | 41 | @TableField(value = "longitude") 42 | private String longitude; 43 | 44 | @TableField(value = "latitude") 45 | private String latitude; 46 | 47 | @TableField(value = "create_time", fill = FieldFill.INSERT) 48 | private LocalDateTime createTime; 49 | 50 | @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) 51 | private LocalDateTime updateTime; 52 | } 53 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/components/Table/index.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 50 | 59 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/icons/components/form.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | /* tslint:disable */ 3 | // @ts-ignore 4 | import icon from 'vue-svgicon' 5 | 6 | icon.register({ 7 | 'form': { 8 | width: 128, 9 | height: 128, 10 | viewBox: '0 0 128 128', 11 | data: '' 12 | } 13 | }) 14 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/config/mybatis/MybatisPlusConfig.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.config.mybatis; 2 | 3 | import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; 4 | import com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor; 5 | import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize; 6 | import org.mybatis.spring.annotation.MapperScan; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.context.annotation.Profile; 10 | import org.springframework.transaction.annotation.EnableTransactionManagement; 11 | 12 | /** 13 | * @author yuelimin 14 | * @version 1.0.0 15 | * @since 11 16 | */ 17 | @Configuration 18 | @MapperScan("com.example.**.mapper.**") 19 | @EnableTransactionManagement(proxyTargetClass = true) 20 | public class MybatisPlusConfig { 21 | 22 | /** 23 | * 分页插件 24 | * 25 | * @return PaginationInterceptor 26 | */ 27 | @Bean 28 | public PaginationInterceptor paginationInterceptor() { 29 | PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); 30 | paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true)); 31 | return paginationInterceptor; 32 | } 33 | 34 | /** 35 | * 性能分析插件 36 | * 37 | * @return PerformanceInterceptor 38 | */ 39 | @Bean 40 | @Profile(value = {"dev", "feature"}) 41 | public PerformanceInterceptor performanceInterceptor() { 42 | return new PerformanceInterceptor(); 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/styles/index.scss: -------------------------------------------------------------------------------- 1 | // @import './variables.scss'; // Already imported in style-resources-loader 2 | // @import './mixins.scss'; // Already imported in style-resources-loader 3 | @import './transition.scss'; 4 | @import './svgicon.scss'; 5 | // @import './font-icon.scss'; 6 | @import 'https://at.alicdn.com/t/font_1970909_qog2b4ne0a.css'; 7 | 8 | 9 | /* Global scss */ 10 | 11 | body { 12 | height: 100%; 13 | min-width: 1240px; 14 | -moz-osx-font-smoothing: grayscale; 15 | -webkit-font-smoothing: antialiased; 16 | background-color: #f3f4f7; 17 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif; 18 | } 19 | 20 | html { 21 | height: 100%; 22 | background-color: #f3f4f7; 23 | } 24 | 25 | .BMap_cpyCtrl { 26 | display: none; 27 | } 28 | 29 | .anchorBL { 30 | display: none; 31 | } 32 | 33 | #app { 34 | height: 100%; 35 | } 36 | 37 | *, 38 | *:before, 39 | *:after { 40 | box-sizing: border-box; 41 | } 42 | 43 | a, 44 | a:focus, 45 | a:hover { 46 | color: inherit; 47 | outline: none; 48 | text-decoration: none; 49 | } 50 | 51 | div:focus { 52 | outline: none; 53 | } 54 | 55 | .clearfix { 56 | @include clearfix; 57 | } 58 | 59 | .app-container { 60 | padding: 20px; 61 | } 62 | 63 | .el-form--inline .el-form-item { 64 | margin-right: 25px; 65 | } 66 | 67 | .flex-column-center { 68 | display: flex; 69 | flex-direction: column; 70 | align-items: center; 71 | justify-content: center; 72 | } 73 | 74 | .flex-row-center { 75 | display: flex; 76 | flex-direction: row; 77 | align-items: center; 78 | justify-content: center; 79 | } 80 | -------------------------------------------------------------------------------- /hardware-monitor-common/src/main/java/com/example/common/utils/MD5Util.java: -------------------------------------------------------------------------------- 1 | package com.example.common.utils; 2 | 3 | import org.springframework.util.DigestUtils; 4 | 5 | import java.io.UnsupportedEncodingException; 6 | 7 | /** 8 | *

9 | * MD5加密 10 | * 单向加密算法(不可逆) 11 | * 特点: 加密速度快, 不需要秘钥, 但是安全性不高, 需要搭配随机盐值使用 12 | *

13 | * 14 | * @author YueLiMin 15 | * @version 1.0.0 16 | * @since 11 17 | */ 18 | public class MD5Util { 19 | 20 | /** 21 | * 加密(加密内容, 随机盐, 编码) 22 | * 23 | * @param content 24 | * @param salt 25 | * @param charset 26 | * @return 27 | */ 28 | public static String sign(String content, String salt, String charset) { 29 | content = content + salt; 30 | return DigestUtils.md5DigestAsHex(getContentBytes(content, charset)); 31 | } 32 | 33 | /** 34 | * 对比 35 | * 36 | * @param content 37 | * @param sign 38 | * @param salt 39 | * @param charset 40 | * @return 41 | */ 42 | public static boolean verify(String content, String sign, String salt, String charset) { 43 | content = content + salt; 44 | String mysign = DigestUtils.md5DigestAsHex(getContentBytes(content, charset)); 45 | 46 | return mysign.equals(sign); 47 | } 48 | 49 | private static byte[] getContentBytes(String content, String charset) { 50 | if (!"".equals(charset)) { 51 | try { 52 | return content.getBytes(charset); 53 | } catch (UnsupportedEncodingException var3) { 54 | throw new RuntimeException("MD5签名过程中出现错误, 指定的编码集错误"); 55 | } 56 | } else { 57 | return content.getBytes(); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/controller/chain/AlarmController.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.controller.chain; 2 | 3 | import com.example.backend.service.chain.IAlarmService; 4 | import com.example.chain.dto.AlarmDTO; 5 | import com.example.chain.query.AlarmQuery; 6 | import com.example.chain.vo.AlarmVO; 7 | import com.example.common.domain.RestPageResult; 8 | import com.example.common.domain.RestResponse; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.web.bind.annotation.*; 11 | 12 | import java.util.List; 13 | 14 | /** 15 | * @author yuelimin 16 | * @version 1.0.0 17 | * @since 11 18 | */ 19 | @RestController 20 | @RequestMapping("/api") 21 | public class AlarmController { 22 | @Autowired 23 | private IAlarmService alarmService; 24 | 25 | @PostMapping("/alarm/search") 26 | public RestPageResult> searchAlarm(@RequestBody AlarmQuery alarmQuery) { 27 | return alarmService.searchAlarm(alarmQuery); 28 | } 29 | 30 | @PutMapping("/alarm") 31 | public RestResponse updateById(@RequestBody AlarmVO alarmVO) { 32 | alarmService.updateAlarmById(alarmVO); 33 | 34 | return RestResponse.success(); 35 | } 36 | 37 | @DeleteMapping("/alarm/{id}") 38 | public RestResponse removeById(@PathVariable("id") Long id) { 39 | alarmService.removeAlarmById(id); 40 | 41 | return RestResponse.success(); 42 | } 43 | 44 | @PostMapping("/alarm") 45 | public RestResponse createAlarm(@RequestBody AlarmVO alarmVO) { 46 | alarmService.createAlarm(alarmVO); 47 | 48 | return RestResponse.success(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/store/modules/app.ts: -------------------------------------------------------------------------------- 1 | import {Action, getModule, Module, Mutation, VuexModule} from 'vuex-module-decorators' 2 | import {getSidebarStatus, setSidebarStatus} from '@/utils/cookies' 3 | import store from '@/store' 4 | 5 | export enum DeviceType { 6 | Mobile, 7 | Desktop, 8 | } 9 | 10 | export interface IAppState { 11 | device: DeviceType 12 | sidebar: { 13 | opened: boolean 14 | withoutAnimation: boolean 15 | } 16 | } 17 | 18 | @Module({dynamic: true, store, name: 'app'}) 19 | class App extends VuexModule implements IAppState { 20 | public sidebar = { 21 | opened: getSidebarStatus() !== 'closed', 22 | withoutAnimation: false 23 | } 24 | public device = DeviceType.Desktop 25 | 26 | @Mutation 27 | private TOGGLE_SIDEBAR(withoutAnimation: boolean) { 28 | this.sidebar.opened = !this.sidebar.opened 29 | this.sidebar.withoutAnimation = withoutAnimation 30 | if (this.sidebar.opened) { 31 | setSidebarStatus('opened') 32 | } else { 33 | setSidebarStatus('closed') 34 | } 35 | } 36 | 37 | @Mutation 38 | private CLOSE_SIDEBAR(withoutAnimation: boolean) { 39 | this.sidebar.opened = false 40 | this.sidebar.withoutAnimation = withoutAnimation 41 | setSidebarStatus('closed') 42 | } 43 | 44 | @Mutation 45 | private TOGGLE_DEVICE(device: DeviceType) { 46 | this.device = device 47 | } 48 | 49 | @Action 50 | public ToggleSideBar(withoutAnimation: boolean) { 51 | this.TOGGLE_SIDEBAR(withoutAnimation) 52 | } 53 | 54 | @Action 55 | public CloseSideBar(withoutAnimation: boolean) { 56 | this.CLOSE_SIDEBAR(withoutAnimation) 57 | } 58 | 59 | @Action 60 | public ToggleDevice(device: DeviceType) { 61 | this.TOGGLE_DEVICE(device) 62 | } 63 | } 64 | 65 | export const AppModule = getModule(App) 66 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/service/chain/IDeviceGeoService.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.service.chain; 2 | 3 | import com.example.chain.dto.DeviceGeoDetails; 4 | import com.example.chain.pojo.DeviceGeo; 5 | import com.example.common.exception.BusinessException; 6 | 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | /** 11 | * @author yuelimin 12 | * @version 1.0.0 13 | * @since 11 14 | */ 15 | public interface IDeviceGeoService { 16 | /** 17 | * 查询指定范围内的设备详情 18 | * 19 | * @param longitude 经度 20 | * @param latitude 纬度 21 | * @param distance 范围 22 | * @return 设备详情 23 | * @throws BusinessException 业务异常 24 | */ 25 | List searchDeviceGeoLocationDetails(Double longitude, Double latitude, String distance) throws BusinessException; 26 | 27 | /** 28 | * 搜索指定范围内的设备列表 29 | * 30 | * @param longitude 经度 31 | * @param latitude 纬度 32 | * @param distance 指定范围 33 | * @return 设备列表 34 | * @throws BusinessException 业务异常 35 | */ 36 | List searchDeviceGeoLocation(Double longitude, Double latitude, String distance) throws BusinessException; 37 | 38 | /** 39 | * 保存地理信息到ElasticSearch 40 | * 41 | * @param deviceGeo com.example.chain.pojo.DeviceGeo 地理信息实体类 42 | * @throws BusinessException 业务异常 43 | */ 44 | void createDeviceGeo(DeviceGeo deviceGeo) throws BusinessException; 45 | 46 | /** 47 | * 设备地理信息报文解析 48 | * 49 | * @param topic 设备地理信息主题 50 | * @param payload 设备地理信息报文 51 | * @return com.example.chain.pojo.DeviceGeo 地理信息实体类 52 | * @throws BusinessException 业务异常 53 | */ 54 | DeviceGeo analysis(String topic, Map payload) throws BusinessException; 55 | } 56 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/filter/RequestFilter.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.filter; 2 | 3 | import com.example.common.exception.BusinessException; 4 | import com.example.common.utils.TokenUtil; 5 | import com.mysql.cj.util.StringUtils; 6 | import org.springframework.stereotype.Component; 7 | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; 8 | 9 | import javax.servlet.http.HttpServletRequest; 10 | import javax.servlet.http.HttpServletResponse; 11 | 12 | /** 13 | * @author yuelimin 14 | * @version 1.0.0 15 | * @since 11 16 | */ 17 | @Component 18 | public class RequestFilter extends HandlerInterceptorAdapter { 19 | @Override 20 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 21 | // 发起预检请求直接放行 22 | if ("OPTIONS".equals(request.getMethod().toUpperCase())) { 23 | return true; 24 | } 25 | 26 | if ("/api/login".equals(request.getServletPath().toLowerCase())) { 27 | return true; 28 | } 29 | 30 | if ("/api/device/client".equals(request.getServletPath().toLowerCase())) { 31 | return true; 32 | } 33 | 34 | if (request.getServletPath().toLowerCase().contains("rsa-key")) { 35 | return true; 36 | } 37 | 38 | String authorization = request.getHeader("Authorization"); 39 | if (StringUtils.isNullOrEmpty(authorization)) { 40 | throw new BusinessException("用户未登录"); 41 | } 42 | 43 | try { 44 | Long aLong = TokenUtil.verifyToken(authorization); 45 | } catch (Exception e) { 46 | throw new BusinessException("无效的用户登录"); 47 | } 48 | 49 | return true; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/service/chain/IAlarmService.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.service.chain; 2 | 3 | import com.example.chain.dto.AlarmDTO; 4 | import com.example.chain.query.AlarmQuery; 5 | import com.example.chain.vo.AlarmVO; 6 | import com.example.common.domain.RestPageResult; 7 | import com.example.common.exception.BusinessException; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * @author yuelimin 13 | * @version 1.0.0 14 | * @since 11 15 | */ 16 | public interface IAlarmService { 17 | 18 | /** 19 | * 分页条件查询报警规则 20 | * 21 | * @param alarmQuery com.example.chain.query.AlarmQuery 22 | * @return com.example.common.domain.RestPageResult< List< AlarmDTO>> 23 | * @throws BusinessException 业务异常 24 | */ 25 | RestPageResult> searchAlarm(AlarmQuery alarmQuery) throws BusinessException; 26 | 27 | /** 28 | * 根据id查询告警规则 29 | * 30 | * @param id java.lang.Long 31 | * @return com.example.chain.dto.AlarmDTO 32 | * @throws BusinessException 业务异常 33 | */ 34 | AlarmDTO findAlarmById(Long id) throws BusinessException; 35 | 36 | /** 37 | * 更新告警规则 38 | * 39 | * @param alarmVO com.example.chain.vo.AlarmVO 40 | * @throws BusinessException 业务异常 41 | */ 42 | void updateAlarmById(AlarmVO alarmVO) throws BusinessException; 43 | 44 | /** 45 | * 移除告警规则 46 | * 47 | * @param id java.lang.Long 48 | * @throws BusinessException 业务异常 49 | */ 50 | void removeAlarmById(Long id) throws BusinessException; 51 | 52 | /** 53 | * 创建告警规则 54 | * 55 | * @param alarmVO com.example.chain.vo.AlarmVO 56 | * @throws BusinessException 业务异常 57 | */ 58 | void createAlarm(AlarmVO alarmVO) throws BusinessException; 59 | } 60 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/components/Charts/mixins/resize.ts: -------------------------------------------------------------------------------- 1 | import {ECharts} from 'echarts' 2 | import {Component, Vue} from 'vue-property-decorator' 3 | 4 | @Component({ 5 | name: 'ResizeMixin' 6 | }) 7 | export default class extends Vue { 8 | protected chart!: ECharts | null 9 | private sidebarElm?: Element 10 | 11 | mounted() { 12 | this.initResizeEvent() 13 | this.initSidebarResizeEvent() 14 | } 15 | 16 | beforeDestroy() { 17 | this.destroyResizeEvent() 18 | this.destroySidebarResizeEvent() 19 | } 20 | 21 | activated() { 22 | this.initResizeEvent() 23 | this.initSidebarResizeEvent() 24 | } 25 | 26 | deactivated() { 27 | this.destroyResizeEvent() 28 | this.destroySidebarResizeEvent() 29 | } 30 | 31 | private chartResizeHandler() { 32 | if (this.chart) { 33 | this.chart.resize() 34 | } 35 | } 36 | 37 | private sidebarResizeHandler(e: TransitionEvent) { 38 | if (e.propertyName === 'width') { 39 | this.chartResizeHandler() 40 | } 41 | } 42 | 43 | private initResizeEvent() { 44 | if (this.chartResizeHandler) { 45 | window.addEventListener('resize', this.chartResizeHandler) 46 | } 47 | } 48 | 49 | private destroyResizeEvent() { 50 | if (this.chartResizeHandler) { 51 | window.removeEventListener('resize', this.chartResizeHandler) 52 | } 53 | } 54 | 55 | private initSidebarResizeEvent() { 56 | this.sidebarElm = document.getElementsByClassName('sidebar-container')[0] 57 | if (this.sidebarElm) { 58 | this.sidebarElm.addEventListener('transitionend', this.sidebarResizeHandler as EventListener) 59 | } 60 | } 61 | 62 | private destroySidebarResizeEvent() { 63 | if (this.sidebarElm) { 64 | this.sidebarElm.removeEventListener('transitionend', this.sidebarResizeHandler as EventListener) 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/views/dashboard/components/totleCont.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 33 | 34 | 82 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-monitoring/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | hardware-monitor-web 7 | org.example 8 | 1.0.0 9 | 10 | 4.0.0 11 | 12 | hardware-monitor-monitoring 13 | 14 | 15 | 11 16 | 11 17 | 18 | 19 | ${project.artifactId} 20 | 应用服务监控 21 | 22 | 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-web 27 | 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-starter-actuator 32 | 33 | 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-starter-security 38 | 39 | 40 | 41 | de.codecentric 42 | spring-boot-admin-starter-server 43 | 44 | 45 | 46 | de.codecentric 47 | spring-boot-admin-server-ui 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/controller/admin/UserController.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.controller.admin; 2 | 3 | import com.example.admin.dto.LoginResultDTO; 4 | import com.example.admin.vo.LoginVO; 5 | import com.example.admin.vo.UserVO; 6 | import com.example.backend.service.admin.IUserService; 7 | import com.example.common.domain.RestResponse; 8 | import com.example.common.utils.RSAUtil; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.web.bind.annotation.*; 11 | 12 | /** 13 | * @author yuelimin 14 | * @version 1.0.0 15 | * @since 11 16 | */ 17 | @RestController 18 | @RequestMapping("/api") 19 | public class UserController { 20 | @Autowired 21 | private IUserService iUserService; 22 | 23 | @GetMapping("/users/info") 24 | public RestResponse userInfo() { 25 | return RestResponse.success(); 26 | } 27 | 28 | @DeleteMapping("/users/logout") 29 | public RestResponse userLogout() { 30 | return RestResponse.success(); 31 | } 32 | 33 | @PostMapping("/login") 34 | public LoginResultDTO userLogin(@RequestBody LoginVO loginVO) throws Exception { 35 | return iUserService.userLogin(loginVO); 36 | } 37 | 38 | @PostMapping("/users") 39 | public RestResponse userCreate(@RequestBody UserVO userVO) { 40 | iUserService.userCreate(userVO); 41 | 42 | return RestResponse.success(); 43 | } 44 | 45 | @GetMapping("/rsa-key/{password}") 46 | public RestResponse encodePassword(@PathVariable("password") String password) throws Exception { 47 | return RestResponse.success(RSAUtil.encrypt(password)); 48 | } 49 | 50 | @GetMapping("/rsa-key") 51 | public RestResponse publicKeyRsa() { 52 | return RestResponse.success(RSAUtil.getPublicKeyStr()); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/permission.ts: -------------------------------------------------------------------------------- 1 | import router from './router' 2 | import NProgress from 'nprogress' 3 | import 'nprogress/nprogress.css' 4 | import {Route} from 'vue-router' 5 | import {UserModule} from '@/store/modules/user' 6 | 7 | NProgress.configure({showSpinner: false}) 8 | 9 | const whiteList = ['/login'] 10 | 11 | router.beforeEach(async (to: Route, _: Route, next: any) => { 12 | // Start progress bar 13 | NProgress.start() 14 | 15 | // Determine whether the user has logged in 16 | if (UserModule.token) { 17 | if (to.path === '/login') { 18 | // If is logged in, redirect to the home page 19 | next({path: '/'}) 20 | NProgress.done() 21 | } else { 22 | // Check whether the user has obtained his permission roles 23 | // if (UserModule.roles.length === 0) { 24 | // try { 25 | // // Get user info, including roles 26 | // await UserModule.GetUserInfo() 27 | // // Set the replace: true, so the navigation will not leave a history record 28 | // next({ ...to, replace: true }) 29 | // } catch (err) { 30 | // // Remove token and redirect to login page 31 | // UserModule.ResetToken() 32 | // Message.error(err || 'Has Error') 33 | // next(`/login?redirect=${to.path}`) 34 | // NProgress.done() 35 | // } 36 | // } else { 37 | // next() 38 | // } 39 | next() 40 | } 41 | } else { 42 | // Has no token 43 | if (whiteList.indexOf(to.path) !== -1) { 44 | // In the free login whitelist, go directly 45 | next() 46 | } else { 47 | // Other pages that do not have permission to access are redirected to the login page. 48 | next(`/login?redirect=${to.path}`) 49 | NProgress.done() 50 | } 51 | } 52 | }) 53 | 54 | router.afterEach((to: Route) => { 55 | // Finish progress bar 56 | NProgress.done() 57 | 58 | // set page title 59 | document.title = to.meta.title 60 | }) 61 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/emq/client/EmqClient.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.emq.client; 2 | 3 | import com.example.backend.emq.callback.EmqMessageCallback; 4 | import com.example.common.exception.BusinessException; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.eclipse.paho.client.mqttv3.MqttClient; 7 | import org.eclipse.paho.client.mqttv3.MqttException; 8 | import org.eclipse.paho.client.mqttv3.MqttMessage; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.beans.factory.annotation.Value; 11 | import org.springframework.stereotype.Component; 12 | 13 | import java.util.UUID; 14 | 15 | /** 16 | * @author yuelimin 17 | * @version 1.0.0 18 | * @since 11 19 | */ 20 | @Slf4j 21 | @Component 22 | public class EmqClient { 23 | @Value("${emq.uri}") 24 | private String emqUri; 25 | 26 | @Autowired 27 | private EmqMessageCallback emqMessageCallback; 28 | 29 | private MqttClient mqttClient; 30 | 31 | public void connect() { 32 | try { 33 | mqttClient = new MqttClient(emqUri, "monitor-" + UUID.randomUUID().toString().replace("-", "")); 34 | mqttClient.setCallback(emqMessageCallback); 35 | mqttClient.connect(); 36 | } catch (MqttException e) { 37 | throw new BusinessException("mqtt消息服务器连接失败"); 38 | } 39 | } 40 | 41 | public void publish(String topic, String msg) { 42 | try { 43 | MqttMessage mqttMessage = new MqttMessage(msg.getBytes()); 44 | // 向某主题发送消息 45 | mqttClient.getTopic(topic).publish(mqttMessage); 46 | } catch (MqttException e) { 47 | throw new BusinessException("mqtt消息发送失败"); 48 | } 49 | } 50 | 51 | public void subscribe(String topic) { 52 | try { 53 | mqttClient.subscribe(topic); 54 | } catch (MqttException e) { 55 | throw new BusinessException("mqtt消息订阅失败"); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /hardware-monitor-common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | hardware-monitor 7 | org.example 8 | 1.0.0 9 | 10 | 4.0.0 11 | 12 | hardware-monitor-common 13 | 14 | 15 | 11 16 | 11 17 | 18 | 19 | 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-starter-web 24 | 25 | 26 | 27 | com.baomidou 28 | mybatis-plus-boot-starter 29 | 30 | 31 | mysql 32 | mysql-connector-java 33 | 34 | 35 | com.alibaba 36 | druid-spring-boot-starter 37 | 38 | 39 | 40 | com.google.guava 41 | guava 42 | 43 | 44 | 45 | org.projectlombok 46 | lombok 47 | 48 | 49 | 50 | com.auth0 51 | java-jwt 52 | 4.0.0-beta.0 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/service/chain/IReportService.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.service.chain; 2 | 3 | import com.example.chain.dto.*; 4 | import com.example.common.exception.BusinessException; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @author yuelimin 10 | * @version 1.0.0 11 | * @since 11 12 | */ 13 | public interface IReportService { 14 | 15 | /** 16 | * 根据指标id获取设备列表 17 | * 18 | * @param quotaId 指标id 19 | * @return java.util.List< java.lang.String > 20 | */ 21 | List getDeviceNameByQuotaId(Long quotaId); 22 | 23 | /** 24 | * 获取实时告警日志 25 | * 26 | * @param start 开始时间 27 | * @param end 结束时间 28 | * @return java.util.List< com.example.chain.dto.AlarmLogDTO > 29 | */ 30 | List getRealTimeAlarmLog(Long start, Long end); 31 | 32 | /** 33 | * 获取异常率top10的设备 34 | * 35 | * @param start 开始时间 36 | * @param end 结束时间 37 | * @param type 类型 1-小时 2-天 3-周 38 | * @return java.util.List< com.example.chain.dto.DeviceHeapDTO > 39 | */ 40 | List getDeviceAbnormalTop10(String start, String end, String type); 41 | 42 | /** 43 | * todo 获取异常趋势数据 44 | * 45 | * @param start 开始时间 46 | * @param end 结束时间 47 | * @param type 类型 1-小时 2-天 3-周 48 | * @return java.util.List< com.example.chain.dto.DeviceTrendDTO > 49 | */ 50 | List getDeviceAbnormalTrendList(String start, String end, String type); 51 | 52 | /** 53 | * 实时设备监控 54 | * 55 | * @return com.example.chain.dto.DeviceMonitorDTO 56 | * @throws BusinessException 业务异常 57 | */ 58 | DeviceMonitorDTO getDeviceMonitor() throws BusinessException; 59 | 60 | /** 61 | * 获取状态分布 62 | * 63 | * @return java.util.List< com.example.chain.dto.PieDTO > 64 | * @throws BusinessException 业务异常 65 | */ 66 | List getStatusCollect() throws BusinessException; 67 | } 68 | -------------------------------------------------------------------------------- /hardware-monitor-service/hardware-monitor-service-chain/src/main/java/com/example/chain/dto/QuotaDTO.java: -------------------------------------------------------------------------------- 1 | package com.example.chain.dto; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import lombok.Data; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | *

10 | * 指标信息DTO 11 | *

12 | * 13 | * @author yuelimin 14 | * @version 1.0.0 15 | * @since 11 16 | */ 17 | @Data 18 | @JsonInclude(JsonInclude.Include.NON_NULL) 19 | public class QuotaDTO implements Serializable { 20 | 21 | private static final long serialVersionUID = -6387513644132639728L; 22 | 23 | /** 24 | * 指标ID 25 | */ 26 | private Long id; 27 | 28 | /** 29 | * 指标名称 30 | */ 31 | private String name; 32 | 33 | /** 34 | * 单位 35 | */ 36 | private String unit; 37 | 38 | /** 39 | * 报文主题 40 | */ 41 | private String subject; 42 | 43 | /** 44 | * 指标值字段名称 45 | */ 46 | private String valueKey; 47 | 48 | /** 49 | * 指标值数据类型 50 | */ 51 | private String valueType; 52 | 53 | /** 54 | * 指标值(数值) 55 | */ 56 | private String value; 57 | 58 | /** 59 | * 设备识别码字段(设备Id) 60 | */ 61 | private String snKey; 62 | 63 | /** 64 | * web钩子地址 65 | */ 66 | private String webhook; 67 | 68 | /** 69 | * 参考值 70 | */ 71 | private String referenceValue; 72 | 73 | /** 74 | * 设备Id 75 | */ 76 | private String deviceId; 77 | 78 | // 告警部分 // 79 | 80 | /** 81 | * 是否告警 82 | */ 83 | private String alarm; 84 | 85 | /** 86 | * 告警名称 87 | */ 88 | private String alarmName; 89 | 90 | /** 91 | * 告警级别 92 | */ 93 | private Integer level; 94 | 95 | /** 96 | * 告警web钩子 97 | */ 98 | private String alarmWebhook; 99 | 100 | /** 101 | * 沉默周期 102 | */ 103 | private Integer cycle; 104 | 105 | /** 106 | * 设备标签 107 | */ 108 | private String tag; 109 | } 110 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/styles/font-icon.scss: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'iconfont'; /* project id 1970909 */ 3 | src: url('https://at.alicdn.com/t/font_1970909_pn2czyvmjx.eot'); 4 | src: url('https://at.alicdn.com/t/font_1970909_pn2czyvmjx.eot?#iefix') format('embedded-opentype'), 5 | url('https://at.alicdn.com/t/font_1970909_pn2czyvmjx.woff2') format('woff2'), 6 | url('https://at.alicdn.com/t/font_1970909_pn2czyvmjx.woff') format('woff'), 7 | url('https://at.alicdn.com/t/font_1970909_pn2czyvmjx.ttf') format('truetype'), 8 | url('https://at.alicdn.com/t/font_1970909_pn2czyvmjx.svg#iconfont') format('svg'); 9 | } 10 | 11 | .iconfont { 12 | font-family: "iconfont" !important; 13 | font-size: 16px; 14 | font-style: normal; 15 | -webkit-font-smoothing: antialiased; 16 | -moz-osx-font-smoothing: grayscale; 17 | } 18 | 19 | .icon-rili:before { 20 | content: "\e600"; 21 | } 22 | 23 | .icon-tianjia:before { 24 | content: "\e620"; 25 | } 26 | 27 | .icon-zhibiao:before { 28 | content: "\e66a"; 29 | } 30 | 31 | .icon-sousuo:before { 32 | content: "\e603"; 33 | } 34 | 35 | .icon-shanchu1:before { 36 | content: "\e785"; 37 | } 38 | 39 | .icon-iconset0178:before { 40 | content: "\e64d"; 41 | } 42 | 43 | .icon-dingwei:before { 44 | content: "\e63c"; 45 | } 46 | 47 | .icon-baojingalarm8:before { 48 | content: "\e71d"; 49 | } 50 | 51 | .icon-signal:before { 52 | content: "\e76b"; 53 | } 54 | 55 | .icon-shanchu:before { 56 | content: "\e78d"; 57 | } 58 | 59 | .icon-shebei:before { 60 | content: "\e62f"; 61 | } 62 | 63 | .icon-lixian:before { 64 | content: "\e73e"; 65 | } 66 | 67 | .icon-app_icons--:before { 68 | content: "\e61b"; 69 | } 70 | 71 | .icon-shouye:before { 72 | content: "\e619"; 73 | } 74 | 75 | .icon-shebei1:before { 76 | content: "\e617"; 77 | } 78 | 79 | .icon-bianji:before { 80 | content: "\e7dd"; 81 | } 82 | 83 | .icon-shuju:before { 84 | content: "\e60a"; 85 | } 86 | 87 | .icon-shujux:before { 88 | content: "\e608"; 89 | } 90 | 91 | .icon-shezhi:before { 92 | content: "\e64e"; 93 | } 94 | 95 | .icon-bj:before { 96 | content: "\e606"; 97 | } -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-monitoring/src/main/java/com/example/monitoring/config/SecuritySecureConfig.java: -------------------------------------------------------------------------------- 1 | package com.example.monitoring.config; 2 | 3 | import de.codecentric.boot.admin.server.config.AdminServerProperties; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 6 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 7 | import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; 8 | import org.springframework.security.web.csrf.CookieCsrfTokenRepository; 9 | 10 | /** 11 | * @author yuelimin 12 | * @version 1.0.0 13 | * @since 11 14 | */ 15 | @Configuration 16 | public class SecuritySecureConfig extends WebSecurityConfigurerAdapter { 17 | 18 | private final String adminContextPath; 19 | 20 | public SecuritySecureConfig(AdminServerProperties adminServerProperties) { 21 | this.adminContextPath = adminServerProperties.getContextPath(); 22 | } 23 | 24 | @Override 25 | protected void configure(HttpSecurity http) throws Exception { 26 | SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler(); 27 | successHandler.setTargetUrlParameter("redirectTo"); 28 | 29 | // 跨域设置, SpringBootAdmin客户端通过instances注册, 见InstancesController 30 | http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) 31 | .ignoringAntMatchers(adminContextPath + "/instances"); 32 | 33 | // 静态资源 34 | http.authorizeRequests().antMatchers(adminContextPath + "/assets/**").permitAll(); 35 | // 所有请求必须通过认证 36 | http.authorizeRequests().anyRequest().authenticated(); 37 | 38 | // 整合spring-boot-admin-server-ui 39 | http.formLogin().loginPage("/login").permitAll(); 40 | http.logout().logoutUrl("/logout").logoutSuccessUrl("/login"); 41 | 42 | // 启用basic认证 SpringBootAdmin客户端使用的是basic认证 43 | http.httpBasic(); 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/layout/components/Sidebar/index.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 53 | 54 | 80 | 81 | 92 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/controller/chain/QuotaController.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.controller.chain; 2 | 3 | import com.example.backend.service.chain.IQuotaService; 4 | import com.example.chain.dto.QuotaDTO; 5 | import com.example.chain.query.QuotaQuery; 6 | import com.example.chain.vo.QuotaVO; 7 | import com.example.common.domain.RestPageResult; 8 | import com.example.common.domain.RestResponse; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.web.bind.annotation.*; 11 | 12 | import java.util.List; 13 | 14 | /** 15 | * @author yuelimin 16 | * @version 1.0.0 17 | * @since 11 18 | */ 19 | @RestController 20 | @RequestMapping("/api") 21 | public class QuotaController { 22 | @Autowired 23 | private IQuotaService quotaService; 24 | 25 | @GetMapping("/quota/search/integer") 26 | public RestResponse> findQuotaByInteger() { 27 | return RestResponse.success(quotaService.findQuotaByNumber()); 28 | } 29 | 30 | @PostMapping("/quota/search/integer") 31 | public RestPageResult> searchQuotaInteger(@RequestBody QuotaQuery quotaQuery) { 32 | return quotaService.searchQuotaByNumber(quotaQuery); 33 | } 34 | 35 | @PostMapping("/quota/search") 36 | public RestPageResult> searchQuota(@RequestBody QuotaQuery quotaQuery) { 37 | return quotaService.searchQuota(quotaQuery); 38 | } 39 | 40 | @GetMapping("/quota/{id}") 41 | public QuotaDTO findQuotaById(@PathVariable("id") Long id) { 42 | return quotaService.findQuotaById(id); 43 | } 44 | 45 | @PutMapping("/quota") 46 | public boolean updateQuota(@RequestBody QuotaVO quotaVO) { 47 | return quotaService.updateQuotaById(quotaVO); 48 | } 49 | 50 | @DeleteMapping("/quota/{id}") 51 | public boolean removeQuota(@PathVariable("id") Long id) { 52 | return quotaService.removeQuotaById(id); 53 | } 54 | 55 | @PostMapping("/quota") 56 | public boolean createQuota(@RequestBody QuotaVO quotaVO) { 57 | return quotaService.createQuota(quotaVO); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/service/chain/impl/IGpsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.service.chain.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.example.backend.emq.client.EmqClient; 5 | import com.example.backend.mapper.chain.GpsMapper; 6 | import com.example.backend.service.chain.IGpsService; 7 | import com.example.chain.dto.GpsDTO; 8 | import com.example.chain.pojo.Gps; 9 | import com.example.chain.vo.GpsVO; 10 | import com.example.common.exception.BusinessException; 11 | import lombok.extern.slf4j.Slf4j; 12 | import org.springframework.beans.BeanUtils; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.stereotype.Service; 15 | 16 | import java.util.List; 17 | 18 | /** 19 | * @author yuelimin 20 | * @version 1.0.0 21 | * @since 11 22 | */ 23 | @Slf4j 24 | @Service 25 | public class IGpsServiceImpl implements IGpsService { 26 | @Autowired 27 | private GpsMapper gpsMapper; 28 | @Autowired 29 | private EmqClient emqClient; 30 | 31 | @Override 32 | public GpsDTO findGps() throws BusinessException { 33 | Gps gps = gpsMapper.selectById(1); 34 | if (gps == null) { 35 | return null; 36 | } 37 | 38 | GpsDTO gpsDTO = new GpsDTO(); 39 | 40 | BeanUtils.copyProperties(gps, gpsDTO); 41 | 42 | return gpsDTO; 43 | } 44 | 45 | @Override 46 | public void updateGpsById(GpsVO gpsVO) throws BusinessException { 47 | Gps gps = new Gps(); 48 | 49 | BeanUtils.copyProperties(gpsVO, gps); 50 | 51 | gps.setId(1L); 52 | 53 | gpsMapper.updateById(gps); 54 | 55 | // 更新信息重新订阅主题 56 | emqClient.subscribe(gps.getSubject()); 57 | } 58 | 59 | @Override 60 | public void removeGpsById(Long id) throws BusinessException { 61 | gpsMapper.deleteById(id); 62 | } 63 | 64 | @Override 65 | public void creatGps(GpsVO gpsVO) throws BusinessException { 66 | Gps gps = new Gps(); 67 | 68 | BeanUtils.copyProperties(gpsVO, gps); 69 | 70 | gpsMapper.insert(gps); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/components/Tabs/index.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 44 | 88 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/controller/chain/BoardController.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.controller.chain; 2 | 3 | import com.example.backend.service.chain.IBoardService; 4 | import com.example.chain.dto.BoardDTO; 5 | import com.example.chain.vo.BoardVO; 6 | import com.example.common.domain.RestResponse; 7 | import com.example.common.utils.TokenUtil; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.web.bind.annotation.*; 10 | 11 | import javax.servlet.http.HttpServletRequest; 12 | import java.util.List; 13 | import java.util.Map; 14 | 15 | /** 16 | * @author yuelimin 17 | * @version 1.0.0 18 | * @since 11 19 | */ 20 | @RestController 21 | @RequestMapping("/api") 22 | public class BoardController { 23 | @Autowired 24 | private IBoardService boardService; 25 | 26 | @GetMapping("/board/my") 27 | public List getMyBoard(HttpServletRequest request) { 28 | Long userId = TokenUtil.verifyToken(request.getHeader("Authorization")); 29 | 30 | return boardService.getMyBoard(userId); 31 | } 32 | 33 | @GetMapping("/board/system") 34 | public List getSystemBoard() { 35 | return boardService.getSystemBoard(); 36 | } 37 | 38 | @PutMapping("/board/status") 39 | public RestResponse updateBoardStatus(@RequestBody List> data) { 40 | boardService.updateBoardStatus(data); 41 | 42 | return RestResponse.success(); 43 | } 44 | 45 | @PutMapping("/board") 46 | public RestResponse updateBoard(@RequestBody BoardVO boardVO) { 47 | boardService.updateBoard(boardVO); 48 | 49 | return RestResponse.success(); 50 | } 51 | 52 | @DeleteMapping("/board/{id}") 53 | public RestResponse deleteBoard(@PathVariable("id") Long id) { 54 | boardService.deleteBoardById(id); 55 | 56 | return RestResponse.success(); 57 | } 58 | 59 | @PostMapping("/board") 60 | public RestResponse createBoard(@RequestBody BoardVO boardVO) { 61 | boardService.createBoard(boardVO); 62 | 63 | return RestResponse.success(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/utils/request.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | import { Message, MessageBox } from 'element-ui' 3 | import { UserModule } from '@/store/modules/user' 4 | 5 | const service = axios.create({ 6 | baseURL: process.env.VUE_APP_BASE_API, 7 | timeout: 50000 8 | }) 9 | 10 | // Request interceptors 11 | service.interceptors.request.use( 12 | (config) => { 13 | if (UserModule.token) { 14 | config.headers['Authorization'] = UserModule.token 15 | } 16 | return config 17 | }, 18 | (error) => { 19 | Promise.reject(error) 20 | } 21 | ) 22 | 23 | // Response interceptors 24 | service.interceptors.response.use( 25 | (response) => { 26 | // Some example codes here: 27 | // code == 200: success 28 | // code == 50001: invalid access token 29 | // code == 50002: already login in other place 30 | // code == 50003: access token expired 31 | // code == 50004: invalid user (user not exist) 32 | // code == 50005: username or password is incorrect 33 | // You can change this part for your own usage. 34 | 35 | const res = response.data 36 | if (response.status !== 200) { 37 | Message({ 38 | message: res.msg || 'Error', 39 | type: 'error', 40 | duration: 2 * 1000 41 | }) 42 | if (res.code === 50008 || res.code === 50012 || res.code === 50014) { 43 | MessageBox.confirm( 44 | 'You have been logged out, try to login again.', 45 | 'Log out', 46 | { 47 | confirmButtonText: 'Relogin', 48 | cancelButtonText: 'Cancel', 49 | type: 'warning' 50 | } 51 | ).then(() => { 52 | UserModule.ResetToken() 53 | location.reload() // To prevent bugs from vue-router 54 | }) 55 | } 56 | return Promise.reject(new Error(res.msg || 'Error')) 57 | } else { 58 | return response.data 59 | } 60 | }, 61 | (error) => { 62 | console.log(error.response) 63 | if (error.response.status == 401) { 64 | UserModule.ResetToken() 65 | location.reload() 66 | } 67 | Message({ 68 | message: error.response.data.msg || error.message, 69 | type: 'error', 70 | duration: 2 * 1000 71 | }) 72 | return Promise.reject(error) 73 | } 74 | ) 75 | 76 | export default service 77 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/config/redis/RedisConfig.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.config.redis; 2 | 3 | import com.fasterxml.jackson.annotation.JsonAutoDetect; 4 | import com.fasterxml.jackson.annotation.PropertyAccessor; 5 | import com.fasterxml.jackson.databind.ObjectMapper; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.data.redis.connection.RedisConnectionFactory; 9 | import org.springframework.data.redis.core.RedisTemplate; 10 | import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; 11 | import org.springframework.data.redis.serializer.StringRedisSerializer; 12 | 13 | /** 14 | *

redis序列化配置类(实现方式蛮多的, 不必拘泥这一种)

15 | * 16 | * @author yuelimin 17 | * @version 1.0.0 18 | * @since 11 19 | */ 20 | @Configuration 21 | public class RedisConfig { 22 | @Bean 23 | public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { 24 | RedisTemplate redisTemplate = new RedisTemplate<>(); 25 | redisTemplate.setConnectionFactory(redisConnectionFactory); 26 | 27 | // 使用Jackson2JsonRedisSerialize 替换默认序列化 28 | Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); 29 | 30 | ObjectMapper objectMapper = new ObjectMapper(); 31 | objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); 32 | objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); 33 | 34 | jackson2JsonRedisSerializer.setObjectMapper(objectMapper); 35 | 36 | StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); 37 | // key采用String的序列化方式 38 | redisTemplate.setKeySerializer(stringRedisSerializer); 39 | // hash的key也采用String的序列化方式 40 | redisTemplate.setHashKeySerializer(stringRedisSerializer); 41 | // value序列化方式采用jackson 42 | redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); 43 | // hash的value序列化方式采用jackson 44 | redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer); 45 | redisTemplate.afterPropertiesSet(); 46 | return redisTemplate; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/emq/config/EmqMonitoringConfig.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.emq.config; 2 | 3 | import com.example.backend.emq.client.EmqClient; 4 | import com.example.backend.service.chain.IGpsService; 5 | import com.example.backend.service.chain.IQuotaService; 6 | import com.example.chain.dto.GpsDTO; 7 | import com.example.chain.pojo.Quota; 8 | import com.example.common.exception.BusinessException; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.stereotype.Component; 12 | 13 | import javax.annotation.PostConstruct; 14 | import java.util.List; 15 | 16 | /** 17 | * @author yuelimin 18 | * @version 1.0.0 19 | * @since 11 20 | */ 21 | @Slf4j 22 | @Component 23 | public class EmqMonitoringConfig { 24 | @Autowired 25 | private EmqClient emqClient; 26 | @Autowired 27 | private IQuotaService quotaService; 28 | @Autowired 29 | private IGpsService gpsService; 30 | 31 | @PostConstruct 32 | public void subscribe() { 33 | emqClient.connect(); 34 | 35 | List all = quotaService.findAll(); 36 | if (all.size() == 0) { 37 | log.info("com.example.backend.emq.config.EmqMonitoringConfig#subscribe() 指标信息为空, 主题订阅失败"); 38 | } 39 | 40 | all.forEach(s -> { 41 | try { 42 | emqClient.subscribe("$queue/" + s); 43 | log.info("com.example.backend.emq.config.EmqMonitoringConfig#subscribe() 指标信息主题[{}]订阅成功", s.getSubject()); 44 | 45 | } catch (Exception e) { 46 | throw new BusinessException("指标主题订阅失败 " + s.getSubject()); 47 | } 48 | }); 49 | 50 | GpsDTO gps = gpsService.findGps(); 51 | if (gps == null) { 52 | log.info("com.example.backend.emq.config.EmqMonitoringConfig#subscribe() 地理信息数据为空, 主题订阅失败"); 53 | } 54 | 55 | try { 56 | assert gps != null; 57 | emqClient.subscribe(gps.getSubject()); 58 | log.info("com.example.backend.emq.config.EmqMonitoringConfig#subscribe() 地理信息主题[{}]订阅成功", gps.getSubject()); 59 | } catch (Exception e) { 60 | throw new BusinessException("地理信息主题订阅失败 " + gps.getSubject()); 61 | } 62 | 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /hardware-monitor-common/src/main/java/com/example/common/utils/DateUtil.java: -------------------------------------------------------------------------------- 1 | package com.example.common.utils; 2 | 3 | import java.text.ParseException; 4 | import java.text.SimpleDateFormat; 5 | import java.util.Calendar; 6 | import java.util.Date; 7 | 8 | /** 9 | * @author yuelimin 10 | * @version 1.0.0 11 | * @since 11 12 | */ 13 | public class DateUtil { 14 | /** 15 | * 秒格式化为具体的日期时间 16 | * 17 | * @param second 秒 18 | * @return 日期时间字符串 2019-01-01 00-00-00 19 | */ 20 | public static String secondFormat(Long second) { 21 | Calendar instance = Calendar.getInstance(); 22 | instance.setTimeInMillis(second * 1000); 23 | 24 | return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(instance.getTime()); 25 | } 26 | 27 | /** 28 | * 毫秒值格式化为具体的日期时间 29 | * 30 | * @param millis 毫秒 31 | * @return 日期时间字符串 2019-01-01 00-00-00 32 | */ 33 | public static String millisFormat(Long millis) { 34 | Date date = new Date(millis); 35 | 36 | return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date); 37 | } 38 | 39 | /** 40 | * 将2019-01-01+00:00:00格式化为秒值 41 | * 42 | * @param datetimeFormat 日期时间格式化字符串 2019-01-01+00:00:00 43 | * @return 秒值 44 | */ 45 | public static Long datetimeFormat2second(String datetimeFormat) throws ParseException { 46 | String format = null; 47 | if (datetimeFormat.contains("+")) { 48 | format = datetimeFormat.replace("+", " "); 49 | } else { 50 | format = datetimeFormat; 51 | } 52 | 53 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 54 | long time = simpleDateFormat.parse(format).getTime(); 55 | 56 | return time / 1000; 57 | } 58 | 59 | /** 60 | * 将2019-01-01+00:00:00格式化为毫秒值 61 | * 62 | * @param datetimeFormat 日期时间格式化字符串 2019-01-01+00:00:00 63 | * @return 毫秒值 64 | */ 65 | public static Long datetimeFormat2Millis(String datetimeFormat) throws ParseException { 66 | String format = null; 67 | if (datetimeFormat.contains("+")) { 68 | format = datetimeFormat.replace("+", " "); 69 | } else { 70 | format = datetimeFormat; 71 | } 72 | 73 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 74 | 75 | return simpleDateFormat.parse(format).getTime(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /hardware-monitor-ui/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-typescript-admin-template", 3 | "version": "0.1.0", 4 | "private": true, 5 | "author": "Chong Guo ", 6 | "scripts": { 7 | "serve": "vue-cli-service serve", 8 | "build": "vue-cli-service build", 9 | "lint": "vue-cli-service lint", 10 | "svg": "vsvg -s ./src/icons/svg -t ./src/icons/components --ext ts --es6", 11 | "test:e2e": "vue-cli-service test:e2e", 12 | "test:unit": "vue-cli-service test:unit" 13 | }, 14 | "dependencies": { 15 | "axios": "^0.19.0", 16 | "bcryptjs": "^2.4.3", 17 | "echarts": "^4.8.0", 18 | "element-ui": "^2.12.0", 19 | "js-cookie": "^2.2.1", 20 | "moment": "^2.27.0", 21 | "mqtt": "^4.2.1", 22 | "normalize.css": "^8.0.1", 23 | "nprogress": "^0.2.0", 24 | "path-to-regexp": "^3.0.0", 25 | "register-service-worker": "^1.6.2", 26 | "vue": "^2.6.10", 27 | "vue-baidu-map": "^0.21.22", 28 | "vue-class-component": "^7.1.0", 29 | "vue-property-decorator": "^8.2.2", 30 | "vue-router": "^3.1.2", 31 | "vue-svgicon": "^3.2.6", 32 | "vuex": "^3.1.1", 33 | "vuex-class": "^0.3.2", 34 | "vuex-module-decorators": "^0.10.1" 35 | }, 36 | "devDependencies": { 37 | "@types/echarts": "^4.6.3", 38 | "@types/jest": "^24.0.18", 39 | "@types/js-cookie": "^2.2.2", 40 | "@types/node": "~12.12.23", 41 | "@types/nprogress": "^0.2.0", 42 | "@types/webpack-env": "^1.14.0", 43 | "@vue/cli-plugin-babel": "^3.11.0", 44 | "@vue/cli-plugin-e2e-cypress": "^3.11.0", 45 | "@vue/cli-plugin-eslint": "^3.11.0", 46 | "@vue/cli-plugin-pwa": "^3.11.0", 47 | "@vue/cli-plugin-typescript": "^3.11.0", 48 | "@vue/cli-plugin-unit-jest": "^3.11.0", 49 | "@vue/cli-service": "^3.11.0", 50 | "@vue/eslint-config-standard": "^4.0.0", 51 | "@vue/eslint-config-typescript": "^4.0.0", 52 | "@vue/test-utils": "^1.0.0-beta.29", 53 | "babel-core": "^7.0.0-bridge.0", 54 | "babel-eslint": "^10.0.3", 55 | "eslint": "^6.2.2", 56 | "eslint-plugin-vue": "^5.2.3", 57 | "fibers": "^4.0.1", 58 | "jest": "^24.9.0", 59 | "sass": "^1.22.10", 60 | "sass-loader": "^7.3.1", 61 | "style-resources-loader": "^1.2.1", 62 | "ts-jest": "^24.0.2", 63 | "typescript": "3.6.2", 64 | "vue-cli-plugin-element": "^1.0.1", 65 | "vue-cli-plugin-style-resources-loader": "^0.1.3", 66 | "vue-template-compiler": "^2.6.10", 67 | "webpack": "^4.39.3" 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /hardware-monitor-common/src/main/java/com/example/common/utils/JsonUtil.java: -------------------------------------------------------------------------------- 1 | package com.example.common.utils; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | import com.fasterxml.jackson.databind.DeserializationFeature; 5 | import com.fasterxml.jackson.databind.JsonNode; 6 | import com.fasterxml.jackson.databind.ObjectMapper; 7 | import com.fasterxml.jackson.databind.SerializationFeature; 8 | import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; 9 | 10 | import java.io.IOException; 11 | 12 | /** 13 | * json序列化工具类 14 | * 15 | * @author yuelimin 16 | * @version 1.0.0 17 | * @since 11 18 | */ 19 | public class JsonUtil { 20 | /** 21 | * 反序列化 22 | * 23 | * @param json 24 | * @param clazz 25 | * @param 26 | * @return 27 | * @throws IOException 28 | */ 29 | public static T getByJson(String json, Class clazz) throws IOException { 30 | ObjectMapper mapper = new ObjectMapper(); 31 | // 在反序列化时忽略在 json 中存在但 Java 对象不存在的属性 32 | mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 33 | // 在序列化时日期格式默认为 yyyy-MM-dd'T'HH:mm:ss.SSSZ 34 | mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); 35 | // 反序列化"2020-01-22T11:11:11"字符串为LocalDateTime格式的配置 36 | mapper.registerModule(new JavaTimeModule()); 37 | 38 | return mapper.readValue(json, clazz); 39 | } 40 | 41 | /** 42 | * 从json字符串中根据nodeName获取值 43 | * 44 | * @param nodeName 45 | * @param json 46 | * @return 47 | * @throws IOException 48 | */ 49 | public static String getValueByNodeName(String nodeName, String json) throws IOException { 50 | ObjectMapper objectMapper = new ObjectMapper(); 51 | JsonNode jsonNode = objectMapper.readTree(json); 52 | 53 | return jsonNode.findPath(nodeName).asText(); 54 | } 55 | 56 | /** 57 | * 序列化 58 | * 59 | * @param object 60 | * @return 61 | * @throws JsonProcessingException 62 | */ 63 | public static String serialize(Object object) throws JsonProcessingException { 64 | ObjectMapper mapper = new ObjectMapper(); 65 | // 在序列化时日期格式默认为 yyyy-MM-dd'T'HH:mm:ss.SSSZ 66 | mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); 67 | // 反序列化"2020-01-22T11:11:11"字符串为LocalDateTime格式的配置 68 | mapper.registerModule(new JavaTimeModule()); 69 | 70 | return mapper.writeValueAsString(object); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/controller/chain/ReportController.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.controller.chain; 2 | 3 | import com.example.backend.service.chain.IReportService; 4 | import com.example.chain.dto.*; 5 | import com.example.chain.query.BaseQuery; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.web.bind.annotation.*; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * @author yuelimin 13 | * @version 1.0.0 14 | * @since 11 15 | */ 16 | @RestController 17 | @RequestMapping("/api") 18 | public class ReportController { 19 | @Autowired 20 | private IReportService reportService; 21 | 22 | // todo 数据预览 23 | // @GetMapping("/report/preview") 24 | 25 | // todo 指标看板数据 26 | // @PostMapping("/report/board/data") 27 | 28 | @PostMapping("/report/devices") 29 | public List getDeviceIdsListByQuotaId(@RequestBody BaseQuery baseQuery) { 30 | return reportService.getDeviceNameByQuotaId(baseQuery.getId()); 31 | } 32 | 33 | @GetMapping(value = {"/report/alarm/real-time", "/report/alarm/real-time/{seconds}"}) 34 | public List realTimeAlarmLog(@PathVariable(required = false, value = "seconds") Integer seconds) { 35 | // 结束时间 36 | long end = System.currentTimeMillis() / 1000; 37 | long start = 0; 38 | if (seconds != null) { 39 | // 开始时间 40 | start = end - seconds; 41 | } 42 | 43 | start = end - 5L; 44 | 45 | return reportService.getRealTimeAlarmLog(start, end); 46 | } 47 | 48 | @PostMapping("/report/alarm/top10") 49 | public List getDeviceAlarmTop10(@RequestBody BaseQuery baseQuery) { 50 | return reportService.getDeviceAbnormalTop10(baseQuery.getStartTime(), baseQuery.getEndTime(), baseQuery.getType()); 51 | } 52 | 53 | @PostMapping("/report/alarm/trend") 54 | public List getDeviceAlarmTrend(@RequestBody BaseQuery baseQuery) { 55 | return reportService.getDeviceAbnormalTrendList(baseQuery.getStartTime(), baseQuery.getEndTime(), baseQuery.getType()); 56 | } 57 | 58 | @GetMapping("/report/device/monitor") 59 | public DeviceMonitorDTO getDeviceMonitor() { 60 | return reportService.getDeviceMonitor(); 61 | } 62 | 63 | @GetMapping("/report/device/status-collect") 64 | public List getDeviceStatusCollect() { 65 | return reportService.getStatusCollect(); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /doc/docker-compose/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | elasticsearch: 3 | image: elasticsearch:7.2.0 4 | container_name: elasticsearch 5 | privileged: true 6 | user: root 7 | environment: 8 | - cluster.name=elasticsearch 9 | - discovery.type=single-node 10 | - ES_JAVA_OPTS=-Xms256m -Xmx256m 11 | volumes: 12 | - /root/docker/elasticsearch/plugins:/usr/share/elasticsearch/plugins 13 | - /root/docker/elasticsearch/data:/usr/share/elasticsearch/data 14 | ports: 15 | - 9200:9200 16 | - 9300:9300 17 | 18 | logstash: 19 | image: logstash:7.2.0 20 | container_name: logstash 21 | ports: 22 | - 4560:4560 23 | privileged: true 24 | environment: 25 | - TZ=Asia/Shanghai 26 | volumes: 27 | - /root/docker/logstash/logstash.conf:/usr/share/logstash/pipeline/logstash.conf 28 | depends_on: 29 | - elasticsearch 30 | links: 31 | - elasticsearch:es 32 | 33 | kibana: 34 | image: kibana:7.2.0 35 | container_name: kibana 36 | ports: 37 | - 5601:5601 38 | privileged: true 39 | links: 40 | - elasticsearch:es 41 | depends_on: 42 | - elasticsearch 43 | environment: 44 | - elasticsearch.hosts=http://elasticsearch:9200 45 | 46 | emqx: 47 | image: emqx/emqx:v4.1.0 48 | container_name: emqx 49 | privileged: true 50 | ports: 51 | - 18083:18083 52 | - 8081:8081 53 | - 8083:8083 54 | - 8084:8084 55 | - 1883:1883 56 | volumes: 57 | - /root/docker/emqx/data/emq/emqx.conf:/opt/emqx/etc/emqx.conf 58 | - /root/docker/emqx/data/emq/plugins:/opt/emqx/etc/plugins 59 | 60 | mysql: 61 | image: mysql:8.0.20 62 | command: --default-authentication-plugin=mysql_native_password 63 | restart: always 64 | container_name: mysql 65 | privileged: true 66 | environment: 67 | MYSQL_ROOT_PASSWORD: yueliminvc@outlook.com 68 | TZ: Asia/Shanghai 69 | ports: 70 | - 3306:3306 71 | volumes: 72 | - /root/docker/mysql:/var/lib/mysql 73 | - /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime 74 | network_mode: "host" 75 | 76 | redis: 77 | image: redis:6.0.5 78 | container_name: redis 79 | privileged: true 80 | expose: 81 | - 6379 82 | volumes: 83 | - /root/docker/redis/data:/data 84 | - /root/docker/redis/conf/redis.conf:/etc/redis/redis.conf 85 | ports: 86 | - 6379:6379 87 | command: redis-server /etc/redis/redis.conf --appendonly yes --requirepass "yueliminvc@outlook.com" 88 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/handler/GlobalExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.handler; 2 | 3 | import com.example.common.domain.RestResponse; 4 | import com.example.common.exception.BusinessException; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.http.HttpStatus; 7 | import org.springframework.web.HttpMediaTypeNotSupportedException; 8 | import org.springframework.web.HttpRequestMethodNotSupportedException; 9 | import org.springframework.web.bind.MethodArgumentNotValidException; 10 | import org.springframework.web.bind.annotation.ExceptionHandler; 11 | import org.springframework.web.bind.annotation.ResponseStatus; 12 | import org.springframework.web.bind.annotation.RestControllerAdvice; 13 | 14 | /** 15 | * @author yuelimin 16 | * @version 1.0.0 17 | * @since 11 18 | */ 19 | @Slf4j 20 | @RestControllerAdvice 21 | public class GlobalExceptionHandler { 22 | 23 | @ResponseStatus(HttpStatus.BAD_REQUEST) 24 | @ExceptionHandler(MethodArgumentNotValidException.class) 25 | public RestResponse handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { 26 | log.error(e.getMessage(), e); 27 | 28 | return RestResponse.fail(e.getBindingResult().getAllErrors().get(0).getDefaultMessage()); 29 | } 30 | 31 | @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED) 32 | @ExceptionHandler(HttpRequestMethodNotSupportedException.class) 33 | public RestResponse handlerHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) { 34 | log.error(e.getMessage(), e); 35 | 36 | return RestResponse.fail(HttpStatus.METHOD_NOT_ALLOWED.value(), "请求方法不支持, 呜呜呜"); 37 | } 38 | 39 | @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE) 40 | @ExceptionHandler(HttpMediaTypeNotSupportedException.class) 41 | public RestResponse handlerHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e) { 42 | log.error(e.getMessage(), e); 43 | 44 | return RestResponse.fail(HttpStatus.UNSUPPORTED_MEDIA_TYPE.value(), "不支持的媒体类型, 呜呜呜"); 45 | } 46 | 47 | @ResponseStatus(HttpStatus.BAD_REQUEST) 48 | @ExceptionHandler(BusinessException.class) 49 | public RestResponse handleExcepting(BusinessException e) { 50 | log.error(e.getMessage(), e); 51 | 52 | return RestResponse.fail(HttpStatus.BAD_REQUEST.value(), e.getMessage()); 53 | } 54 | 55 | @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) 56 | @ExceptionHandler(Exception.class) 57 | public RestResponse handleExcepting(Exception e) { 58 | log.error(e.getMessage()); 59 | return RestResponse.fail(HttpStatus.INTERNAL_SERVER_ERROR.value(), "服务器内部错误"); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /hardware-monitor-common/src/main/java/com/example/common/utils/TokenUtil.java: -------------------------------------------------------------------------------- 1 | package com.example.common.utils; 2 | 3 | import com.auth0.jwt.JWT; 4 | import com.auth0.jwt.JWTVerifier; 5 | import com.auth0.jwt.algorithms.Algorithm; 6 | import com.auth0.jwt.exceptions.TokenExpiredException; 7 | import com.auth0.jwt.interfaces.DecodedJWT; 8 | import com.example.common.exception.BusinessException; 9 | 10 | import java.util.Calendar; 11 | import java.util.Date; 12 | 13 | /** 14 | * @author yuelimin 15 | * @version 1.0.0 16 | * @since 11 17 | */ 18 | public class TokenUtil { 19 | 20 | /** 21 | * 签发人 22 | */ 23 | private static final String ISSUER = "admin"; 24 | 25 | /** 26 | * 创建JWT 27 | * 28 | * @param userId 29 | * @return 30 | * @throws Exception 31 | */ 32 | public static String generateToken(Long userId) throws Exception { 33 | Algorithm algorithm = Algorithm.RSA256(RSAUtil.getPublicKey(), RSAUtil.getPrivateKey()); 34 | 35 | Calendar calendar = Calendar.getInstance(); 36 | calendar.setTime(new Date()); 37 | // 48小时token失效 38 | calendar.add(Calendar.HOUR, 48); 39 | 40 | return JWT.create() 41 | .withKeyId(String.valueOf(userId)) 42 | .withIssuer(ISSUER) 43 | .withExpiresAt(calendar.getTime()) 44 | .sign(algorithm); 45 | } 46 | 47 | /** 48 | * 校验token 49 | * 50 | * @param token 51 | * @return 52 | */ 53 | public static Long verifyToken(String token) { 54 | try { 55 | Algorithm algorithm = Algorithm.RSA256(RSAUtil.getPublicKey(), RSAUtil.getPrivateKey()); 56 | JWTVerifier verifier = JWT.require(algorithm).build(); 57 | DecodedJWT jwt = verifier.verify(token); 58 | 59 | String userId = jwt.getKeyId(); 60 | return Long.valueOf(userId); 61 | } catch (TokenExpiredException e) { 62 | throw new BusinessException(401, "token过期"); 63 | } catch (Exception e) { 64 | throw new BusinessException(401, "非法的用户token"); 65 | } 66 | } 67 | 68 | /** 69 | * 刷新token 70 | * 71 | * @param userId 72 | * @return 73 | * @throws Exception 74 | */ 75 | public static String generateRefreshToken(Long userId) throws Exception { 76 | Algorithm algorithm = Algorithm.RSA256(RSAUtil.getPublicKey(), RSAUtil.getPrivateKey()); 77 | 78 | Calendar calendar = Calendar.getInstance(); 79 | calendar.setTime(new Date()); 80 | calendar.add(Calendar.DAY_OF_MONTH, 7); 81 | 82 | return JWT.create() 83 | .withKeyId(String.valueOf(userId)) 84 | .withIssuer(ISSUER) 85 | .withExpiresAt(calendar.getTime()) 86 | .sign(algorithm); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /hardware-monitor-ui/tests/unit/components/Breadcrumb.spec.ts: -------------------------------------------------------------------------------- 1 | import {createLocalVue, mount} from '@vue/test-utils' 2 | import VueRouter from 'vue-router' 3 | import ElementUI from 'element-ui' 4 | import Breadcrumb from '@/components/Breadcrumb/index.vue' 5 | 6 | const localVue = createLocalVue() 7 | localVue.use(VueRouter) 8 | localVue.use(ElementUI) 9 | 10 | const routes = [ 11 | { 12 | path: '/', 13 | children: [{ 14 | path: 'dashboard' 15 | }] 16 | }, 17 | { 18 | path: '/menu', 19 | children: [{ 20 | path: 'menu1', 21 | meta: {title: 'menu1'}, 22 | children: [{ 23 | path: 'menu1-1', 24 | meta: {title: 'menu1-1'} 25 | }, 26 | { 27 | path: 'menu1-2', 28 | redirect: 'noredirect', 29 | meta: {title: 'menu1-2'}, 30 | children: [{ 31 | path: 'menu1-2-1', 32 | meta: {title: 'menu1-2-1'} 33 | }, 34 | { 35 | path: 'menu1-2-2' 36 | }] 37 | }] 38 | }] 39 | }] 40 | 41 | const router = new VueRouter({ 42 | routes 43 | }) 44 | 45 | describe('Breadcrumb.vue', () => { 46 | const wrapper = mount(Breadcrumb, { 47 | localVue, 48 | router 49 | }) 50 | 51 | it('dashboard', () => { 52 | router.push('/dashboard') 53 | const len = wrapper.findAll('.el-breadcrumb__inner').length 54 | expect(len).toBe(1) 55 | }) 56 | 57 | it('normal route', () => { 58 | router.push('/menu/menu1') 59 | const len = wrapper.findAll('.el-breadcrumb__inner').length 60 | expect(len).toBe(2) 61 | }) 62 | 63 | it('nested route', () => { 64 | router.push('/menu/menu1/menu1-2/menu1-2-1') 65 | const len = wrapper.findAll('.el-breadcrumb__inner').length 66 | expect(len).toBe(4) 67 | }) 68 | 69 | it('no meta.title', () => { 70 | router.push('/menu/menu1/menu1-2/menu1-2-2') 71 | const len = wrapper.findAll('.el-breadcrumb__inner').length 72 | expect(len).toBe(3) 73 | }) 74 | 75 | it('click link', () => { 76 | router.push('/menu/menu1/menu1-2/menu1-2-2') 77 | const breadcrumbArray = wrapper.findAll('.el-breadcrumb__inner') 78 | const second = breadcrumbArray.at(1) 79 | const href = second.find('a').text() 80 | expect(href).toBe('menu1') 81 | }) 82 | 83 | it('noredirect', () => { 84 | router.push('/menu/menu1/menu1-2/menu1-2-1') 85 | const breadcrumbArray = wrapper.findAll('.el-breadcrumb__inner') 86 | const redirectBreadcrumb = breadcrumbArray.at(2) 87 | expect(redirectBreadcrumb.contains('a')).toBe(false) 88 | }) 89 | 90 | it('last breadcrumb', () => { 91 | router.push('/menu/menu1/menu1-2/menu1-2-1') 92 | const breadcrumbArray = wrapper.findAll('.el-breadcrumb__inner') 93 | const redirectBreadcrumb = breadcrumbArray.at(3) 94 | expect(redirectBreadcrumb.contains('a')).toBe(false) 95 | }) 96 | }) 97 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/api/dashboard.ts: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | 4 | // 获取指标 5 | export const quotaNumberQuota = () => 6 | request({ 7 | url: '/api/quota/search/integer', 8 | method: 'get', 9 | }) 10 | 11 | 12 | // 获取系统面板 13 | export const boardSystemBoard = () => 14 | request({ 15 | url: '/api/board/system', 16 | method: 'get', 17 | }) 18 | // 更改系统面板 19 | export const boardStatus = (params: any) => 20 | request({ 21 | url: '/api/board/status', 22 | method: 'put', 23 | data: params 24 | }) 25 | // 添加面板 26 | export const addBoard = (params: any) => 27 | request({ 28 | url: `/api/board`, 29 | method: 'post', 30 | data: params 31 | }) 32 | // 删除面板 33 | export const delBoard = (id: number) => 34 | request({ 35 | url: `/api/board/${id}`, 36 | method: 'delete', 37 | }) 38 | // 获取非系统(私有)面板 39 | export const getUnSystemPanel = () => 40 | request({ 41 | url: '/api/board/my', 42 | method: 'get', 43 | }) 44 | 45 | 46 | // 监控设备数 - 设备数和报警设备数量 47 | export const monitor = () => 48 | request({ 49 | url: '/api/report/device/monitor', 50 | method: 'get', 51 | }) 52 | // 设备状态分布 - 首页环形图数据 53 | export const statusCollect = (params: any) => 54 | request({ 55 | url: '/api/report/device/status-collect', 56 | method: 'get', 57 | params 58 | }) 59 | // 地图 - 根据经纬度获取设备信息 60 | export const deviceList = (params: any) => 61 | request({ 62 | url: `/api/gps/device-details/${params.lat}/${params.lon}/${params.distance}`, 63 | method: 'get' 64 | }) 65 | 66 | 67 | // 报表-今日异常设备 68 | // 异常趋势图 69 | export const trendDatas = (params: any) => 70 | request({ 71 | url: '/api/report/alarm/trend', 72 | method: 'post', 73 | data: params 74 | }) 75 | // 异常数量Top10 76 | export const top10Alarm = (params: any) => 77 | request({ 78 | url: '/api/report/alarm/top10', 79 | method: 'post', 80 | data: params 81 | }) 82 | // 报表-获取实时告警日志 83 | export const realTimeAlarmLog = () => 84 | request({ 85 | url: '/api/report/alarm/real-time', 86 | method: 'get' 87 | }) 88 | 89 | 90 | 91 | // 报表-自定义面板 92 | // 用列表中的对应ID获取信息 93 | export const boardData = (params: any) => 94 | request({ 95 | url: '/api/report/board-data', 96 | method: 'post', 97 | data: params 98 | }) 99 | // 通过指标查询设备列表 100 | export const quotaDevices = (params: any) => 101 | request({ 102 | url: `/api/report/devices`, 103 | method: 'post', 104 | data: params 105 | }) 106 | // 预览接口 107 | export const preview = (data: any) => 108 | request({ 109 | url: '/api/report/preview', 110 | method: 'post', 111 | data: data 112 | }) 113 | // 添加看板 114 | // export const board = (data: any) => 115 | // request({ 116 | // url: '/api/board', 117 | // method: 'post', 118 | // data 119 | // }) 120 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/store/modules/user.ts: -------------------------------------------------------------------------------- 1 | import {Action, getModule, Module, Mutation, VuexModule} from 'vuex-module-decorators' 2 | import {getUserInfo, login} from '@/api/users' 3 | import {getToken, removeToken, setToken} from '@/utils/cookies' 4 | import store from '@/store' 5 | 6 | export interface IUserState { 7 | token: string 8 | name: string 9 | avatar: string 10 | introduction: string 11 | roles: string[] 12 | } 13 | 14 | @Module({dynamic: true, store, name: 'user'}) 15 | class User extends VuexModule implements IUserState { 16 | public token = getToken() || '' 17 | public name = '' 18 | public avatar = '' 19 | public introduction = '' 20 | public roles: string[] = [] 21 | 22 | @Mutation 23 | private SET_TOKEN(token: string) { 24 | this.token = token 25 | } 26 | 27 | @Mutation 28 | private SET_NAME(name: string) { 29 | this.name = name 30 | } 31 | 32 | @Mutation 33 | private SET_AVATAR(avatar: string) { 34 | this.avatar = avatar 35 | } 36 | 37 | @Mutation 38 | private SET_INTRODUCTION(introduction: string) { 39 | this.introduction = introduction 40 | } 41 | 42 | @Mutation 43 | private SET_ROLES(roles: string[]) { 44 | this.roles = roles 45 | } 46 | 47 | @Action 48 | public async Login(userInfo: { username: string, password: string }) { 49 | let {username, password} = userInfo 50 | username = username.trim() 51 | const data: any = await login({ 52 | loginName: username, 53 | password: password, 54 | }) 55 | if (data.token) { 56 | localStorage.setItem('adminId', data.adminId); 57 | setToken(data.token) 58 | this.SET_TOKEN(data.token) 59 | return {success: true} 60 | } else { 61 | return {success: false} 62 | } 63 | } 64 | 65 | @Action 66 | public ResetToken() { 67 | removeToken() 68 | this.SET_TOKEN('') 69 | this.SET_ROLES([]) 70 | } 71 | 72 | @Action 73 | public async GetUserInfo() { 74 | // return; 75 | if (this.token === '') { 76 | throw Error('GetUserInfo: token is undefined!') 77 | } 78 | const {data} = await getUserInfo({ /* Your params here */}) 79 | if (!data) { 80 | throw Error('Verification failed, please Login again.') 81 | } 82 | const {roles, name, avatar, introduction} = data.user 83 | // roles must be a non-empty array 84 | if (!roles || roles.length <= 0) { 85 | throw Error('GetUserInfo: roles must be a non-null array!') 86 | } 87 | this.SET_ROLES(roles) 88 | this.SET_NAME(name) 89 | this.SET_AVATAR(avatar) 90 | this.SET_INTRODUCTION(introduction) 91 | } 92 | 93 | @Action 94 | public async LogOut() { 95 | if (this.token === '') { 96 | throw Error('LogOut: token is undefined!') 97 | } 98 | // await logout() 99 | removeToken() 100 | this.SET_TOKEN('') 101 | this.SET_ROLES([]) 102 | } 103 | } 104 | 105 | export const UserModule = getModule(User) 106 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/layout/index.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 49 | 50 | 133 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/java/com/example/backend/service/chain/IQuotaService.java: -------------------------------------------------------------------------------- 1 | package com.example.backend.service.chain; 2 | 3 | import com.example.chain.dto.QuotaDTO; 4 | import com.example.chain.pojo.Quota; 5 | import com.example.chain.query.QuotaQuery; 6 | import com.example.chain.vo.QuotaVO; 7 | import com.example.common.domain.RestPageResult; 8 | import com.example.common.exception.BusinessException; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * @author yuelimin 14 | * @version 1.0.0 15 | * @since 11 16 | */ 17 | public interface IQuotaService { 18 | /** 19 | * 根据设备id查询设备对应的指标列表 20 | * 21 | * @param deviceId 设备id 22 | * @return 指标列表 23 | * @throws BusinessException 业务异常 24 | */ 25 | List findQuotaListByDeviceId(String deviceId) throws BusinessException; 26 | 27 | /** 28 | * 获取全部数据类型指标 29 | * 30 | * @return java.util.List< QuotaDTO> 31 | * @throws BusinessException 业务异常 32 | */ 33 | List findQuotaByNumber() throws BusinessException; 34 | 35 | /** 36 | * 分页查询数据类型指标 37 | * 38 | * @param quotaQuery com.example.chain.query.QuotaQuery 39 | * @return com.example.common.domain.RestPageResult< List< QuotaDTO>> 40 | * @throws BusinessException 业务异常 41 | */ 42 | RestPageResult> searchQuotaByNumber(QuotaQuery quotaQuery) throws BusinessException; 43 | 44 | /** 45 | * 分页查询 46 | * 47 | * @param quotaQuery com.example.chain.query.QuotaQuery 48 | * @return com.example.common.domain.RestPageResult< List< QuotaDTO>> 49 | * @throws BusinessException 业务异常 50 | */ 51 | RestPageResult> searchQuota(QuotaQuery quotaQuery) throws BusinessException; 52 | 53 | /** 54 | * 更新指标 55 | * 56 | * @param quotaVO com.example.chain.vo.QuotaVO 57 | * @return java.lang.boolean 更新指标是否成功 true成功 false失败 58 | * @throws BusinessException 业务异常 59 | */ 60 | boolean updateQuotaById(QuotaVO quotaVO) throws BusinessException; 61 | 62 | /** 63 | * 移除指标 64 | * 65 | * @param id java.lang.Long 指标id 66 | * @return java.lang.boolean 移除指标是否成功 true成功 false失败 67 | * @throws BusinessException 68 | */ 69 | boolean removeQuotaById(Long id) throws BusinessException; 70 | 71 | /** 72 | * 根据id查询指标 73 | * 74 | * @param id java.lang.Long 指标id 75 | * @return com.example.chain.dto.QuotaDTO 76 | * @throws BusinessException 业务异常 77 | */ 78 | QuotaDTO findQuotaById(Long id) throws BusinessException; 79 | 80 | /** 81 | * 获取全部指标信息 82 | * 83 | * @return java.util.List 84 | * @throws BusinessException 业务异常 85 | */ 86 | List findAll() throws BusinessException; 87 | 88 | /** 89 | * 新增指标 90 | * 91 | * @param quotaVO com.example.chain.vo.QuotaVO 92 | * @return java.lang.boolean 是否添加成功 93 | * @throws BusinessException 业务异常 94 | */ 95 | boolean createQuota(QuotaVO quotaVO) throws BusinessException; 96 | } 97 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | hardware-monitor-web 7 | org.example 8 | 1.0.0 9 | 10 | 4.0.0 11 | 12 | hardware-monitor-backend 13 | 14 | 15 | 11 16 | 11 17 | 18 | 19 | ${project.artifactId} 20 | 冷链监控后台服务 21 | 22 | 23 | 24 | org.example 25 | hardware-monitor-service-admin 26 | 1.0.0 27 | 28 | 29 | org.example 30 | hardware-monitor-service-chain 31 | 1.0.0 32 | 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-starter-actuator 37 | 38 | 39 | 40 | de.codecentric 41 | spring-boot-admin-starter-client 42 | 43 | 44 | 45 | org.springframework.boot 46 | spring-boot-starter-test 47 | 48 | 49 | junit 50 | junit 51 | test 52 | 53 | 54 | 55 | org.elasticsearch.client 56 | elasticsearch-rest-high-level-client 57 | 58 | 59 | org.elasticsearch 60 | elasticsearch 61 | 62 | 63 | org.elasticsearch.client 64 | elasticsearch-rest-client 65 | 66 | 67 | 68 | org.eclipse.paho 69 | org.eclipse.paho.client.mqttv3 70 | 71 | 72 | 73 | org.springframework.boot 74 | spring-boot-starter-data-redis 75 | 76 | 77 | org.apache.commons 78 | commons-pool2 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /hardware-monitor-ui/src/components/Breadcrumb/index.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 88 | 89 | 107 | -------------------------------------------------------------------------------- /hardware-monitor-web/hardware-monitor-backend/src/main/resources/application-dev.yml: -------------------------------------------------------------------------------- 1 | config: 2 | mysql: 3 | username: root 4 | password: yueliminvc@outlook.com 5 | ip: 127.0.0.1 6 | port: 3306 7 | db: monitor 8 | redis: 9 | ip: 127.0.0.1 10 | port: 6379 11 | password: yueliminvc@outlook.com 12 | database: 0 13 | 14 | spring: 15 | boot: 16 | admin: 17 | client: 18 | username: yueliminvc@outlook.com 19 | password: yueliminvc@outlook.com 20 | url: http://127.0.0.1:57000 21 | datasource: 22 | type: com.alibaba.druid.pool.DruidDataSource 23 | driver-class-name: com.mysql.cj.jdbc.Driver 24 | url: jdbc:mysql://${config.mysql.ip}:${config.mysql.port}/${config.mysql.db}?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false 25 | username: ${config.mysql.username} 26 | password: ${config.mysql.password} 27 | druid: 28 | initial-size: 5 29 | min-idle: 5 30 | max-active: 20 31 | max-wait: 60000 32 | time-between-eviction-runs-millis: 60000 33 | min-evictable-idle-time-millis: 300000 34 | validation-query: SELECT 1 FROM DUAL 35 | test-while-idle: true 36 | test-on-borrow: true 37 | test-on-return: false 38 | pool-prepared-statements: true 39 | max-pool-prepared-statement-per-connection-size: 20 40 | filter: 41 | stat: 42 | slow-sql-millis: 1 43 | log-slow-sql: true 44 | filters: config,stat,wall,log4j2 45 | web-stat-filter: 46 | enabled: true 47 | url-pattern: /* 48 | exclusions: "*.js,*.gif,*.jpg,*.css,*.ioc,/druid/*" 49 | session-stat-enable: false 50 | session-stat-max-count: 1000 51 | principal-cookie-name: admin 52 | principal-session-name: admin 53 | profile-enable: true 54 | stat-view-servlet: 55 | enabled: true 56 | url-pattern: /druid/* 57 | # 白名单 58 | allow: 127.0.0.1 59 | # 黑名单 60 | deny: 192.168.158.110 61 | reset-enable: false 62 | login-password: admin 63 | login-username: admin 64 | aop-patterns: com.example.*.service 65 | elasticsearch: 66 | rest: 67 | uris: http://127.0.0.1:9200 68 | cache: 69 | type: REDIS 70 | redis: 71 | host: ${config.redis.ip} 72 | password: ${config.redis.password} 73 | port: ${config.redis.port} 74 | database: ${config.redis.database} 75 | timeout: 3000ms 76 | lettuce: 77 | pool: 78 | max-idle: 8 79 | min-idle: 0 80 | max-active: 8 81 | max-wait: 3000ms 82 | shutdown-timeout: 3000ms 83 | 84 | mybatis-plus: 85 | configuration: 86 | cache-enabled: false 87 | map-underscore-to-camel-case: true 88 | global-config: 89 | banner: false 90 | db-config: 91 | id-type: id_worker 92 | mapper-locations: classpath:/mapper/*/*.xml 93 | 94 | management: 95 | endpoints: 96 | web: 97 | base-path: /actuator 98 | exposure: 99 | include: '*' 100 | endpoint: 101 | shutdown: 102 | enabled: true 103 | health: 104 | show-details: always 105 | 106 | emq: 107 | uri: tcp://127.0.0.1:1883 --------------------------------------------------------------------------------