From dea97793496d7ae11fdf88ac16caf9ac34e02e06 Mon Sep 17 00:00:00 2001 From: lcr <977192391@qq.com> Date: Wed, 12 Jun 2024 17:23:51 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=8D=A2=E9=A1=B9=E7=9B=AE=E6=A1=86?= =?UTF-8?q?=E6=9E=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 45 +- LICENSE | 211 +- README.md | 128 +- bin/clean.bat | 12 + bin/package.bat | 12 + bin/run.bat | 14 + custom-ui/.editorconfig | 22 + custom-ui/.env.development | 11 + custom-ui/.env.production | 8 + custom-ui/.env.staging | 10 + custom-ui/.eslintignore | 10 + custom-ui/.eslintrc.js | 199 + custom-ui/README.md | 30 + custom-ui/babel.config.js | 13 + custom-ui/bin/build.bat | 12 + custom-ui/bin/package.bat | 12 + custom-ui/bin/run-web.bat | 12 + custom-ui/build/index.js | 35 + custom-ui/package-lock.json | 15631 ++++++++++++++++ custom-ui/package.json | 90 + custom-ui/public/favicon.ico | Bin 0 -> 5663 bytes custom-ui/public/html/ie.html | 46 + custom-ui/public/index.html | 208 + custom-ui/public/robots.txt | 2 + custom-ui/src/App.vue | 28 + custom-ui/src/api/business/survey.js | 53 + custom-ui/src/api/business/template.js | 54 + custom-ui/src/api/business/templateProp.js | 45 + .../src/api/business/templatePropValue.js | 61 + custom-ui/src/api/login.js | 70 + custom-ui/src/api/menu.js | 9 + custom-ui/src/api/monitor/cache.js | 57 + custom-ui/src/api/monitor/job.js | 71 + custom-ui/src/api/monitor/jobLog.js | 26 + custom-ui/src/api/monitor/logininfor.js | 34 + custom-ui/src/api/monitor/online.js | 18 + custom-ui/src/api/monitor/operlog.js | 26 + custom-ui/src/api/monitor/server.js | 9 + custom-ui/src/api/system/config.js | 60 + custom-ui/src/api/system/dept.js | 52 + custom-ui/src/api/system/dict/data.js | 52 + custom-ui/src/api/system/dict/type.js | 60 + custom-ui/src/api/system/menu.js | 60 + custom-ui/src/api/system/notice.js | 44 + custom-ui/src/api/system/post.js | 44 + custom-ui/src/api/system/role.js | 119 + custom-ui/src/api/system/user.js | 135 + custom-ui/src/api/tool/gen.js | 76 + custom-ui/src/assets/401_images/401.gif | Bin 0 -> 164227 bytes custom-ui/src/assets/404_images/404.png | Bin 0 -> 98071 bytes custom-ui/src/assets/404_images/404_cloud.png | Bin 0 -> 4766 bytes custom-ui/src/assets/icons/index.js | 9 + custom-ui/src/assets/icons/svg/404.svg | 1 + custom-ui/src/assets/icons/svg/bug.svg | 1 + custom-ui/src/assets/icons/svg/build.svg | 1 + custom-ui/src/assets/icons/svg/button.svg | 1 + custom-ui/src/assets/icons/svg/cascader.svg | 1 + custom-ui/src/assets/icons/svg/chart.svg | 1 + custom-ui/src/assets/icons/svg/checkbox.svg | 1 + custom-ui/src/assets/icons/svg/clipboard.svg | 1 + custom-ui/src/assets/icons/svg/code.svg | 1 + custom-ui/src/assets/icons/svg/color.svg | 1 + custom-ui/src/assets/icons/svg/component.svg | 1 + custom-ui/src/assets/icons/svg/dashboard.svg | 1 + custom-ui/src/assets/icons/svg/date-range.svg | 1 + custom-ui/src/assets/icons/svg/date.svg | 1 + custom-ui/src/assets/icons/svg/dict.svg | 1 + .../src/assets/icons/svg/documentation.svg | 1 + custom-ui/src/assets/icons/svg/download.svg | 1 + custom-ui/src/assets/icons/svg/drag.svg | 1 + custom-ui/src/assets/icons/svg/druid.svg | 1 + custom-ui/src/assets/icons/svg/edit.svg | 1 + custom-ui/src/assets/icons/svg/education.svg | 1 + custom-ui/src/assets/icons/svg/email.svg | 1 + custom-ui/src/assets/icons/svg/example.svg | 1 + custom-ui/src/assets/icons/svg/excel.svg | 1 + .../src/assets/icons/svg/exit-fullscreen.svg | 1 + custom-ui/src/assets/icons/svg/eye-open.svg | 1 + custom-ui/src/assets/icons/svg/eye.svg | 1 + custom-ui/src/assets/icons/svg/form.svg | 1 + custom-ui/src/assets/icons/svg/fullscreen.svg | 1 + custom-ui/src/assets/icons/svg/github.svg | 1 + custom-ui/src/assets/icons/svg/guide.svg | 1 + custom-ui/src/assets/icons/svg/icon.svg | 1 + custom-ui/src/assets/icons/svg/input.svg | 1 + .../src/assets/icons/svg/international.svg | 1 + custom-ui/src/assets/icons/svg/job.svg | 1 + custom-ui/src/assets/icons/svg/language.svg | 1 + custom-ui/src/assets/icons/svg/link.svg | 1 + custom-ui/src/assets/icons/svg/list.svg | 1 + custom-ui/src/assets/icons/svg/lock.svg | 1 + custom-ui/src/assets/icons/svg/log.svg | 1 + custom-ui/src/assets/icons/svg/logininfor.svg | 1 + custom-ui/src/assets/icons/svg/message.svg | 1 + custom-ui/src/assets/icons/svg/money.svg | 1 + custom-ui/src/assets/icons/svg/monitor.svg | 2 + custom-ui/src/assets/icons/svg/nested.svg | 1 + custom-ui/src/assets/icons/svg/number.svg | 1 + custom-ui/src/assets/icons/svg/online.svg | 1 + custom-ui/src/assets/icons/svg/password.svg | 1 + custom-ui/src/assets/icons/svg/pdf.svg | 1 + custom-ui/src/assets/icons/svg/people.svg | 1 + custom-ui/src/assets/icons/svg/peoples.svg | 1 + custom-ui/src/assets/icons/svg/phone.svg | 1 + custom-ui/src/assets/icons/svg/post.svg | 1 + custom-ui/src/assets/icons/svg/qq.svg | 1 + custom-ui/src/assets/icons/svg/question.svg | 1 + custom-ui/src/assets/icons/svg/radio.svg | 1 + custom-ui/src/assets/icons/svg/rate.svg | 1 + custom-ui/src/assets/icons/svg/redis-list.svg | 2 + custom-ui/src/assets/icons/svg/redis.svg | 1 + custom-ui/src/assets/icons/svg/row.svg | 1 + custom-ui/src/assets/icons/svg/search.svg | 1 + custom-ui/src/assets/icons/svg/select.svg | 1 + custom-ui/src/assets/icons/svg/server.svg | 1 + custom-ui/src/assets/icons/svg/shopping.svg | 1 + custom-ui/src/assets/icons/svg/size.svg | 1 + custom-ui/src/assets/icons/svg/skill.svg | 1 + custom-ui/src/assets/icons/svg/slider.svg | 1 + custom-ui/src/assets/icons/svg/star.svg | 1 + custom-ui/src/assets/icons/svg/swagger.svg | 1 + custom-ui/src/assets/icons/svg/switch.svg | 1 + custom-ui/src/assets/icons/svg/system.svg | 2 + custom-ui/src/assets/icons/svg/tab.svg | 1 + custom-ui/src/assets/icons/svg/table.svg | 1 + custom-ui/src/assets/icons/svg/textarea.svg | 1 + custom-ui/src/assets/icons/svg/theme.svg | 1 + custom-ui/src/assets/icons/svg/time-range.svg | 1 + custom-ui/src/assets/icons/svg/time.svg | 1 + custom-ui/src/assets/icons/svg/tool.svg | 1 + custom-ui/src/assets/icons/svg/tree-table.svg | 1 + custom-ui/src/assets/icons/svg/tree.svg | 1 + custom-ui/src/assets/icons/svg/upload.svg | 1 + custom-ui/src/assets/icons/svg/user.svg | 1 + custom-ui/src/assets/icons/svg/validCode.svg | 1 + custom-ui/src/assets/icons/svg/wechat.svg | 1 + custom-ui/src/assets/icons/svg/zip.svg | 1 + custom-ui/src/assets/icons/svgo.yml | 22 + custom-ui/src/assets/images/dark.svg | 39 + custom-ui/src/assets/images/light.svg | 39 + .../src/assets/images/login-background.jpg | Bin 0 -> 521275 bytes custom-ui/src/assets/images/profile.jpg | Bin 0 -> 81131 bytes custom-ui/src/assets/logo/logo.png | Bin 0 -> 5663 bytes custom-ui/src/assets/styles/btn.scss | 99 + custom-ui/src/assets/styles/element-ui.scss | 92 + .../src/assets/styles/element-variables.scss | 31 + custom-ui/src/assets/styles/index.scss | 191 + custom-ui/src/assets/styles/mixin.scss | 66 + custom-ui/src/assets/styles/ruoyi.scss | 277 + custom-ui/src/assets/styles/sidebar.scss | 227 + custom-ui/src/assets/styles/transition.scss | 53 + custom-ui/src/assets/styles/variables.scss | 54 + custom-ui/src/components/Breadcrumb/index.vue | 74 + custom-ui/src/components/Crontab/day.vue | 161 + custom-ui/src/components/Crontab/hour.vue | 114 + custom-ui/src/components/Crontab/index.vue | 430 + custom-ui/src/components/Crontab/min.vue | 116 + custom-ui/src/components/Crontab/month.vue | 114 + custom-ui/src/components/Crontab/result.vue | 559 + custom-ui/src/components/Crontab/second.vue | 117 + custom-ui/src/components/Crontab/week.vue | 202 + custom-ui/src/components/Crontab/year.vue | 131 + custom-ui/src/components/DictData/index.js | 49 + custom-ui/src/components/DictTag/index.vue | 52 + custom-ui/src/components/Editor/index.vue | 272 + custom-ui/src/components/FileUpload/index.vue | 215 + custom-ui/src/components/Hamburger/index.vue | 44 + .../src/components/HeaderSearch/index.vue | 189 + custom-ui/src/components/IconSelect/index.vue | 68 + .../src/components/IconSelect/requireIcons.js | 11 + .../src/components/ImagePreview/index.vue | 90 + .../src/components/ImageUpload/index.vue | 226 + custom-ui/src/components/Pagination/index.vue | 114 + custom-ui/src/components/PanThumb/index.vue | 142 + custom-ui/src/components/ParentView/index.vue | 3 + custom-ui/src/components/RightPanel/index.vue | 106 + .../src/components/RightToolbar/index.vue | 104 + custom-ui/src/components/RuoYi/Doc/index.vue | 21 + custom-ui/src/components/RuoYi/Git/index.vue | 21 + custom-ui/src/components/Screenfull/index.vue | 57 + custom-ui/src/components/SizeSelect/index.vue | 56 + custom-ui/src/components/SvgIcon/index.vue | 61 + .../src/components/ThemePicker/index.vue | 173 + custom-ui/src/components/TopNav/index.vue | 185 + custom-ui/src/components/iFrame/index.vue | 36 + custom-ui/src/directive/dialog/drag.js | 64 + custom-ui/src/directive/dialog/dragHeight.js | 34 + custom-ui/src/directive/dialog/dragWidth.js | 30 + custom-ui/src/directive/index.js | 23 + custom-ui/src/directive/module/clipboard.js | 54 + .../src/directive/permission/hasPermi.js | 28 + custom-ui/src/directive/permission/hasRole.js | 28 + custom-ui/src/layout/components/AppMain.vue | 61 + .../layout/components/IframeToggle/index.vue | 24 + .../src/layout/components/InnerLink/index.vue | 47 + custom-ui/src/layout/components/Navbar.vue | 192 + .../src/layout/components/Settings/index.vue | 260 + .../layout/components/Sidebar/FixiOSBug.js | 25 + .../src/layout/components/Sidebar/Item.vue | 33 + .../src/layout/components/Sidebar/Link.vue | 43 + .../src/layout/components/Sidebar/Logo.vue | 93 + .../layout/components/Sidebar/SidebarItem.vue | 100 + .../src/layout/components/Sidebar/index.vue | 57 + .../layout/components/TagsView/ScrollPane.vue | 94 + .../src/layout/components/TagsView/index.vue | 332 + custom-ui/src/layout/components/index.js | 5 + custom-ui/src/layout/index.vue | 111 + custom-ui/src/layout/mixin/ResizeHandler.js | 45 + custom-ui/src/main.js | 86 + custom-ui/src/permission.js | 56 + custom-ui/src/plugins/auth.js | 60 + custom-ui/src/plugins/cache.js | 77 + custom-ui/src/plugins/download.js | 72 + custom-ui/src/plugins/index.js | 20 + custom-ui/src/plugins/modal.js | 83 + custom-ui/src/plugins/tab.js | 67 + custom-ui/src/router/index.js | 177 + custom-ui/src/settings.js | 44 + custom-ui/src/store/getters.js | 19 + custom-ui/src/store/index.js | 25 + custom-ui/src/store/modules/app.js | 66 + custom-ui/src/store/modules/dict.js | 50 + custom-ui/src/store/modules/permission.js | 133 + custom-ui/src/store/modules/settings.js | 42 + custom-ui/src/store/modules/tagsView.js | 228 + custom-ui/src/store/modules/user.js | 96 + custom-ui/src/utils/auth.js | 15 + custom-ui/src/utils/dict/Dict.js | 82 + custom-ui/src/utils/dict/DictConverter.js | 17 + custom-ui/src/utils/dict/DictData.js | 13 + custom-ui/src/utils/dict/DictMeta.js | 38 + custom-ui/src/utils/dict/DictOptions.js | 51 + custom-ui/src/utils/dict/index.js | 33 + custom-ui/src/utils/errorCode.js | 6 + custom-ui/src/utils/generator/config.js | 438 + custom-ui/src/utils/generator/css.js | 18 + .../src/utils/generator/drawingDefault.js | 29 + custom-ui/src/utils/generator/html.js | 359 + custom-ui/src/utils/generator/icon.json | 1 + custom-ui/src/utils/generator/js.js | 236 + custom-ui/src/utils/generator/render.js | 126 + custom-ui/src/utils/index.js | 390 + custom-ui/src/utils/jsencrypt.js | 30 + custom-ui/src/utils/permission.js | 51 + custom-ui/src/utils/request.js | 146 + custom-ui/src/utils/ruoyi.js | 239 + custom-ui/src/utils/scroll-to.js | 58 + custom-ui/src/utils/validate.js | 83 + .../src/views/business/countGroup/index.vue | 175 + custom-ui/src/views/business/survey/index.vue | 347 + .../src/views/business/surveySubmit/index.vue | 166 + .../src/views/business/template/index.vue | 298 + .../src/views/business/templateProp/index.vue | 363 + .../business/templatePropValue/index.vue | 307 + .../views/components/icons/element-icons.js | 3 + .../src/views/components/icons/index.vue | 87 + .../src/views/components/icons/svg-icons.js | 10 + custom-ui/src/views/dashboard/BarChart.vue | 102 + custom-ui/src/views/dashboard/LineChart.vue | 135 + custom-ui/src/views/dashboard/PanelGroup.vue | 181 + custom-ui/src/views/dashboard/PieChart.vue | 79 + custom-ui/src/views/dashboard/RaddarChart.vue | 116 + .../src/views/dashboard/mixins/resize.js | 56 + custom-ui/src/views/error/401.vue | 88 + custom-ui/src/views/error/404.vue | 233 + custom-ui/src/views/index.vue | 87 + custom-ui/src/views/index_v1.vue | 98 + custom-ui/src/views/login.vue | 225 + custom-ui/src/views/monitor/cache/index.vue | 146 + custom-ui/src/views/monitor/cache/list.vue | 241 + custom-ui/src/views/monitor/druid/index.vue | 15 + custom-ui/src/views/monitor/job/index.vue | 513 + custom-ui/src/views/monitor/job/log.vue | 295 + .../src/views/monitor/logininfor/index.vue | 245 + custom-ui/src/views/monitor/online/index.vue | 122 + custom-ui/src/views/monitor/operlog/index.vue | 305 + custom-ui/src/views/monitor/server/index.vue | 207 + custom-ui/src/views/redirect.vue | 12 + custom-ui/src/views/register.vue | 209 + custom-ui/src/views/system/config/index.vue | 343 + custom-ui/src/views/system/dept/index.vue | 340 + custom-ui/src/views/system/dict/data.vue | 402 + custom-ui/src/views/system/dict/index.vue | 347 + custom-ui/src/views/system/menu/index.vue | 453 + custom-ui/src/views/system/notice/index.vue | 312 + custom-ui/src/views/system/post/index.vue | 309 + custom-ui/src/views/system/role/authUser.vue | 199 + custom-ui/src/views/system/role/index.vue | 605 + .../src/views/system/role/selectUser.vue | 138 + custom-ui/src/views/system/user/authRole.vue | 117 + custom-ui/src/views/system/user/index.vue | 670 + .../src/views/system/user/profile/index.vue | 91 + .../views/system/user/profile/resetPwd.vue | 68 + .../views/system/user/profile/userAvatar.vue | 187 + .../views/system/user/profile/userInfo.vue | 75 + .../src/views/tool/build/CodeTypeDialog.vue | 106 + .../src/views/tool/build/DraggableItem.vue | 100 + .../src/views/tool/build/IconsDialog.vue | 123 + custom-ui/src/views/tool/build/RightPanel.vue | 946 + .../src/views/tool/build/TreeNodeDialog.vue | 149 + custom-ui/src/views/tool/build/index.vue | 826 + .../src/views/tool/gen/basicInfoForm.vue | 60 + custom-ui/src/views/tool/gen/editTable.vue | 234 + custom-ui/src/views/tool/gen/genInfoForm.vue | 299 + custom-ui/src/views/tool/gen/importTable.vue | 120 + custom-ui/src/views/tool/gen/index.vue | 337 + custom-ui/src/views/tool/swagger/index.vue | 15 + custom-ui/vue.config.js | 136 + custom-ui/启动必看.txt | 5 + pom.xml | 487 +- ruoyi-admin/pom.xml | 112 + .../main/java/com/ruoyi/RunApplication.java | 30 + .../java/com/ruoyi/RunServletInitializer.java | 18 + .../controller/common/CaptchaController.java | 94 + .../controller/common/CommonController.java | 163 + .../controller/monitor/CacheController.java | 120 + .../controller/monitor/ServerController.java | 27 + .../monitor/SysLogininforController.java | 82 + .../monitor/SysOperlogController.java | 69 + .../monitor/SysUserOnlineController.java | 92 + .../system/SysConfigController.java | 134 + .../controller/system/SysDeptController.java | 132 + .../system/SysDictDataController.java | 121 + .../system/SysDictTypeController.java | 132 + .../controller/system/SysIndexController.java | 29 + .../controller/system/SysLoginController.java | 86 + .../controller/system/SysMenuController.java | 142 + .../system/SysNoticeController.java | 91 + .../controller/system/SysPostController.java | 130 + .../system/SysProfileController.java | 144 + .../system/SysRegisterController.java | 38 + .../controller/system/SysRoleController.java | 263 + .../controller/system/SysUserController.java | 256 + .../web/controller/tool/TestController.java | 183 + .../ruoyi/web/core/config/SwaggerConfig.java | 125 + .../META-INF/spring-devtools.properties | 1 + .../src/main/resources/application-druid.yml | 57 + .../src/main/resources/application.yml | 139 + ruoyi-admin/src/main/resources/banner.txt | 24 + .../main/resources/i18n/messages.properties | 37 + ruoyi-admin/src/main/resources/logback.xml | 93 + .../main/resources/mybatis/mybatis-config.xml | 20 + ruoyi-business/pom.xml | 28 + .../controller/BusinessSurveyController.java | 138 + .../BusinessTemplateController.java | 138 + .../BusinessTemplatePropController.java | 121 + .../BusinessTemplatePropValueController.java | 128 + .../ruoyi/business/domain/BusinessSurvey.java | 64 + .../business/domain/BusinessTemplate.java | 73 + .../business/domain/BusinessTemplateProp.java | 182 + .../domain/BusinessTemplatePropValue.java | 111 + .../business/mapper/BusinessSurveyMapper.java | 16 + .../mapper/BusinessTemplateMapper.java | 16 + .../mapper/BusinessTemplatePropMapper.java | 16 + .../BusinessTemplatePropValueMapper.java | 23 + .../service/IBusinessSurveyService.java | 22 + .../service/IBusinessTemplatePropService.java | 15 + .../IBusinessTemplatePropValueService.java | 28 + .../service/IBusinessTemplateService.java | 15 + .../impl/BusinessSurveyServiceImpl.java | 102 + .../impl/BusinessTemplatePropServiceImpl.java | 27 + .../BusinessTemplatePropValueServiceImpl.java | 149 + .../impl/BusinessTemplateServiceImpl.java | 27 + .../mapper/business/BusinessSurveyMapper.xml | 95 + .../business/BusinessTemplateMapper.xml | 90 + .../business/BusinessTemplatePropMapper.xml | 115 + .../BusinessTemplatePropValueMapper.xml | 113 + ruoyi-common/pom.xml | 148 + .../ruoyi/common/annotation/Anonymous.java | 19 + .../ruoyi/common/annotation/DataScope.java | 33 + .../ruoyi/common/annotation/DataSource.java | 28 + .../com/ruoyi/common/annotation/Excel.java | 187 + .../com/ruoyi/common/annotation/Excels.java | 18 + .../java/com/ruoyi/common/annotation/Log.java | 46 + .../ruoyi/common/annotation/RateLimiter.java | 40 + .../ruoyi/common/annotation/RepeatSubmit.java | 31 + .../com/ruoyi/common/config/RuoYiConfig.java | 135 + .../ruoyi/common/constant/CacheConstants.java | 44 + .../com/ruoyi/common/constant/Constants.java | 142 + .../ruoyi/common/constant/GenConstants.java | 117 + .../com/ruoyi/common/constant/HttpStatus.java | 94 + .../common/constant/ScheduleConstants.java | 50 + .../ruoyi/common/constant/UserConstants.java | 78 + .../core/controller/BaseController.java | 202 + .../ruoyi/common/core/domain/AjaxResult.java | 185 + .../ruoyi/common/core/domain/BaseEntity.java | 152 + .../java/com/ruoyi/common/core/domain/R.java | 115 + .../ruoyi/common/core/domain/TreeEntity.java | 79 + .../ruoyi/common/core/domain/TreeSelect.java | 77 + .../common/core/domain/entity/SysDept.java | 203 + .../core/domain/entity/SysDictData.java | 176 + .../core/domain/entity/SysDictType.java | 96 + .../common/core/domain/entity/SysMenu.java | 259 + .../common/core/domain/entity/SysRole.java | 241 + .../common/core/domain/entity/SysUser.java | 324 + .../common/core/domain/model/LoginBody.java | 69 + .../common/core/domain/model/LoginUser.java | 266 + .../core/domain/model/RegisterBody.java | 11 + .../ruoyi/common/core/page/PageDomain.java | 101 + .../ruoyi/common/core/page/TableDataInfo.java | 85 + .../ruoyi/common/core/page/TableSupport.java | 56 + .../ruoyi/common/core/redis/RedisCache.java | 268 + .../ruoyi/common/core/text/CharsetKit.java | 86 + .../com/ruoyi/common/core/text/Convert.java | 1000 + .../ruoyi/common/core/text/StrFormatter.java | 92 + .../ruoyi/common/enums/BusinessStatus.java | 20 + .../com/ruoyi/common/enums/BusinessType.java | 59 + .../ruoyi/common/enums/DataSourceType.java | 19 + .../com/ruoyi/common/enums/HttpMethod.java | 36 + .../com/ruoyi/common/enums/LimitType.java | 20 + .../com/ruoyi/common/enums/OperatorType.java | 24 + .../com/ruoyi/common/enums/UserStatus.java | 30 + .../common/exception/DemoModeException.java | 15 + .../common/exception/GlobalException.java | 58 + .../common/exception/ServiceException.java | 74 + .../ruoyi/common/exception/UtilException.java | 26 + .../common/exception/base/BaseException.java | 97 + .../common/exception/file/FileException.java | 19 + .../FileNameLengthLimitExceededException.java | 16 + .../file/FileSizeLimitExceededException.java | 16 + .../file/InvalidExtensionException.java | 81 + .../common/exception/job/TaskException.java | 34 + .../exception/user/CaptchaException.java | 16 + .../user/CaptchaExpireException.java | 16 + .../common/exception/user/UserException.java | 18 + .../user/UserPasswordNotMatchException.java | 16 + ...UserPasswordRetryLimitExceedException.java | 16 + .../filter/PropertyPreExcludeFilter.java | 24 + .../ruoyi/common/filter/RepeatableFilter.java | 52 + .../filter/RepeatedlyRequestWrapper.java | 76 + .../com/ruoyi/common/filter/XssFilter.java | 75 + .../filter/XssHttpServletRequestWrapper.java | 111 + .../common/handler/MyMetaObjectHandler.java | 52 + .../java/com/ruoyi/common/utils/Arith.java | 114 + .../com/ruoyi/common/utils/DateUtils.java | 187 + .../com/ruoyi/common/utils/DictUtils.java | 186 + .../com/ruoyi/common/utils/ExceptionUtil.java | 39 + .../java/com/ruoyi/common/utils/LogUtils.java | 18 + .../com/ruoyi/common/utils/MessageUtils.java | 26 + .../com/ruoyi/common/utils/PageUtils.java | 35 + .../com/ruoyi/common/utils/SecurityUtils.java | 120 + .../com/ruoyi/common/utils/ServletUtils.java | 218 + .../com/ruoyi/common/utils/StringUtils.java | 614 + .../java/com/ruoyi/common/utils/Threads.java | 99 + .../ruoyi/common/utils/bean/BeanUtils.java | 110 + .../common/utils/bean/BeanValidators.java | 24 + .../common/utils/file/FileTypeUtils.java | 76 + .../common/utils/file/FileUploadUtils.java | 232 + .../ruoyi/common/utils/file/FileUtils.java | 291 + .../ruoyi/common/utils/file/ImageUtils.java | 98 + .../common/utils/file/MimeTypeUtils.java | 59 + .../ruoyi/common/utils/html/EscapeUtil.java | 167 + .../ruoyi/common/utils/html/HTMLFilter.java | 570 + .../ruoyi/common/utils/http/HttpHelper.java | 55 + .../ruoyi/common/utils/http/HttpUtils.java | 274 + .../ruoyi/common/utils/ip/AddressUtils.java | 56 + .../com/ruoyi/common/utils/ip/IpUtils.java | 264 + .../common/utils/poi/ExcelHandlerAdapter.java | 19 + .../com/ruoyi/common/utils/poi/ExcelUtil.java | 1734 ++ .../common/utils/reflect/ReflectUtils.java | 410 + .../com/ruoyi/common/utils/sign/Base64.java | 291 + .../com/ruoyi/common/utils/sign/Md5Utils.java | 67 + .../common/utils/spring/SpringUtils.java | 158 + .../com/ruoyi/common/utils/sql/SqlUtil.java | 61 + .../com/ruoyi/common/utils/uuid/IdUtils.java | 49 + .../java/com/ruoyi/common/utils/uuid/Seq.java | 86 + .../com/ruoyi/common/utils/uuid/UUID.java | 484 + .../main/java/com/ruoyi/common/xss/Xss.java | 27 + .../com/ruoyi/common/xss/XssValidator.java | 34 + ruoyi-framework/pom.xml | 70 + .../framework/aspectj/DataScopeAspect.java | 167 + .../framework/aspectj/DataSourceAspect.java | 72 + .../ruoyi/framework/aspectj/LogAspect.java | 227 + .../framework/aspectj/RateLimiterAspect.java | 90 + .../framework/config/ApplicationConfig.java | 30 + .../ruoyi/framework/config/CaptchaConfig.java | 83 + .../ruoyi/framework/config/DruidConfig.java | 126 + .../config/FastJson2JsonRedisSerializer.java | 48 + .../ruoyi/framework/config/FilterConfig.java | 58 + .../framework/config/KaptchaTextCreator.java | 68 + .../framework/config/MybatisPlusConfig.java | 62 + .../ruoyi/framework/config/RedisConfig.java | 69 + .../framework/config/ResourcesConfig.java | 73 + .../framework/config/SecurityConfig.java | 148 + .../ruoyi/framework/config/ServerConfig.java | 32 + .../framework/config/ThreadPoolConfig.java | 63 + .../config/properties/DruidProperties.java | 77 + .../properties/PermitAllUrlProperties.java | 72 + .../datasource/DynamicDataSource.java | 26 + .../DynamicDataSourceContextHolder.java | 45 + .../interceptor/RepeatSubmitInterceptor.java | 55 + .../impl/SameUrlDataInterceptor.java | 110 + .../ruoyi/framework/manager/AsyncManager.java | 55 + .../framework/manager/ShutdownManager.java | 39 + .../manager/factory/AsyncFactory.java | 102 + .../context/AuthenticationContextHolder.java | 28 + .../context/PermissionContextHolder.java | 27 + .../filter/JwtAuthenticationTokenFilter.java | 44 + .../handle/AuthenticationEntryPointImpl.java | 34 + .../handle/LogoutSuccessHandlerImpl.java | 52 + .../ruoyi/framework/web/domain/Server.java | 240 + .../framework/web/domain/server/Cpu.java | 101 + .../framework/web/domain/server/Jvm.java | 130 + .../framework/web/domain/server/Mem.java | 61 + .../framework/web/domain/server/Sys.java | 84 + .../framework/web/domain/server/SysFile.java | 114 + .../web/exception/GlobalExceptionHandler.java | 114 + .../web/service/PermissionService.java | 168 + .../web/service/SysLoginService.java | 141 + .../web/service/SysPasswordService.java | 94 + .../web/service/SysPermissionService.java | 82 + .../web/service/SysRegisterService.java | 115 + .../framework/web/service/TokenService.java | 226 + .../web/service/UserDetailsServiceImpl.java | 65 + ruoyi-generator/pom.xml | 40 + .../com/ruoyi/generator/config/GenConfig.java | 73 + .../generator/controller/GenController.java | 214 + .../com/ruoyi/generator/domain/GenTable.java | 372 + .../generator/domain/GenTableColumn.java | 373 + .../mapper/GenTableColumnMapper.java | 60 + .../generator/mapper/GenTableMapper.java | 83 + .../service/GenTableColumnServiceImpl.java | 68 + .../service/GenTableServiceImpl.java | 521 + .../service/IGenTableColumnService.java | 44 + .../generator/service/IGenTableService.java | 121 + .../com/ruoyi/generator/util/GenUtils.java | 257 + .../generator/util/VelocityInitializer.java | 34 + .../ruoyi/generator/util/VelocityUtils.java | 402 + .../src/main/resources/generator.yml | 10 + .../mapper/generator/GenTableColumnMapper.xml | 127 + .../mapper/generator/GenTableMapper.xml | 202 + .../main/resources/vm/java/controller.java.vm | 116 + .../src/main/resources/vm/java/domain.java.vm | 109 + .../src/main/resources/vm/java/mapper.java.vm | 19 + .../main/resources/vm/java/service.java.vm | 15 + .../resources/vm/java/serviceImpl.java.vm | 35 + .../main/resources/vm/java/sub-domain.java.vm | 76 + .../src/main/resources/vm/js/api.js.vm | 44 + .../src/main/resources/vm/sql/sql.vm | 22 + .../main/resources/vm/vue/index-tree.vue.vm | 505 + .../src/main/resources/vm/vue/index.vue.vm | 607 + .../resources/vm/vue/v3/index-tree.vue.vm | 474 + .../src/main/resources/vm/vue/v3/index.vue.vm | 595 + .../src/main/resources/vm/vue/v3/readme.txt | 1 + .../src/main/resources/vm/xml/mapper.xml.vm | 135 + ruoyi-quartz/pom.xml | 40 + .../ruoyi/quartz/config/ScheduleConfig.java | 57 + .../quartz/controller/SysJobController.java | 185 + .../controller/SysJobLogController.java | 92 + .../java/com/ruoyi/quartz/domain/SysJob.java | 171 + .../com/ruoyi/quartz/domain/SysJobLog.java | 155 + .../ruoyi/quartz/mapper/SysJobLogMapper.java | 64 + .../com/ruoyi/quartz/mapper/SysJobMapper.java | 67 + .../quartz/service/ISysJobLogService.java | 56 + .../ruoyi/quartz/service/ISysJobService.java | 102 + .../service/impl/SysJobLogServiceImpl.java | 87 + .../service/impl/SysJobServiceImpl.java | 261 + .../java/com/ruoyi/quartz/task/RyTask.java | 28 + .../ruoyi/quartz/util/AbstractQuartzJob.java | 107 + .../java/com/ruoyi/quartz/util/CronUtils.java | 63 + .../com/ruoyi/quartz/util/JobInvokeUtil.java | 182 + .../QuartzDisallowConcurrentExecution.java | 21 + .../ruoyi/quartz/util/QuartzJobExecution.java | 19 + .../com/ruoyi/quartz/util/ScheduleUtils.java | 139 + .../mapper/quartz/SysJobLogMapper.xml | 93 + .../resources/mapper/quartz/SysJobMapper.xml | 111 + ruoyi-system/pom.xml | 28 + .../com/ruoyi/system/domain/SysCache.java | 81 + .../com/ruoyi/system/domain/SysConfig.java | 111 + .../ruoyi/system/domain/SysLogininfor.java | 144 + .../com/ruoyi/system/domain/SysNotice.java | 102 + .../com/ruoyi/system/domain/SysOperLog.java | 255 + .../java/com/ruoyi/system/domain/SysPost.java | 124 + .../com/ruoyi/system/domain/SysRoleDept.java | 46 + .../com/ruoyi/system/domain/SysRoleMenu.java | 46 + .../ruoyi/system/domain/SysUserOnline.java | 113 + .../com/ruoyi/system/domain/SysUserPost.java | 46 + .../com/ruoyi/system/domain/SysUserRole.java | 46 + .../com/ruoyi/system/domain/vo/MetaVo.java | 106 + .../com/ruoyi/system/domain/vo/RouterVo.java | 148 + .../ruoyi/system/mapper/SysConfigMapper.java | 76 + .../ruoyi/system/mapper/SysDeptMapper.java | 118 + .../system/mapper/SysDictDataMapper.java | 95 + .../system/mapper/SysDictTypeMapper.java | 83 + .../system/mapper/SysLogininforMapper.java | 42 + .../ruoyi/system/mapper/SysMenuMapper.java | 125 + .../ruoyi/system/mapper/SysNoticeMapper.java | 60 + .../ruoyi/system/mapper/SysOperLogMapper.java | 48 + .../ruoyi/system/mapper/SysPostMapper.java | 99 + .../system/mapper/SysRoleDeptMapper.java | 44 + .../ruoyi/system/mapper/SysRoleMapper.java | 107 + .../system/mapper/SysRoleMenuMapper.java | 44 + .../ruoyi/system/mapper/SysUserMapper.java | 127 + .../system/mapper/SysUserPostMapper.java | 44 + .../system/mapper/SysUserRoleMapper.java | 62 + .../system/service/ISysConfigService.java | 89 + .../ruoyi/system/service/ISysDeptService.java | 124 + .../system/service/ISysDictDataService.java | 60 + .../system/service/ISysDictTypeService.java | 98 + .../system/service/ISysLogininforService.java | 40 + .../ruoyi/system/service/ISysMenuService.java | 144 + .../system/service/ISysNoticeService.java | 60 + .../system/service/ISysOperLogService.java | 48 + .../ruoyi/system/service/ISysPostService.java | 99 + .../ruoyi/system/service/ISysRoleService.java | 173 + .../system/service/ISysUserOnlineService.java | 48 + .../ruoyi/system/service/ISysUserService.java | 206 + .../service/impl/SysConfigServiceImpl.java | 232 + .../service/impl/SysDeptServiceImpl.java | 338 + .../service/impl/SysDictDataServiceImpl.java | 111 + .../service/impl/SysDictTypeServiceImpl.java | 223 + .../impl/SysLogininforServiceImpl.java | 65 + .../service/impl/SysMenuServiceImpl.java | 531 + .../service/impl/SysNoticeServiceImpl.java | 92 + .../service/impl/SysOperLogServiceImpl.java | 76 + .../service/impl/SysPostServiceImpl.java | 178 + .../service/impl/SysRoleServiceImpl.java | 424 + .../impl/SysUserOnlineServiceImpl.java | 96 + .../service/impl/SysUserServiceImpl.java | 543 + .../mapper/system/SysConfigMapper.xml | 117 + .../resources/mapper/system/SysDeptMapper.xml | 159 + .../mapper/system/SysDictDataMapper.xml | 124 + .../mapper/system/SysDictTypeMapper.xml | 105 + .../mapper/system/SysLogininforMapper.xml | 57 + .../resources/mapper/system/SysMenuMapper.xml | 202 + .../mapper/system/SysNoticeMapper.xml | 89 + .../mapper/system/SysOperLogMapper.xml | 83 + .../resources/mapper/system/SysPostMapper.xml | 122 + .../mapper/system/SysRoleDeptMapper.xml | 34 + .../resources/mapper/system/SysRoleMapper.xml | 152 + .../mapper/system/SysRoleMenuMapper.xml | 34 + .../resources/mapper/system/SysUserMapper.xml | 221 + .../mapper/system/SysUserPostMapper.xml | 34 + .../mapper/system/SysUserRoleMapper.xml | 44 + sql/dba.sql | 1251 ++ wjcy-common/pom.xml | 37 - .../zhengjie/annotation/AnonymousAccess.java | 30 - .../java/me/zhengjie/annotation/CheckPwd.java | 25 - .../zhengjie/annotation/DataPermission.java | 47 - .../java/me/zhengjie/annotation/DateTime.java | 31 - .../zhengjie/annotation/FormSubmission.java | 28 - .../java/me/zhengjie/annotation/Limit.java | 49 - .../java/me/zhengjie/annotation/Query.java | 90 - .../rest/AnonymousDeleteMapping.java | 91 - .../annotation/rest/AnonymousGetMapping.java | 90 - .../rest/AnonymousPatchMapping.java | 91 - .../annotation/rest/AnonymousPostMapping.java | 91 - .../annotation/rest/AnonymousPutMapping.java | 91 - .../java/me/zhengjie/aspect/LimitAspect.java | 99 - .../java/me/zhengjie/aspect/LimitType.java | 27 - .../main/java/me/zhengjie/base/BaseDTO.java | 40 - .../java/me/zhengjie/base/BaseEntity.java | 85 - .../java/me/zhengjie/base/BaseMapper.java | 53 - .../me/zhengjie/config/AuditorConfig.java | 45 - .../java/me/zhengjie/config/BeanFactory.java | 105 - .../me/zhengjie/config/CorsInterceptor.java | 36 - .../me/zhengjie/config/CustomIdGenerator.java | 39 - .../me/zhengjie/config/DhApiProperties.java | 58 - .../zhengjie/config/ElPermissionConfig.java | 37 - .../me/zhengjie/config/FileProperties.java | 60 - .../java/me/zhengjie/config/MvcConfig.java | 31 - .../zhengjie/config/MyMetaObjectHandler.java | 82 - .../me/zhengjie/config/MybatisPlusConfig.java | 32 - .../me/zhengjie/config/PlatsProperties.java | 44 - .../me/zhengjie/config/PropertiesConfig.java | 30 - .../java/me/zhengjie/config/RedisConfig.java | 223 - .../me/zhengjie/config/RedissonConfig.java | 48 - .../me/zhengjie/config/RsaProperties.java | 38 - .../me/zhengjie/config/SwaggerConfig.java | 217 - .../java/me/zhengjie/config/SystemConfig.java | 97 - .../me/zhengjie/config/YdApiProperties.java | 34 - .../zhengjie/config/constant/Constants.java | 30 - .../java/me/zhengjie/constant/Constants.java | 16 - .../me/zhengjie/constant/PublicConstant.java | 56 - .../main/java/me/zhengjie/dao/CtApplyDao.java | 39 - .../java/me/zhengjie/dao/CtBrowseDao.java | 61 - .../main/java/me/zhengjie/dao/CtBuyerDao.java | 56 - .../main/java/me/zhengjie/dao/CtCardDao.java | 34 - .../me/zhengjie/dao/CtClickFarmingDao.java | 90 - .../java/me/zhengjie/dao/CtClickOrderDao.java | 100 - .../java/me/zhengjie/dao/CtCompanyDao.java | 34 - .../main/java/me/zhengjie/dao/CtDhPayDao.java | 24 - .../main/java/me/zhengjie/dao/CtExcelDao.java | 17 - .../me/zhengjie/dao/CtExcelImportInfoDao.java | 17 - .../main/java/me/zhengjie/dao/CtOrderDao.java | 17 - .../java/me/zhengjie/dao/CtPlatformDao.java | 17 - .../main/java/me/zhengjie/dao/CtRebotDao.java | 41 - .../dao/CtResponseOrderAddressDao.java | 17 - .../me/zhengjie/dao/CtResponseOrderDao.java | 17 - .../dao/CtResponseOrderProductDao.java | 17 - .../main/java/me/zhengjie/dao/CtVpnDao.java | 35 - .../java/me/zhengjie/dao/DhAddCarDao.java | 61 - .../me/zhengjie/dao/DhAddCarOrderDao.java | 48 - .../java/me/zhengjie/dao/DhCarGoodsDao.java | 17 - .../main/java/me/zhengjie/dao/LoginIpDao.java | 17 - .../java/me/zhengjie/dao/SettingSiteDao.java | 17 - .../java/me/zhengjie/dao/SysQuartzJobDao.java | 26 - .../java/me/zhengjie/dao/SysQuartzLogDao.java | 23 - .../me/zhengjie/dao/mapper/CtDhPayService.xml | 12 - .../src/main/java/me/zhengjie/dto/Dto.java | 73 - .../main/java/me/zhengjie/dto/PageDTO.java | 49 - .../zhengjie/dto/StatementAggregateDTO.java | 38 - .../main/java/me/zhengjie/entity/CtApply.java | 73 - .../java/me/zhengjie/entity/CtBrowse.java | 45 - .../me/zhengjie/entity/CtBrowseYdParams.java | 33 - .../main/java/me/zhengjie/entity/CtBuyer.java | 103 - .../zhengjie/entity/CtBuyerClickSuccess.java | 19 - .../zhengjie/entity/CtBuyerContactInfo.java | 45 - .../me/zhengjie/entity/CtBuyerExport.java | 71 - .../zhengjie/entity/CtBuyerExportTemple.java | 67 - .../me/zhengjie/entity/CtBuyerImport.java | 84 - .../main/java/me/zhengjie/entity/CtCard.java | 80 - .../java/me/zhengjie/entity/CtCardExport.java | 40 - .../zhengjie/entity/CtCardExportTemple.java | 46 - .../java/me/zhengjie/entity/CtCardImport.java | 96 - .../java/me/zhengjie/entity/CtCardInfo.java | 22 - .../entity/CtClickFarmSupplyMentYdParams.java | 41 - .../zhengjie/entity/CtClickFarmYdParams.java | 59 - .../me/zhengjie/entity/CtClickFarming.java | 70 - .../zhengjie/entity/CtClickFarmingExport.java | 59 - .../entity/CtClickFarmingExportTemp.java | 53 - .../zhengjie/entity/CtClickFarmingImport.java | 64 - .../entity/CtClickFarmingOrderInfo.java | 37 - .../java/me/zhengjie/entity/CtClickOrder.java | 55 - .../zhengjie/entity/CtClickOrderExport.java | 37 - .../entity/CtClickOrderExportTemple.java | 39 - .../zhengjie/entity/CtClickOrderImport.java | 40 - .../zhengjie/entity/CtClickOrderYdParams.java | 33 - .../java/me/zhengjie/entity/CtCompany.java | 43 - .../me/zhengjie/entity/CtCompanyInfo.java | 23 - .../main/java/me/zhengjie/entity/CtDhPay.java | 44 - .../me/zhengjie/entity/CtDhPayExport.java | 29 - .../zhengjie/entity/CtDhPayExportTemple.java | 25 - .../me/zhengjie/entity/CtDhPayImport.java | 40 - .../main/java/me/zhengjie/entity/CtExcel.java | 41 - .../me/zhengjie/entity/CtExcelExportInfo.java | 40 - .../zhengjie/entity/CtExcelExportTemple.java | 33 - .../me/zhengjie/entity/CtExcelImportInfo.java | 59 - .../main/java/me/zhengjie/entity/CtOrder.java | 55 - .../zhengjie/entity/CtParamContactInfo.java | 39 - .../me/zhengjie/entity/CtParamProduct.java | 29 - .../java/me/zhengjie/entity/CtPlatform.java | 40 - .../main/java/me/zhengjie/entity/CtRebot.java | 41 - .../me/zhengjie/entity/CtRebotExport.java | 31 - .../zhengjie/entity/CtRebotExportTemple.java | 24 - .../me/zhengjie/entity/CtRebotImport.java | 43 - .../me/zhengjie/entity/CtResponseOrder.java | 67 - .../entity/CtResponseOrderAddress.java | 53 - .../entity/CtResponseOrderProduct.java | 96 - .../me/zhengjie/entity/CtSettingSite.java | 43 - .../main/java/me/zhengjie/entity/CtVpn.java | 55 - .../java/me/zhengjie/entity/CtVpnExport.java | 45 - .../me/zhengjie/entity/CtVpnExportTemple.java | 43 - .../java/me/zhengjie/entity/CtVpnImport.java | 66 - .../java/me/zhengjie/entity/CtVpnInfo.java | 23 - .../java/me/zhengjie/entity/DhAddCar.java | 48 - .../me/zhengjie/entity/DhAddCarOrder.java | 55 - .../java/me/zhengjie/entity/DhCarGoods.java | 62 - .../me/zhengjie/entity/ExcelImportInfo.java | 38 - .../main/java/me/zhengjie/entity/LoginIp.java | 39 - .../zhengjie/entity/QueryWrapperAndPage.java | 15 - .../java/me/zhengjie/entity/ResultObj.java | 20 - .../java/me/zhengjie/entity/ReturnObje.java | 28 - .../java/me/zhengjie/entity/SysQuartzJob.java | 70 - .../java/me/zhengjie/entity/SysQuartzLog.java | 58 - .../main/java/me/zhengjie/entity/YdSign.java | 32 - .../me/zhengjie/entity/YdStartReturn.java | 24 - .../java/me/zhengjie/entity/quartz/Boss.java | 23 - .../me/zhengjie/entity/quartz/DataInfo.java | 19 - .../entity/quartz/JobQueryByUuid.java | 18 - .../entity/quartz/JobQueryByUuidData.java | 28 - .../entity/quartz/JobQueryByUuidReturn.java | 93 - .../quartz/JobQueryByUuidRobotParams.java | 22 - .../entity/quartz/JobQueryReturnResult.java | 22 - .../java/me/zhengjie/entity/quartz/Param.java | 20 - .../me/zhengjie/entity/quartz/Params.java | 22 - .../me/zhengjie/entity/quartz/RebotStatu.java | 19 - .../entity/quartz/RebotStatuInfo.java | 29 - .../entity/quartz/RebotStatuReturn.java | 20 - .../me/zhengjie/entity/quartz/SecreInfo.java | 21 - .../entity/quartz/StartYdReturnInfo.java | 22 - .../me/zhengjie/enums/BuyerLevelEnum.java | 77 - .../zhengjie/enums/BuyerOccupyStatusEnum.java | 75 - .../me/zhengjie/enums/BuyerStatusEnum.java | 80 - .../me/zhengjie/enums/CardDealerTypeEnum.java | 75 - .../me/zhengjie/enums/CardStatusEnum.java | 76 - .../java/me/zhengjie/enums/CardTypeEnum.java | 76 - .../zhengjie/enums/ClickBrowseStatusEnum.java | 77 - .../enums/ClickFarmingStatusEnum.java | 79 - .../zhengjie/enums/ClickOrderStatusEnum.java | 77 - .../me/zhengjie/enums/CtReboteStatusEnum.java | 75 - .../me/zhengjie/enums/DhAddCarStatusEnum.java | 82 - .../me/zhengjie/enums/DhPayStatusEnum.java | 77 - .../enums/ExcelInfoRequestTypeEnum.java | 75 - .../me/zhengjie/enums/ExcelStatusEnum.java | 76 - .../java/me/zhengjie/enums/LanguageEnum.java | 38 - .../java/me/zhengjie/enums/OrderTypeEnum.java | 75 - .../me/zhengjie/enums/ParamsTypeEnum.java | 75 - .../java/me/zhengjie/enums/PlatTypeEnum.java | 92 - .../me/zhengjie/enums/RobotStatusEnum.java | 77 - .../java/me/zhengjie/enums/TaskInfoEnum.java | 54 - .../me/zhengjie/enums/TaskIsPauseEnum.java | 75 - .../java/me/zhengjie/enums/TaskTypeEnum.java | 75 - .../java/me/zhengjie/enums/VpnDealerEnum.java | 74 - .../java/me/zhengjie/enums/VpnStatusEnum.java | 75 - .../java/me/zhengjie/enums/VpnTypeEnum.java | 74 - .../java/me/zhengjie/enums/YesOrNoEnum.java | 75 - .../enums/interfaces/IntegerEnum.java | 40 - .../zhengjie/enums/interfaces/LongEnum.java | 40 - .../enums/interfaces/MemberIsUsedEnum.java | 71 - .../java/me/zhengjie/error/ErrorCodeEnum.java | 143 - .../exception/BadConfigurationException.java | 98 - .../exception/BadRequestException.java | 50 - .../exception/EntityExistException.java | 34 - .../exception/EntityNotFoundException.java | 34 - .../zhengjie/exception/handler/ApiError.java | 52 - .../handler/GlobalExceptionHandler.java | 197 - .../mybatis/LambdaQueryWrapperImpl.java | 29 - .../me/zhengjie/service/CtApplyService.java | 42 - .../me/zhengjie/service/CtBrowseService.java | 41 - .../me/zhengjie/service/CtBuyerService.java | 50 - .../me/zhengjie/service/CtCardService.java | 26 - .../service/CtClickFarmingService.java | 36 - .../zhengjie/service/CtClickOrderService.java | 65 - .../me/zhengjie/service/CtCompanyService.java | 34 - .../me/zhengjie/service/CtDhPayService.java | 29 - .../service/CtExcelImportInfoService.java | 23 - .../me/zhengjie/service/CtExcelService.java | 15 - .../me/zhengjie/service/CtOrderService.java | 31 - .../zhengjie/service/CtPlatformService.java | 24 - .../me/zhengjie/service/CtRebotService.java | 63 - .../CtResponseOrderAddressService.java | 17 - .../CtResponseOrderProductService.java | 17 - .../service/CtResponseOrderService.java | 17 - .../me/zhengjie/service/CtVpnService.java | 24 - .../service/DhAddCarOrderService.java | 41 - .../me/zhengjie/service/DhAddCarService.java | 49 - .../zhengjie/service/DhCarGoodsService.java | 15 - .../zhengjie/service/FileUploadService.java | 20 - .../me/zhengjie/service/LoginIpService.java | 58 - .../zhengjie/service/SettingSiteService.java | 25 - .../zhengjie/service/SysQuartzLogService.java | 21 - .../me/zhengjie/service/YdQuartzService.java | 74 - .../service/impl/CtApplyServiceImpl.java | 44 - .../service/impl/CtBrowseServiceImpl.java | 44 - .../service/impl/CtBuyerServiceImpl.java | 69 - .../service/impl/CtCardServiceImpl.java | 33 - .../impl/CtClickFarmingServiceImpl.java | 62 - .../service/impl/CtClickOrderServiceImpl.java | 90 - .../service/impl/CtCompanyServiceImpl.java | 53 - .../service/impl/CtDhPayServiceImpl.java | 100 - .../impl/CtExcelImportInfoServiceImpl.java | 174 - .../service/impl/CtExcelServiceImpl.java | 19 - .../service/impl/CtOrderServiceImpl.java | 196 - .../service/impl/CtPlatformServiceImpl.java | 37 - .../service/impl/CtRebotServiceImpl.java | 127 - .../CtResponseOrderAddressServiceImpl.java | 19 - .../CtResponseOrderProductServiceImpl.java | 19 - .../impl/CtResponseOrderServiceImpl.java | 19 - .../service/impl/CtVpnServiceImpl.java | 31 - .../impl/DhAddCarOrderServiceImpl.java | 98 - .../service/impl/DhAddCarServiceImpl.java | 108 - .../service/impl/DhCarGoodsServiceImpl.java | 19 - .../service/impl/FileUploadServiceImpl.java | 130 - .../service/impl/LoginIpServiceImpl.java | 121 - .../service/impl/SettingSiteServiceImpl.java | 75 - .../service/impl/SysQuartzJobServiceImpl.java | 63 - .../service/impl/SysQuartzLogServiceImpl.java | 35 - .../service/impl/YdQuartzServiceImpl.java | 464 - .../service/redission/LockCallBack.java | 8 - .../service/vo/AdminGoogleAuthInfoVO.java | 31 - .../service/vo/BuyOrderResponseAddressVO.java | 39 - .../service/vo/BuyOrderResponseOrderVO.java | 54 - .../service/vo/BuyOrderResponseProductVO.java | 81 - .../me/zhengjie/service/vo/BuyOrderVO.java | 24 - .../me/zhengjie/service/vo/CtApplyInfoVO.java | 19 - .../me/zhengjie/service/vo/CtApplyListVO.java | 68 - .../zhengjie/service/vo/CtBrowseDetailVO.java | 73 - .../zhengjie/service/vo/CtBrowseListVO.java | 63 - .../service/vo/CtBuyerClickFarmVO.java | 103 - .../zhengjie/service/vo/CtBuyerDetailVO.java | 162 - .../me/zhengjie/service/vo/CtBuyerListVO.java | 111 - .../me/zhengjie/service/vo/CtBuyerVO.java | 47 - .../zhengjie/service/vo/CtCardDetailVO.java | 125 - .../me/zhengjie/service/vo/CtCardListVO.java | 72 - .../service/vo/CtClickFarmEditDetailVO.java | 63 - .../service/vo/CtClickFarmingDetailVO.java | 98 - .../zhengjie/service/vo/CtClickFarmingVO.java | 59 - .../service/vo/CtClickOrderDetailVO.java | 48 - .../service/vo/CtClickOrderListVO.java | 45 - .../zhengjie/service/vo/CtCompanyInfoVO.java | 23 - .../me/zhengjie/service/vo/CtCompanyVO.java | 35 - .../zhengjie/service/vo/CtDhPayDetailVO.java | 40 - .../me/zhengjie/service/vo/CtDhPayListVO.java | 36 - .../service/vo/CtExcelImportInfoVO.java | 42 - .../me/zhengjie/service/vo/CtExcelVO.java | 31 - .../me/zhengjie/service/vo/CtOrderVO.java | 44 - .../zhengjie/service/vo/CtPlatformInfoVO.java | 23 - .../me/zhengjie/service/vo/CtPlatformVO.java | 29 - .../me/zhengjie/service/vo/CtRebotListVO.java | 37 - .../me/zhengjie/service/vo/CtVpnInfoVO.java | 16 - .../java/me/zhengjie/service/vo/CtVpnVO.java | 42 - .../zhengjie/service/vo/GoogleAuthInfoVO.java | 27 - .../me/zhengjie/service/vo/LoginIpVO.java | 57 - .../service/vo/OrderResponStatusVO.java | 21 - .../service/vo/OrderResponSubErrorVO.java | 19 - .../zhengjie/service/vo/OrderResponseVO.java | 28 - .../me/zhengjie/service/vo/PayOrderVO.java | 23 - .../me/zhengjie/service/vo/SettingSiteVO.java | 31 - .../service/vo/SysQuartzJobListVO.java | 40 - .../service/vo/SysQuartzLogListVO.java | 47 - .../service/vo/dhaddcar/DhAddCarListVO.java | 80 - .../service/vo/dhaddcar/DhAddCarVO.java | 65 - .../vo/dhaddcar/DhAddCarYdParamsVO.java | 56 - .../service/vo/dhcargood/DhCarGoodKeyVO.java | 76 - .../service/vo/dhcargood/DhCarGoodLinkVO.java | 56 - .../vo/dhcarorder/DhAddCarOrderListVO.java | 62 - .../vo/dhcarorder/DhCarOrderParamsVO.java | 59 - .../main/java/me/zhengjie/utils/CacheKey.java | 58 - .../main/java/me/zhengjie/utils/CallBack.java | 43 - .../me/zhengjie/utils/CheckPwdValidator.java | 35 - .../java/me/zhengjie/utils/CloseUtil.java | 47 - .../java/me/zhengjie/utils/CronUtils.java | 49 - .../me/zhengjie/utils/DateTimeValidator.java | 46 - .../main/java/me/zhengjie/utils/DateUtil.java | 555 - .../me/zhengjie/utils/ElAdminConstant.java | 47 - .../zhengjie/utils/EmptyAttributeFiler.java | 76 - .../java/me/zhengjie/utils/EncryptUtils.java | 100 - .../main/java/me/zhengjie/utils/FileUtil.java | 351 - .../main/java/me/zhengjie/utils/HexUtil.java | 51 - .../me/zhengjie/utils/HttpClientUtil.java | 356 - .../zhengjie/utils/HttpConnectionManager.java | 57 - .../main/java/me/zhengjie/utils/IpUtils.java | 380 - .../java/me/zhengjie/utils/JsonDealUtils.java | 54 - .../java/me/zhengjie/utils/LoginIpUtil.java | 88 - .../main/java/me/zhengjie/utils/MD5Util.java | 125 - .../me/zhengjie/utils/NewStringUtils.java | 646 - .../me/zhengjie/utils/OrderGetIndexUtil.java | 63 - .../main/java/me/zhengjie/utils/PageUtil.java | 63 - .../java/me/zhengjie/utils/PageUtils.java | 55 - .../me/zhengjie/utils/PopularizeUtil.java | 49 - .../me/zhengjie/utils/PropertiesUtil.java | 62 - .../java/me/zhengjie/utils/QueryHelp.java | 208 - .../java/me/zhengjie/utils/RedisUtils.java | 903 - .../java/me/zhengjie/utils/RedissonUtil.java | 167 - .../java/me/zhengjie/utils/RequestHolder.java | 50 - .../main/java/me/zhengjie/utils/RsaUtils.java | 202 - .../java/me/zhengjie/utils/SecurityUtils.java | 109 - .../java/me/zhengjie/utils/ServletUtils.java | 184 - .../zhengjie/utils/SpringContextHolder.java | 151 - .../java/me/zhengjie/utils/StringUtil.java | 200 - .../java/me/zhengjie/utils/StringUtils.java | 332 - .../java/me/zhengjie/utils/ThrowableUtil.java | 37 - .../java/me/zhengjie/utils/TransformMap.java | 60 - .../zhengjie/utils/TransformQueryWrapper.java | 165 - .../me/zhengjie/utils/TranslatorUtil.java | 66 - .../me/zhengjie/utils/ValidationUtil.java | 126 - .../me/zhengjie/utils/YdCallBackUtil.java | 89 - .../java/me/zhengjie/utils/YdParamsCheck.java | 54 - .../java/me/zhengjie/utils/YdSignUtil.java | 94 - .../me/zhengjie/utils/enums/CodeBiEnum.java | 50 - .../me/zhengjie/utils/enums/CodeEnum.java | 46 - .../zhengjie/utils/enums/DataScopeEnum.java | 53 - .../utils/enums/RequestMethodEnum.java | 74 - .../zhengjie/utils/excel/ExcelClassField.java | 79 - .../me/zhengjie/utils/excel/ExcelExport.java | 30 - .../me/zhengjie/utils/excel/ExcelImport.java | 34 - .../me/zhengjie/utils/excel/ExcelUtils.java | 993 - .../me/zhengjie/utils/EncryptUtilsTest.java | 32 - .../java/me/zhengjie/utils/FileUtilTest.java | 36 - .../me/zhengjie/utils/StringUtilsTest.java | 66 - wjcy-generator/pom.xml | 39 - .../java/me/zhengjie/domain/ColumnInfo.java | 97 - .../java/me/zhengjie/domain/GenConfig.java | 78 - .../java/me/zhengjie/domain/vo/TableInfo.java | 48 - .../repository/ColumnInfoRepository.java | 34 - .../repository/GenConfigRepository.java | 33 - .../me/zhengjie/rest/GenConfigController.java | 51 - .../me/zhengjie/rest/GeneratorController.java | 107 - .../me/zhengjie/service/GenConfigService.java | 40 - .../me/zhengjie/service/GeneratorService.java | 96 - .../service/impl/GenConfigServiceImpl.java | 67 - .../service/impl/GeneratorServiceImpl.java | 203 - .../main/java/me/zhengjie/utils/ColUtil.java | 54 - .../main/java/me/zhengjie/utils/GenUtil.java | 420 - wjcy-logging/pom.xml | 22 - .../main/java/me/zhengjie/annotation/Log.java | 55 - .../annotation/type/LogActionType.java | 34 - .../zhengjie/annotation/type/LogDaoType.java | 30 - .../annotation/type/LogGetIdType.java | 36 - .../annotation/type/LogGetValueType.java | 32 - .../java/me/zhengjie/aspect/LogAspect.java | 98 - .../src/main/java/me/zhengjie/domain/Log.java | 95 - .../java/me/zhengjie/enums/LogTypeEnum.java | 33 - .../me/zhengjie/repository/LogRepository.java | 49 - .../java/me/zhengjie/rest/LogController.java | 157 - .../java/me/zhengjie/service/LogService.java | 101 - .../me/zhengjie/service/dto/LogErrorDTO.java | 46 - .../service/dto/LogQueryCriteria.java | 42 - .../me/zhengjie/service/dto/LogSmallDTO.java | 40 - .../zhengjie/service/impl/LogServiceImpl.java | 233 - .../service/mapstruct/LogErrorMapper.java | 31 - .../service/mapstruct/LogSmallMapper.java | 31 - wjcy-system/pom.xml | 128 - .../src/main/java/me/zhengjie/AppRun.java | 70 - .../zhengjie/aspect/FormSubmissionAspect.java | 93 - .../me/zhengjie/config/ConfigurerAdapter.java | 88 - .../java/me/zhengjie/config/CorsConfig.java | 20 - .../zhengjie/config/GoogleAuthProperties.java | 58 - .../me/zhengjie/config/WebSocketConfig.java | 33 - .../config/thread/AsyncTaskExecutePool.java | 69 - .../config/thread/AsyncTaskProperties.java | 39 - .../config/thread/TheadFactoryName.java | 63 - .../config/thread/ThreadPoolExecutorUtil.java | 42 - .../me/zhengjie/modules/aspect/LogAspect.java | 154 - .../controller/FileUploadController.java | 51 - .../controller/GoogleAuthController.java | 144 - .../capital/controller/LoginIpController.java | 68 - .../controller/SettingSiteController.java | 140 - .../modules/capital/dto/AddLoginIpDTO.java | 50 - .../modules/capital/dto/EditLoginIpDTO.java | 26 - .../zhengjie/modules/capital/dto/IdDTO.java | 17 - .../capital/dto/RelSettingSiteDTO.java | 27 - .../modules/capital/dto/SettingSiteDTO.java | 33 - .../controller/base/CtApplyController.java | 187 - .../controller/base/CtBrowseController.java | 148 - .../controller/base/CtBuyerController.java | 391 - .../controller/base/CtCardController.java | 307 - .../base/CtClickFarmingController.java | 301 - .../base/CtClickOrderController.java | 330 - .../controller/base/CtCompanyController.java | 187 - .../controller/base/CtDhPayController.java | 300 - .../controller/base/CtExcelController.java | 157 - .../base/CtExcelInfoController.java | 120 - .../controller/base/CtOrderController.java | 165 - .../controller/base/CtPlatformController.java | 136 - .../controller/base/CtRebotController.java | 215 - .../controller/base/CtVpnController.java | 261 - .../base/DhAddCarCatchController.java | 409 - .../controller/base/DhAddCarController.java | 466 - .../base/DhAddCarOrderController.java | 57 - .../controller/base/QuartzLogController.java | 55 - .../group/controller/base/SdsController.java | 320 - .../base/SysQuartzJobController.java | 206 - .../controller/base/YdCallBackController.java | 122 - .../callbcak/BossTaskCallBackController.java | 84 - .../ClickFarmingCallBackController.java | 432 - ...ckFarmingSuppleMentCallBackController.java | 234 - .../ClickOrderCallBackController.java | 151 - .../callbcak/CtbrowseCallBackController.java | 148 - .../callbcak/DhAddCarCallBackController.java | 152 - .../DhCarOrderCallBackController.java | 170 - .../DhCatchOrderCallBackController.java | 166 - .../modules/group/dto/CtApplyAddDTO.java | 57 - .../modules/group/dto/CtApplyListDTO.java | 43 - .../modules/group/dto/CtApplyUpdateDTO.java | 54 - .../modules/group/dto/CtBrowseAddDTO.java | 33 - .../modules/group/dto/CtBrowseListDTO.java | 57 - .../modules/group/dto/CtBrowseUpdateDTO.java | 46 - .../modules/group/dto/CtBuyerAddDTO.java | 135 - .../modules/group/dto/CtBuyerListDTO.java | 57 - .../modules/group/dto/CtBuyerUpdateDTO.java | 122 - .../modules/group/dto/CtCardAddDTO.java | 105 - .../modules/group/dto/CtCardListDTO.java | 62 - .../modules/group/dto/CtCardUpdateDTO.java | 75 - .../group/dto/CtClickFarmingAddDTO.java | 83 - .../modules/group/dto/CtClickFarmingDTO.java | 87 - .../group/dto/CtClickFarmingEditDTO.java | 84 - .../modules/group/dto/CtClickOrderAddDto.java | 71 - .../group/dto/CtClickOrderCommentDto.java | 34 - .../group/dto/CtClickOrderListDTO.java | 69 - .../group/dto/CtClickOrderSupplementDto.java | 58 - .../modules/group/dto/CtCompanyAddDTO.java | 29 - .../modules/group/dto/CtCompanyListDTO.java | 47 - .../modules/group/dto/CtCompanyUpdateDTO.java | 30 - .../modules/group/dto/CtDhPayAddDTO.java | 30 - .../modules/group/dto/CtDhPayListDTO.java | 39 - .../modules/group/dto/CtExcelAddDTO.java | 27 - .../group/dto/CtExcelImportInfoListDTO.java | 41 - .../modules/group/dto/CtExcelListDTO.java | 40 - .../modules/group/dto/CtExcelUpdateDTO.java | 27 - .../modules/group/dto/CtOrderListDTO.java | 42 - .../modules/group/dto/CtPlatformAddDTO.java | 25 - .../modules/group/dto/CtPlatformListDTO.java | 39 - .../group/dto/CtPlatformUpdateDTO.java | 31 - .../modules/group/dto/CtRebotAddDTO.java | 26 - .../modules/group/dto/CtRebotListDTO.java | 42 - .../modules/group/dto/CtRebotUpdateDTO.java | 33 - .../group/dto/CtRebotUpdateStatusDTO.java | 24 - .../modules/group/dto/CtVpnAddDTO.java | 50 - .../modules/group/dto/CtVpnListDTO.java | 59 - .../modules/group/dto/CtVpnUpdateDTO.java | 43 - .../group/dto/DhCarGoodWellReceivedDTO.java | 30 - .../group/dto/DhCarWellReceivedDTO.java | 29 - .../me/zhengjie/modules/group/dto/IdDTO.java | 22 - .../modules/group/dto/SearchOrderListDTO.java | 69 - .../modules/group/dto/SysQuartzJobAddDTO.java | 54 - .../group/dto/SysQuartzJobListDTO.java | 43 - .../group/dto/SysQuartzJobUpdateDTO.java | 49 - .../group/dto/SysQuartzLogListDTO.java | 42 - .../group/dto/dhaddcar/DhAddCarAddDTO.java | 46 - .../group/dto/dhaddcar/DhAddCarEditDTO.java | 48 - .../group/dto/dhaddcar/DhAddCarListDTO.java | 73 - .../dto/dhcargood/DhCarGoodKeyAddDTO.java | 70 - .../dto/dhcargood/DhCarGoodKeyEditDTO.java | 74 - .../dto/dhcargood/DhCarGoodLinkAddDTO.java | 49 - .../dto/dhcargood/DhCarGoodLinkEditDTO.java | 53 - .../dto/dhcarorder/DhAddCarOrderListDTO.java | 66 - .../me/zhengjie/modules/mnt/domain/App.java | 67 - .../zhengjie/modules/mnt/domain/Database.java | 57 - .../zhengjie/modules/mnt/domain/Deploy.java | 59 - .../modules/mnt/domain/DeployHistory.java | 62 - .../modules/mnt/domain/ServerDeploy.java | 80 - .../modules/mnt/repository/AppRepository.java | 27 - .../mnt/repository/DatabaseRepository.java | 27 - .../repository/DeployHistoryRepository.java | 27 - .../mnt/repository/DeployRepository.java | 27 - .../repository/ServerDeployRepository.java | 34 - .../modules/mnt/rest/AppController.java | 87 - .../modules/mnt/rest/DatabaseController.java | 123 - .../modules/mnt/rest/DeployController.java | 153 - .../mnt/rest/DeployHistoryController.java | 67 - .../mnt/rest/ServerDeployController.java | 95 - .../modules/mnt/service/AppService.java | 81 - .../modules/mnt/service/DatabaseService.java | 88 - .../mnt/service/DeployHistoryService.java | 74 - .../modules/mnt/service/DeployService.java | 116 - .../mnt/service/ServerDeployService.java | 95 - .../modules/mnt/service/dto/AppDto.java | 71 - .../mnt/service/dto/AppQueryCriteria.java | 38 - .../modules/mnt/service/dto/DatabaseDto.java | 55 - .../service/dto/DatabaseQueryCriteria.java | 44 - .../modules/mnt/service/dto/DeployDto.java | 78 - .../mnt/service/dto/DeployHistoryDto.java | 58 - .../dto/DeployHistoryQueryCriteria.java | 41 - .../mnt/service/dto/DeployQueryCriteria.java | 39 - .../mnt/service/dto/ServerDeployDto.java | 61 - .../dto/ServerDeployQueryCriteria.java | 38 - .../mnt/service/impl/AppServiceImpl.java | 123 - .../mnt/service/impl/DatabaseServiceImpl.java | 117 - .../impl/DeployHistoryServiceImpl.java | 96 - .../mnt/service/impl/DeployServiceImpl.java | 430 - .../service/impl/ServerDeployServiceImpl.java | 125 - .../mnt/service/mapstruct/AppMapper.java | 31 - .../mnt/service/mapstruct/DatabaseMapper.java | 31 - .../mapstruct/DeployHistoryMapper.java | 31 - .../mnt/service/mapstruct/DeployMapper.java | 31 - .../service/mapstruct/ServerDeployMapper.java | 31 - .../modules/mnt/util/DataTypeEnum.java | 140 - .../modules/mnt/util/ExecuteShellUtil.java | 101 - .../modules/mnt/util/ScpClientUtil.java | 105 - .../zhengjie/modules/mnt/util/SqlUtils.java | 201 - .../modules/mnt/websocket/MsgType.java | 31 - .../modules/mnt/websocket/SocketMsg.java | 33 - .../mnt/websocket/WebSocketServer.java | 139 - .../modules/quartz/config/JobRunner.java | 54 - .../modules/quartz/config/QuartzConfig.java | 52 - .../modules/quartz/domain/QuartzJob.java | 92 - .../modules/quartz/domain/QuartzLog.java | 70 - .../repository/QuartzJobRepository.java | 34 - .../repository/QuartzLogRepository.java | 28 - .../quartz/rest/QuartzJobController.java | 127 - .../quartz/service/QuartzJobService.java | 128 - .../quartz/service/SysQuartzJobService.java | 77 - .../quartz/service/dto/JobQueryCriteria.java | 41 - .../service/impl/QuartzJobServiceImpl.java | 205 - .../service/impl/SysQuartzJobServiceImpl.java | 521 - .../modules/quartz/task/BossTask.java | 51 - .../modules/quartz/task/BossTask22.java | 165 - .../modules/quartz/task/BrowseTask.java | 54 - .../quartz/task/ClickFarmSuppleMentTask.java | 54 - .../modules/quartz/task/ClickFarmTask.java | 54 - .../modules/quartz/task/DhAddCarTask.java | 54 - .../modules/quartz/task/DhCatchOrderTask.java | 54 - .../modules/quartz/task/DhPayTask.java | 47 - .../quartz/task/DhWellReceivedTask.java | 54 - .../modules/quartz/task/ExcelToOrderTask.java | 46 - .../modules/quartz/task/ExcelmportTask.java | 46 - .../modules/quartz/task/OrderToPayTask.java | 46 - .../modules/quartz/task/RebotStatusTask.java | 95 - .../modules/quartz/task/TestTask.java | 49 - .../modules/quartz/task/WellReceivedTask.java | 55 - .../modules/quartz/utils/ExecutionJob.java | 140 - .../modules/quartz/utils/QuartzManage.java | 174 - .../modules/quartz/utils/QuartzRunnable.java | 58 - .../modules/quartz/utils/YdApiUtil.java | 31 - .../config/ConfigBeanConfiguration.java | 43 - .../security/config/SecurityConfig.java | 207 - .../security/config/bean/LoginCode.java | 61 - .../security/config/bean/LoginCodeEnum.java | 43 - .../security/config/bean/LoginProperties.java | 135 - .../config/bean/SecurityProperties.java | 72 - .../rest/AuthorizationController.java | 201 - .../security/rest/OnlineController.java | 68 - .../security/JwtAccessDeniedHandler.java | 37 - .../security/JwtAuthenticationEntryPoint.java | 39 - .../security/security/TokenConfigurer.java | 45 - .../security/security/TokenFilter.java | 111 - .../security/security/TokenProvider.java | 123 - .../security/service/OnlineUserService.java | 191 - .../security/service/UserCacheClean.java | 49 - .../service/UserDetailsServiceImpl.java | 94 - .../security/service/dto/AuthUserDto.java | 39 - .../security/service/dto/JwtUserDto.java | 82 - .../security/service/dto/OnlineUserDto.java | 73 - .../zhengjie/modules/system/domain/Dept.java | 86 - .../zhengjie/modules/system/domain/Dict.java | 54 - .../modules/system/domain/DictDetail.java | 56 - .../zhengjie/modules/system/domain/Job.java | 73 - .../zhengjie/modules/system/domain/Menu.java | 110 - .../zhengjie/modules/system/domain/Role.java | 99 - .../zhengjie/modules/system/domain/User.java | 129 - .../modules/system/domain/vo/MenuMetaVo.java | 35 - .../modules/system/domain/vo/MenuVo.java | 47 - .../modules/system/domain/vo/UserPassVo.java | 37 - .../system/repository/DeptRepository.java | 69 - .../repository/DictDetailRepository.java | 36 - .../system/repository/DictRepository.java | 43 - .../system/repository/JobRepository.java | 42 - .../system/repository/MenuRepository.java | 85 - .../system/repository/RoleRepository.java | 80 - .../system/repository/UserRepository.java | 130 - .../modules/system/rest/DeptController.java | 117 - .../modules/system/rest/DictController.java | 99 - .../system/rest/DictDetailController.java | 99 - .../modules/system/rest/JobController.java | 94 - .../modules/system/rest/LimitController.java | 47 - .../modules/system/rest/MenuController.java | 147 - .../system/rest/MonitorController.java | 45 - .../modules/system/rest/RoleController.java | 154 - .../modules/system/rest/UserController.java | 230 - .../modules/system/rest/VerifyController.java | 76 - .../modules/system/service/DataService.java | 34 - .../modules/system/service/DeptService.java | 124 - .../system/service/DictDetailService.java | 63 - .../modules/system/service/DictService.java | 75 - .../modules/system/service/JobService.java | 93 - .../modules/system/service/MenuService.java | 125 - .../system/service/MonitorService.java | 31 - .../modules/system/service/RoleService.java | 136 - .../modules/system/service/UserService.java | 116 - .../modules/system/service/VerifyService.java | 41 - .../modules/system/service/dto/DeptDto.java | 78 - .../system/service/dto/DeptQueryCriteria.java | 46 - .../system/service/dto/DeptSmallDto.java | 31 - .../system/service/dto/DictDetailDto.java | 40 - .../service/dto/DictDetailQueryCriteria.java | 33 - .../modules/system/service/dto/DictDto.java | 39 - .../system/service/dto/DictQueryCriteria.java | 30 - .../system/service/dto/DictSmallDto.java | 31 - .../system/service/dto/GoogleAuthCodeDTO.java | 27 - .../service/dto/GoogleAuthGenSecretDTO.java | 23 - .../dto/GoogleAuthQrBarCodeUrlDTO.java | 23 - .../modules/system/service/dto/JobDto.java | 46 - .../system/service/dto/JobQueryCriteria.java | 40 - .../system/service/dto/JobSmallDto.java | 33 - .../modules/system/service/dto/MenuDto.java | 91 - .../system/service/dto/MenuQueryCriteria.java | 41 - .../modules/system/service/dto/RoleDto.java | 63 - .../system/service/dto/RoleQueryCriteria.java | 36 - .../system/service/dto/RoleSmallDto.java | 35 - .../service/dto/UpdateGoogleAuthDTO.java | 27 - .../modules/system/service/dto/UserDto.java | 67 - .../system/service/dto/UserQueryCriteria.java | 49 - .../system/service/impl/DataServiceImpl.java | 91 - .../system/service/impl/DeptServiceImpl.java | 283 - .../service/impl/DictDetailServiceImpl.java | 95 - .../system/service/impl/DictServiceImpl.java | 121 - .../system/service/impl/JobServiceImpl.java | 132 - .../system/service/impl/MenuServiceImpl.java | 355 - .../service/impl/MonitorServiceImpl.java | 187 - .../system/service/impl/RoleServiceImpl.java | 226 - .../system/service/impl/UserServiceImpl.java | 282 - .../service/impl/VerifyServiceImpl.java | 81 - .../system/service/mapstruct/DeptMapper.java | 30 - .../service/mapstruct/DeptSmallMapper.java | 31 - .../service/mapstruct/DictDetailMapper.java | 31 - .../system/service/mapstruct/DictMapper.java | 31 - .../service/mapstruct/DictSmallMapper.java | 31 - .../system/service/mapstruct/JobMapper.java | 30 - .../service/mapstruct/JobSmallMapper.java | 31 - .../system/service/mapstruct/MenuMapper.java | 30 - .../system/service/mapstruct/RoleMapper.java | 31 - .../service/mapstruct/RoleSmallMapper.java | 31 - .../system/service/mapstruct/UserMapper.java | 30 - .../utils/GoogleAuthenticatorUtil.java | 179 - wjcy-system/src/main/resources/banner.txt | 8 - .../main/resources/config/application-dev.yml | 285 - .../resources/config/application-local.yml | 411 - .../resources/config/application-prod.yml | 250 - .../main/resources/config/application-xxs.yml | 417 - .../src/main/resources/config/application.yml | 56 - .../src/main/resources/generator.properties | 27 - .../src/main/resources/ip2region/ip2region.db | Bin 6502265 -> 0 bytes wjcy-system/src/main/resources/log4j2.xml | 252 - .../main/resources/log4jdbc.log4j2.properties | 5 - .../main/resources/template/email/email.ftl | 48 - .../resources/template/email/taskAlarm.ftl | 69 - .../template/generator/admin/Controller.ftl | 87 - .../template/generator/admin/Dto.ftl | 54 - .../template/generator/admin/Entity.ftl | 85 - .../template/generator/admin/Mapper.ftl | 32 - .../generator/admin/QueryCriteria.ftl | 81 - .../template/generator/admin/Repository.ftl | 40 - .../template/generator/admin/Service.ftl | 83 - .../template/generator/admin/ServiceImpl.ftl | 157 - .../template/generator/front/api.ftl | 27 - .../template/generator/front/index.ftl | 169 - .../src/main/resources/templates/index.html | 244 - .../me/zhengjie/CtBuyerControllerTest.java | 127 - .../me/zhengjie/CtPlatformControllerTest.java | 43 - .../src/test/java/me/zhengjie/DhApiTest.java | 461 - .../test/java/me/zhengjie/ExcelUserTest.java | 21 - .../me/zhengjie/SettingSiteServiceTest.java | 48 - .../java/me/zhengjie/TransactionSignDemo.java | 8 - wjcy-tools/pom.xml | 57 - .../me/zhengjie/config/MultipartConfig.java | 47 - .../java/me/zhengjie/domain/AlipayConfig.java | 76 - .../java/me/zhengjie/domain/EmailConfig.java | 58 - .../java/me/zhengjie/domain/LocalStorage.java | 73 - .../java/me/zhengjie/domain/QiniuConfig.java | 69 - .../java/me/zhengjie/domain/QiniuContent.java | 64 - .../java/me/zhengjie/domain/vo/EmailVo.java | 44 - .../java/me/zhengjie/domain/vo/TradeVo.java | 63 - .../zhengjie/repository/AliPayRepository.java | 26 - .../zhengjie/repository/EmailRepository.java | 26 - .../repository/LocalStorageRepository.java | 27 - .../repository/QiNiuConfigRepository.java | 36 - .../repository/QiniuContentRepository.java | 34 - .../me/zhengjie/rest/AliPayController.java | 135 - .../me/zhengjie/rest/EmailController.java | 63 - .../zhengjie/rest/LocalStorageController.java | 98 - .../me/zhengjie/rest/QiniuController.java | 122 - .../me/zhengjie/service/AliPayService.java | 57 - .../me/zhengjie/service/EmailService.java | 49 - .../zhengjie/service/LocalStorageService.java | 82 - .../me/zhengjie/service/QiNiuService.java | 118 - .../zhengjie/service/dto/LocalStorageDto.java | 42 - .../dto/LocalStorageQueryCriteria.java | 36 - .../service/dto/PictureQueryCriteria.java | 40 - .../service/dto/QiniuQueryCriteria.java | 36 - .../service/impl/AliPayServiceImpl.java | 119 - .../service/impl/EmailServiceImpl.java | 105 - .../service/impl/LocalStorageServiceImpl.java | 133 - .../service/impl/QiNiuServiceImpl.java | 237 - .../service/mapstruct/LocalStorageMapper.java | 31 - .../me/zhengjie/utils/AliPayStatusEnum.java | 46 - .../java/me/zhengjie/utils/AlipayUtils.java | 85 - .../java/me/zhengjie/utils/QiNiuUtil.java | 71 - .../java/me/zhengjie/utils/RSACoderUtil.java | 234 - 1350 files changed, 82975 insertions(+), 58110 deletions(-) create mode 100644 bin/clean.bat create mode 100644 bin/package.bat create mode 100644 bin/run.bat create mode 100644 custom-ui/.editorconfig create mode 100644 custom-ui/.env.development create mode 100644 custom-ui/.env.production create mode 100644 custom-ui/.env.staging create mode 100644 custom-ui/.eslintignore create mode 100644 custom-ui/.eslintrc.js create mode 100644 custom-ui/README.md create mode 100644 custom-ui/babel.config.js create mode 100644 custom-ui/bin/build.bat create mode 100644 custom-ui/bin/package.bat create mode 100644 custom-ui/bin/run-web.bat create mode 100644 custom-ui/build/index.js create mode 100644 custom-ui/package-lock.json create mode 100644 custom-ui/package.json create mode 100644 custom-ui/public/favicon.ico create mode 100644 custom-ui/public/html/ie.html create mode 100644 custom-ui/public/index.html create mode 100644 custom-ui/public/robots.txt create mode 100644 custom-ui/src/App.vue create mode 100644 custom-ui/src/api/business/survey.js create mode 100644 custom-ui/src/api/business/template.js create mode 100644 custom-ui/src/api/business/templateProp.js create mode 100644 custom-ui/src/api/business/templatePropValue.js create mode 100644 custom-ui/src/api/login.js create mode 100644 custom-ui/src/api/menu.js create mode 100644 custom-ui/src/api/monitor/cache.js create mode 100644 custom-ui/src/api/monitor/job.js create mode 100644 custom-ui/src/api/monitor/jobLog.js create mode 100644 custom-ui/src/api/monitor/logininfor.js create mode 100644 custom-ui/src/api/monitor/online.js create mode 100644 custom-ui/src/api/monitor/operlog.js create mode 100644 custom-ui/src/api/monitor/server.js create mode 100644 custom-ui/src/api/system/config.js create mode 100644 custom-ui/src/api/system/dept.js create mode 100644 custom-ui/src/api/system/dict/data.js create mode 100644 custom-ui/src/api/system/dict/type.js create mode 100644 custom-ui/src/api/system/menu.js create mode 100644 custom-ui/src/api/system/notice.js create mode 100644 custom-ui/src/api/system/post.js create mode 100644 custom-ui/src/api/system/role.js create mode 100644 custom-ui/src/api/system/user.js create mode 100644 custom-ui/src/api/tool/gen.js create mode 100644 custom-ui/src/assets/401_images/401.gif create mode 100644 custom-ui/src/assets/404_images/404.png create mode 100644 custom-ui/src/assets/404_images/404_cloud.png create mode 100644 custom-ui/src/assets/icons/index.js create mode 100644 custom-ui/src/assets/icons/svg/404.svg create mode 100644 custom-ui/src/assets/icons/svg/bug.svg create mode 100644 custom-ui/src/assets/icons/svg/build.svg create mode 100644 custom-ui/src/assets/icons/svg/button.svg create mode 100644 custom-ui/src/assets/icons/svg/cascader.svg create mode 100644 custom-ui/src/assets/icons/svg/chart.svg create mode 100644 custom-ui/src/assets/icons/svg/checkbox.svg create mode 100644 custom-ui/src/assets/icons/svg/clipboard.svg create mode 100644 custom-ui/src/assets/icons/svg/code.svg create mode 100644 custom-ui/src/assets/icons/svg/color.svg create mode 100644 custom-ui/src/assets/icons/svg/component.svg create mode 100644 custom-ui/src/assets/icons/svg/dashboard.svg create mode 100644 custom-ui/src/assets/icons/svg/date-range.svg create mode 100644 custom-ui/src/assets/icons/svg/date.svg create mode 100644 custom-ui/src/assets/icons/svg/dict.svg create mode 100644 custom-ui/src/assets/icons/svg/documentation.svg create mode 100644 custom-ui/src/assets/icons/svg/download.svg create mode 100644 custom-ui/src/assets/icons/svg/drag.svg create mode 100644 custom-ui/src/assets/icons/svg/druid.svg create mode 100644 custom-ui/src/assets/icons/svg/edit.svg create mode 100644 custom-ui/src/assets/icons/svg/education.svg create mode 100644 custom-ui/src/assets/icons/svg/email.svg create mode 100644 custom-ui/src/assets/icons/svg/example.svg create mode 100644 custom-ui/src/assets/icons/svg/excel.svg create mode 100644 custom-ui/src/assets/icons/svg/exit-fullscreen.svg create mode 100644 custom-ui/src/assets/icons/svg/eye-open.svg create mode 100644 custom-ui/src/assets/icons/svg/eye.svg create mode 100644 custom-ui/src/assets/icons/svg/form.svg create mode 100644 custom-ui/src/assets/icons/svg/fullscreen.svg create mode 100644 custom-ui/src/assets/icons/svg/github.svg create mode 100644 custom-ui/src/assets/icons/svg/guide.svg create mode 100644 custom-ui/src/assets/icons/svg/icon.svg create mode 100644 custom-ui/src/assets/icons/svg/input.svg create mode 100644 custom-ui/src/assets/icons/svg/international.svg create mode 100644 custom-ui/src/assets/icons/svg/job.svg create mode 100644 custom-ui/src/assets/icons/svg/language.svg create mode 100644 custom-ui/src/assets/icons/svg/link.svg create mode 100644 custom-ui/src/assets/icons/svg/list.svg create mode 100644 custom-ui/src/assets/icons/svg/lock.svg create mode 100644 custom-ui/src/assets/icons/svg/log.svg create mode 100644 custom-ui/src/assets/icons/svg/logininfor.svg create mode 100644 custom-ui/src/assets/icons/svg/message.svg create mode 100644 custom-ui/src/assets/icons/svg/money.svg create mode 100644 custom-ui/src/assets/icons/svg/monitor.svg create mode 100644 custom-ui/src/assets/icons/svg/nested.svg create mode 100644 custom-ui/src/assets/icons/svg/number.svg create mode 100644 custom-ui/src/assets/icons/svg/online.svg create mode 100644 custom-ui/src/assets/icons/svg/password.svg create mode 100644 custom-ui/src/assets/icons/svg/pdf.svg create mode 100644 custom-ui/src/assets/icons/svg/people.svg create mode 100644 custom-ui/src/assets/icons/svg/peoples.svg create mode 100644 custom-ui/src/assets/icons/svg/phone.svg create mode 100644 custom-ui/src/assets/icons/svg/post.svg create mode 100644 custom-ui/src/assets/icons/svg/qq.svg create mode 100644 custom-ui/src/assets/icons/svg/question.svg create mode 100644 custom-ui/src/assets/icons/svg/radio.svg create mode 100644 custom-ui/src/assets/icons/svg/rate.svg create mode 100644 custom-ui/src/assets/icons/svg/redis-list.svg create mode 100644 custom-ui/src/assets/icons/svg/redis.svg create mode 100644 custom-ui/src/assets/icons/svg/row.svg create mode 100644 custom-ui/src/assets/icons/svg/search.svg create mode 100644 custom-ui/src/assets/icons/svg/select.svg create mode 100644 custom-ui/src/assets/icons/svg/server.svg create mode 100644 custom-ui/src/assets/icons/svg/shopping.svg create mode 100644 custom-ui/src/assets/icons/svg/size.svg create mode 100644 custom-ui/src/assets/icons/svg/skill.svg create mode 100644 custom-ui/src/assets/icons/svg/slider.svg create mode 100644 custom-ui/src/assets/icons/svg/star.svg create mode 100644 custom-ui/src/assets/icons/svg/swagger.svg create mode 100644 custom-ui/src/assets/icons/svg/switch.svg create mode 100644 custom-ui/src/assets/icons/svg/system.svg create mode 100644 custom-ui/src/assets/icons/svg/tab.svg create mode 100644 custom-ui/src/assets/icons/svg/table.svg create mode 100644 custom-ui/src/assets/icons/svg/textarea.svg create mode 100644 custom-ui/src/assets/icons/svg/theme.svg create mode 100644 custom-ui/src/assets/icons/svg/time-range.svg create mode 100644 custom-ui/src/assets/icons/svg/time.svg create mode 100644 custom-ui/src/assets/icons/svg/tool.svg create mode 100644 custom-ui/src/assets/icons/svg/tree-table.svg create mode 100644 custom-ui/src/assets/icons/svg/tree.svg create mode 100644 custom-ui/src/assets/icons/svg/upload.svg create mode 100644 custom-ui/src/assets/icons/svg/user.svg create mode 100644 custom-ui/src/assets/icons/svg/validCode.svg create mode 100644 custom-ui/src/assets/icons/svg/wechat.svg create mode 100644 custom-ui/src/assets/icons/svg/zip.svg create mode 100644 custom-ui/src/assets/icons/svgo.yml create mode 100644 custom-ui/src/assets/images/dark.svg create mode 100644 custom-ui/src/assets/images/light.svg create mode 100644 custom-ui/src/assets/images/login-background.jpg create mode 100644 custom-ui/src/assets/images/profile.jpg create mode 100644 custom-ui/src/assets/logo/logo.png create mode 100644 custom-ui/src/assets/styles/btn.scss create mode 100644 custom-ui/src/assets/styles/element-ui.scss create mode 100644 custom-ui/src/assets/styles/element-variables.scss create mode 100644 custom-ui/src/assets/styles/index.scss create mode 100644 custom-ui/src/assets/styles/mixin.scss create mode 100644 custom-ui/src/assets/styles/ruoyi.scss create mode 100644 custom-ui/src/assets/styles/sidebar.scss create mode 100644 custom-ui/src/assets/styles/transition.scss create mode 100644 custom-ui/src/assets/styles/variables.scss create mode 100644 custom-ui/src/components/Breadcrumb/index.vue create mode 100644 custom-ui/src/components/Crontab/day.vue create mode 100644 custom-ui/src/components/Crontab/hour.vue create mode 100644 custom-ui/src/components/Crontab/index.vue create mode 100644 custom-ui/src/components/Crontab/min.vue create mode 100644 custom-ui/src/components/Crontab/month.vue create mode 100644 custom-ui/src/components/Crontab/result.vue create mode 100644 custom-ui/src/components/Crontab/second.vue create mode 100644 custom-ui/src/components/Crontab/week.vue create mode 100644 custom-ui/src/components/Crontab/year.vue create mode 100644 custom-ui/src/components/DictData/index.js create mode 100644 custom-ui/src/components/DictTag/index.vue create mode 100644 custom-ui/src/components/Editor/index.vue create mode 100644 custom-ui/src/components/FileUpload/index.vue create mode 100644 custom-ui/src/components/Hamburger/index.vue create mode 100644 custom-ui/src/components/HeaderSearch/index.vue create mode 100644 custom-ui/src/components/IconSelect/index.vue create mode 100644 custom-ui/src/components/IconSelect/requireIcons.js create mode 100644 custom-ui/src/components/ImagePreview/index.vue create mode 100644 custom-ui/src/components/ImageUpload/index.vue create mode 100644 custom-ui/src/components/Pagination/index.vue create mode 100644 custom-ui/src/components/PanThumb/index.vue create mode 100644 custom-ui/src/components/ParentView/index.vue create mode 100644 custom-ui/src/components/RightPanel/index.vue create mode 100644 custom-ui/src/components/RightToolbar/index.vue create mode 100644 custom-ui/src/components/RuoYi/Doc/index.vue create mode 100644 custom-ui/src/components/RuoYi/Git/index.vue create mode 100644 custom-ui/src/components/Screenfull/index.vue create mode 100644 custom-ui/src/components/SizeSelect/index.vue create mode 100644 custom-ui/src/components/SvgIcon/index.vue create mode 100644 custom-ui/src/components/ThemePicker/index.vue create mode 100644 custom-ui/src/components/TopNav/index.vue create mode 100644 custom-ui/src/components/iFrame/index.vue create mode 100644 custom-ui/src/directive/dialog/drag.js create mode 100644 custom-ui/src/directive/dialog/dragHeight.js create mode 100644 custom-ui/src/directive/dialog/dragWidth.js create mode 100644 custom-ui/src/directive/index.js create mode 100644 custom-ui/src/directive/module/clipboard.js create mode 100644 custom-ui/src/directive/permission/hasPermi.js create mode 100644 custom-ui/src/directive/permission/hasRole.js create mode 100644 custom-ui/src/layout/components/AppMain.vue create mode 100644 custom-ui/src/layout/components/IframeToggle/index.vue create mode 100644 custom-ui/src/layout/components/InnerLink/index.vue create mode 100644 custom-ui/src/layout/components/Navbar.vue create mode 100644 custom-ui/src/layout/components/Settings/index.vue create mode 100644 custom-ui/src/layout/components/Sidebar/FixiOSBug.js create mode 100644 custom-ui/src/layout/components/Sidebar/Item.vue create mode 100644 custom-ui/src/layout/components/Sidebar/Link.vue create mode 100644 custom-ui/src/layout/components/Sidebar/Logo.vue create mode 100644 custom-ui/src/layout/components/Sidebar/SidebarItem.vue create mode 100644 custom-ui/src/layout/components/Sidebar/index.vue create mode 100644 custom-ui/src/layout/components/TagsView/ScrollPane.vue create mode 100644 custom-ui/src/layout/components/TagsView/index.vue create mode 100644 custom-ui/src/layout/components/index.js create mode 100644 custom-ui/src/layout/index.vue create mode 100644 custom-ui/src/layout/mixin/ResizeHandler.js create mode 100644 custom-ui/src/main.js create mode 100644 custom-ui/src/permission.js create mode 100644 custom-ui/src/plugins/auth.js create mode 100644 custom-ui/src/plugins/cache.js create mode 100644 custom-ui/src/plugins/download.js create mode 100644 custom-ui/src/plugins/index.js create mode 100644 custom-ui/src/plugins/modal.js create mode 100644 custom-ui/src/plugins/tab.js create mode 100644 custom-ui/src/router/index.js create mode 100644 custom-ui/src/settings.js create mode 100644 custom-ui/src/store/getters.js create mode 100644 custom-ui/src/store/index.js create mode 100644 custom-ui/src/store/modules/app.js create mode 100644 custom-ui/src/store/modules/dict.js create mode 100644 custom-ui/src/store/modules/permission.js create mode 100644 custom-ui/src/store/modules/settings.js create mode 100644 custom-ui/src/store/modules/tagsView.js create mode 100644 custom-ui/src/store/modules/user.js create mode 100644 custom-ui/src/utils/auth.js create mode 100644 custom-ui/src/utils/dict/Dict.js create mode 100644 custom-ui/src/utils/dict/DictConverter.js create mode 100644 custom-ui/src/utils/dict/DictData.js create mode 100644 custom-ui/src/utils/dict/DictMeta.js create mode 100644 custom-ui/src/utils/dict/DictOptions.js create mode 100644 custom-ui/src/utils/dict/index.js create mode 100644 custom-ui/src/utils/errorCode.js create mode 100644 custom-ui/src/utils/generator/config.js create mode 100644 custom-ui/src/utils/generator/css.js create mode 100644 custom-ui/src/utils/generator/drawingDefault.js create mode 100644 custom-ui/src/utils/generator/html.js create mode 100644 custom-ui/src/utils/generator/icon.json create mode 100644 custom-ui/src/utils/generator/js.js create mode 100644 custom-ui/src/utils/generator/render.js create mode 100644 custom-ui/src/utils/index.js create mode 100644 custom-ui/src/utils/jsencrypt.js create mode 100644 custom-ui/src/utils/permission.js create mode 100644 custom-ui/src/utils/request.js create mode 100644 custom-ui/src/utils/ruoyi.js create mode 100644 custom-ui/src/utils/scroll-to.js create mode 100644 custom-ui/src/utils/validate.js create mode 100644 custom-ui/src/views/business/countGroup/index.vue create mode 100644 custom-ui/src/views/business/survey/index.vue create mode 100644 custom-ui/src/views/business/surveySubmit/index.vue create mode 100644 custom-ui/src/views/business/template/index.vue create mode 100644 custom-ui/src/views/business/templateProp/index.vue create mode 100644 custom-ui/src/views/business/templatePropValue/index.vue create mode 100644 custom-ui/src/views/components/icons/element-icons.js create mode 100644 custom-ui/src/views/components/icons/index.vue create mode 100644 custom-ui/src/views/components/icons/svg-icons.js create mode 100644 custom-ui/src/views/dashboard/BarChart.vue create mode 100644 custom-ui/src/views/dashboard/LineChart.vue create mode 100644 custom-ui/src/views/dashboard/PanelGroup.vue create mode 100644 custom-ui/src/views/dashboard/PieChart.vue create mode 100644 custom-ui/src/views/dashboard/RaddarChart.vue create mode 100644 custom-ui/src/views/dashboard/mixins/resize.js create mode 100644 custom-ui/src/views/error/401.vue create mode 100644 custom-ui/src/views/error/404.vue create mode 100644 custom-ui/src/views/index.vue create mode 100644 custom-ui/src/views/index_v1.vue create mode 100644 custom-ui/src/views/login.vue create mode 100644 custom-ui/src/views/monitor/cache/index.vue create mode 100644 custom-ui/src/views/monitor/cache/list.vue create mode 100644 custom-ui/src/views/monitor/druid/index.vue create mode 100644 custom-ui/src/views/monitor/job/index.vue create mode 100644 custom-ui/src/views/monitor/job/log.vue create mode 100644 custom-ui/src/views/monitor/logininfor/index.vue create mode 100644 custom-ui/src/views/monitor/online/index.vue create mode 100644 custom-ui/src/views/monitor/operlog/index.vue create mode 100644 custom-ui/src/views/monitor/server/index.vue create mode 100644 custom-ui/src/views/redirect.vue create mode 100644 custom-ui/src/views/register.vue create mode 100644 custom-ui/src/views/system/config/index.vue create mode 100644 custom-ui/src/views/system/dept/index.vue create mode 100644 custom-ui/src/views/system/dict/data.vue create mode 100644 custom-ui/src/views/system/dict/index.vue create mode 100644 custom-ui/src/views/system/menu/index.vue create mode 100644 custom-ui/src/views/system/notice/index.vue create mode 100644 custom-ui/src/views/system/post/index.vue create mode 100644 custom-ui/src/views/system/role/authUser.vue create mode 100644 custom-ui/src/views/system/role/index.vue create mode 100644 custom-ui/src/views/system/role/selectUser.vue create mode 100644 custom-ui/src/views/system/user/authRole.vue create mode 100644 custom-ui/src/views/system/user/index.vue create mode 100644 custom-ui/src/views/system/user/profile/index.vue create mode 100644 custom-ui/src/views/system/user/profile/resetPwd.vue create mode 100644 custom-ui/src/views/system/user/profile/userAvatar.vue create mode 100644 custom-ui/src/views/system/user/profile/userInfo.vue create mode 100644 custom-ui/src/views/tool/build/CodeTypeDialog.vue create mode 100644 custom-ui/src/views/tool/build/DraggableItem.vue create mode 100644 custom-ui/src/views/tool/build/IconsDialog.vue create mode 100644 custom-ui/src/views/tool/build/RightPanel.vue create mode 100644 custom-ui/src/views/tool/build/TreeNodeDialog.vue create mode 100644 custom-ui/src/views/tool/build/index.vue create mode 100644 custom-ui/src/views/tool/gen/basicInfoForm.vue create mode 100644 custom-ui/src/views/tool/gen/editTable.vue create mode 100644 custom-ui/src/views/tool/gen/genInfoForm.vue create mode 100644 custom-ui/src/views/tool/gen/importTable.vue create mode 100644 custom-ui/src/views/tool/gen/index.vue create mode 100644 custom-ui/src/views/tool/swagger/index.vue create mode 100644 custom-ui/vue.config.js create mode 100644 custom-ui/启动必看.txt create mode 100644 ruoyi-admin/pom.xml create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/RunApplication.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/RunServletInitializer.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java create mode 100644 ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java create mode 100644 ruoyi-admin/src/main/resources/META-INF/spring-devtools.properties create mode 100644 ruoyi-admin/src/main/resources/application-druid.yml create mode 100644 ruoyi-admin/src/main/resources/application.yml create mode 100644 ruoyi-admin/src/main/resources/banner.txt create mode 100644 ruoyi-admin/src/main/resources/i18n/messages.properties create mode 100644 ruoyi-admin/src/main/resources/logback.xml create mode 100644 ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml create mode 100644 ruoyi-business/pom.xml create mode 100644 ruoyi-business/src/main/java/com/ruoyi/business/controller/BusinessSurveyController.java create mode 100644 ruoyi-business/src/main/java/com/ruoyi/business/controller/BusinessTemplateController.java create mode 100644 ruoyi-business/src/main/java/com/ruoyi/business/controller/BusinessTemplatePropController.java create mode 100644 ruoyi-business/src/main/java/com/ruoyi/business/controller/BusinessTemplatePropValueController.java create mode 100644 ruoyi-business/src/main/java/com/ruoyi/business/domain/BusinessSurvey.java create mode 100644 ruoyi-business/src/main/java/com/ruoyi/business/domain/BusinessTemplate.java create mode 100644 ruoyi-business/src/main/java/com/ruoyi/business/domain/BusinessTemplateProp.java create mode 100644 ruoyi-business/src/main/java/com/ruoyi/business/domain/BusinessTemplatePropValue.java create mode 100644 ruoyi-business/src/main/java/com/ruoyi/business/mapper/BusinessSurveyMapper.java create mode 100644 ruoyi-business/src/main/java/com/ruoyi/business/mapper/BusinessTemplateMapper.java create mode 100644 ruoyi-business/src/main/java/com/ruoyi/business/mapper/BusinessTemplatePropMapper.java create mode 100644 ruoyi-business/src/main/java/com/ruoyi/business/mapper/BusinessTemplatePropValueMapper.java create mode 100644 ruoyi-business/src/main/java/com/ruoyi/business/service/IBusinessSurveyService.java create mode 100644 ruoyi-business/src/main/java/com/ruoyi/business/service/IBusinessTemplatePropService.java create mode 100644 ruoyi-business/src/main/java/com/ruoyi/business/service/IBusinessTemplatePropValueService.java create mode 100644 ruoyi-business/src/main/java/com/ruoyi/business/service/IBusinessTemplateService.java create mode 100644 ruoyi-business/src/main/java/com/ruoyi/business/service/impl/BusinessSurveyServiceImpl.java create mode 100644 ruoyi-business/src/main/java/com/ruoyi/business/service/impl/BusinessTemplatePropServiceImpl.java create mode 100644 ruoyi-business/src/main/java/com/ruoyi/business/service/impl/BusinessTemplatePropValueServiceImpl.java create mode 100644 ruoyi-business/src/main/java/com/ruoyi/business/service/impl/BusinessTemplateServiceImpl.java create mode 100644 ruoyi-business/src/main/resources/mapper/business/BusinessSurveyMapper.xml create mode 100644 ruoyi-business/src/main/resources/mapper/business/BusinessTemplateMapper.xml create mode 100644 ruoyi-business/src/main/resources/mapper/business/BusinessTemplatePropMapper.xml create mode 100644 ruoyi-business/src/main/resources/mapper/business/BusinessTemplatePropValueMapper.xml create mode 100644 ruoyi-common/pom.xml create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excels.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/text/CharsetKit.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/enums/LimitType.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/enums/UserStatus.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/UtilException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/filter/PropertyPreExcludeFilter.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/handler/MyMetaObjectHandler.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/LogUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanValidators.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelHandlerAdapter.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Base64.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/IdUtils.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/Seq.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/UUID.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/xss/Xss.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/xss/XssValidator.java create mode 100644 ruoyi-framework/pom.xml create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/MybatisPlusConfig.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/ServerConfig.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/manager/AsyncManager.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/AuthenticationContextHolder.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/PermissionContextHolder.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPasswordService.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPermissionService.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java create mode 100644 ruoyi-generator/pom.xml create mode 100644 ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java create mode 100644 ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java create mode 100644 ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java create mode 100644 ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java create mode 100644 ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java create mode 100644 ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java create mode 100644 ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableColumnServiceImpl.java create mode 100644 ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java create mode 100644 ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java create mode 100644 ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java create mode 100644 ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java create mode 100644 ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java create mode 100644 ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java create mode 100644 ruoyi-generator/src/main/resources/generator.yml create mode 100644 ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml create mode 100644 ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml create mode 100644 ruoyi-generator/src/main/resources/vm/java/controller.java.vm create mode 100644 ruoyi-generator/src/main/resources/vm/java/domain.java.vm create mode 100644 ruoyi-generator/src/main/resources/vm/java/mapper.java.vm create mode 100644 ruoyi-generator/src/main/resources/vm/java/service.java.vm create mode 100644 ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm create mode 100644 ruoyi-generator/src/main/resources/vm/java/sub-domain.java.vm create mode 100644 ruoyi-generator/src/main/resources/vm/js/api.js.vm create mode 100644 ruoyi-generator/src/main/resources/vm/sql/sql.vm create mode 100644 ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm create mode 100644 ruoyi-generator/src/main/resources/vm/vue/index.vue.vm create mode 100644 ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm create mode 100644 ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm create mode 100644 ruoyi-generator/src/main/resources/vm/vue/v3/readme.txt create mode 100644 ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm create mode 100644 ruoyi-quartz/pom.xml create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/config/ScheduleConfig.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobLogController.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJob.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJobLog.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobLogMapper.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobMapper.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobLogService.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobService.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobLogServiceImpl.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobServiceImpl.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/AbstractQuartzJob.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/CronUtils.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/JobInvokeUtil.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzDisallowConcurrentExecution.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzJobExecution.java create mode 100644 ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/ScheduleUtils.java create mode 100644 ruoyi-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml create mode 100644 ruoyi-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml create mode 100644 ruoyi-system/pom.xml create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysCache.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MetaVo.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RouterVo.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserOnlineService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.java create mode 100644 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysConfigMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysLogininforMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml create mode 100644 ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml create mode 100644 sql/dba.sql delete mode 100644 wjcy-common/pom.xml delete mode 100644 wjcy-common/src/main/java/me/zhengjie/annotation/AnonymousAccess.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/annotation/CheckPwd.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/annotation/DataPermission.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/annotation/DateTime.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/annotation/FormSubmission.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/annotation/Limit.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/annotation/Query.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/annotation/rest/AnonymousDeleteMapping.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/annotation/rest/AnonymousGetMapping.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/annotation/rest/AnonymousPatchMapping.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/annotation/rest/AnonymousPostMapping.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/annotation/rest/AnonymousPutMapping.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/aspect/LimitAspect.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/aspect/LimitType.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/base/BaseDTO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/base/BaseEntity.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/base/BaseMapper.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/config/AuditorConfig.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/config/BeanFactory.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/config/CorsInterceptor.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/config/CustomIdGenerator.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/config/DhApiProperties.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/config/ElPermissionConfig.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/config/FileProperties.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/config/MvcConfig.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/config/MyMetaObjectHandler.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/config/MybatisPlusConfig.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/config/PlatsProperties.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/config/PropertiesConfig.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/config/RedisConfig.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/config/RedissonConfig.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/config/RsaProperties.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/config/SwaggerConfig.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/config/SystemConfig.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/config/YdApiProperties.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/config/constant/Constants.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/constant/Constants.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/constant/PublicConstant.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/dao/CtApplyDao.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/dao/CtBrowseDao.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/dao/CtBuyerDao.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/dao/CtCardDao.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/dao/CtClickFarmingDao.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/dao/CtClickOrderDao.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/dao/CtCompanyDao.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/dao/CtDhPayDao.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/dao/CtExcelDao.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/dao/CtExcelImportInfoDao.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/dao/CtOrderDao.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/dao/CtPlatformDao.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/dao/CtRebotDao.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/dao/CtResponseOrderAddressDao.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/dao/CtResponseOrderDao.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/dao/CtResponseOrderProductDao.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/dao/CtVpnDao.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/dao/DhAddCarDao.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/dao/DhAddCarOrderDao.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/dao/DhCarGoodsDao.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/dao/LoginIpDao.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/dao/SettingSiteDao.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/dao/SysQuartzJobDao.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/dao/SysQuartzLogDao.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/dao/mapper/CtDhPayService.xml delete mode 100644 wjcy-common/src/main/java/me/zhengjie/dto/Dto.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/dto/PageDTO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/dto/StatementAggregateDTO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtApply.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtBrowse.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtBrowseYdParams.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtBuyer.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtBuyerClickSuccess.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtBuyerContactInfo.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtBuyerExport.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtBuyerExportTemple.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtBuyerImport.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtCard.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtCardExport.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtCardExportTemple.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtCardImport.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtCardInfo.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtClickFarmSupplyMentYdParams.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtClickFarmYdParams.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtClickFarming.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtClickFarmingExport.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtClickFarmingExportTemp.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtClickFarmingImport.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtClickFarmingOrderInfo.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtClickOrder.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtClickOrderExport.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtClickOrderExportTemple.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtClickOrderImport.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtClickOrderYdParams.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtCompany.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtCompanyInfo.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtDhPay.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtDhPayExport.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtDhPayExportTemple.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtDhPayImport.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtExcel.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtExcelExportInfo.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtExcelExportTemple.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtExcelImportInfo.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtOrder.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtParamContactInfo.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtParamProduct.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtPlatform.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtRebot.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtRebotExport.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtRebotExportTemple.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtRebotImport.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtResponseOrder.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtResponseOrderAddress.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtResponseOrderProduct.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtSettingSite.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtVpn.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtVpnExport.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtVpnExportTemple.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtVpnImport.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/CtVpnInfo.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/DhAddCar.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/DhAddCarOrder.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/DhCarGoods.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/ExcelImportInfo.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/LoginIp.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/QueryWrapperAndPage.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/ResultObj.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/ReturnObje.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/SysQuartzJob.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/SysQuartzLog.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/YdSign.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/YdStartReturn.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/quartz/Boss.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/quartz/DataInfo.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/quartz/JobQueryByUuid.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/quartz/JobQueryByUuidData.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/quartz/JobQueryByUuidReturn.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/quartz/JobQueryByUuidRobotParams.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/quartz/JobQueryReturnResult.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/quartz/Param.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/quartz/Params.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/quartz/RebotStatu.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/quartz/RebotStatuInfo.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/quartz/RebotStatuReturn.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/quartz/SecreInfo.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/entity/quartz/StartYdReturnInfo.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/enums/BuyerLevelEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/enums/BuyerOccupyStatusEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/enums/BuyerStatusEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/enums/CardDealerTypeEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/enums/CardStatusEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/enums/CardTypeEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/enums/ClickBrowseStatusEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/enums/ClickFarmingStatusEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/enums/ClickOrderStatusEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/enums/CtReboteStatusEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/enums/DhAddCarStatusEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/enums/DhPayStatusEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/enums/ExcelInfoRequestTypeEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/enums/ExcelStatusEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/enums/LanguageEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/enums/OrderTypeEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/enums/ParamsTypeEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/enums/PlatTypeEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/enums/RobotStatusEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/enums/TaskInfoEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/enums/TaskIsPauseEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/enums/TaskTypeEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/enums/VpnDealerEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/enums/VpnStatusEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/enums/VpnTypeEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/enums/YesOrNoEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/enums/interfaces/IntegerEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/enums/interfaces/LongEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/enums/interfaces/MemberIsUsedEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/error/ErrorCodeEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/exception/BadConfigurationException.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/exception/BadRequestException.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/exception/EntityExistException.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/exception/EntityNotFoundException.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/exception/handler/ApiError.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/exception/handler/GlobalExceptionHandler.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/mybatis/LambdaQueryWrapperImpl.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/CtApplyService.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/CtBrowseService.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/CtBuyerService.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/CtCardService.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/CtClickFarmingService.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/CtClickOrderService.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/CtCompanyService.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/CtDhPayService.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/CtExcelImportInfoService.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/CtExcelService.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/CtOrderService.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/CtPlatformService.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/CtRebotService.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/CtResponseOrderAddressService.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/CtResponseOrderProductService.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/CtResponseOrderService.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/CtVpnService.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/DhAddCarOrderService.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/DhAddCarService.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/DhCarGoodsService.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/FileUploadService.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/LoginIpService.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/SettingSiteService.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/SysQuartzLogService.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/YdQuartzService.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/impl/CtApplyServiceImpl.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/impl/CtBrowseServiceImpl.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/impl/CtBuyerServiceImpl.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/impl/CtCardServiceImpl.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/impl/CtClickFarmingServiceImpl.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/impl/CtClickOrderServiceImpl.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/impl/CtCompanyServiceImpl.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/impl/CtDhPayServiceImpl.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/impl/CtExcelImportInfoServiceImpl.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/impl/CtExcelServiceImpl.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/impl/CtOrderServiceImpl.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/impl/CtPlatformServiceImpl.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/impl/CtRebotServiceImpl.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/impl/CtResponseOrderAddressServiceImpl.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/impl/CtResponseOrderProductServiceImpl.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/impl/CtResponseOrderServiceImpl.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/impl/CtVpnServiceImpl.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/impl/DhAddCarOrderServiceImpl.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/impl/DhAddCarServiceImpl.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/impl/DhCarGoodsServiceImpl.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/impl/FileUploadServiceImpl.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/impl/LoginIpServiceImpl.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/impl/SettingSiteServiceImpl.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/impl/SysQuartzJobServiceImpl.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/impl/SysQuartzLogServiceImpl.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/impl/YdQuartzServiceImpl.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/redission/LockCallBack.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/AdminGoogleAuthInfoVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/BuyOrderResponseAddressVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/BuyOrderResponseOrderVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/BuyOrderResponseProductVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/BuyOrderVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/CtApplyInfoVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/CtApplyListVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/CtBrowseDetailVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/CtBrowseListVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/CtBuyerClickFarmVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/CtBuyerDetailVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/CtBuyerListVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/CtBuyerVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/CtCardDetailVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/CtCardListVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/CtClickFarmEditDetailVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/CtClickFarmingDetailVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/CtClickFarmingVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/CtClickOrderDetailVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/CtClickOrderListVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/CtCompanyInfoVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/CtCompanyVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/CtDhPayDetailVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/CtDhPayListVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/CtExcelImportInfoVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/CtExcelVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/CtOrderVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/CtPlatformInfoVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/CtPlatformVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/CtRebotListVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/CtVpnInfoVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/CtVpnVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/GoogleAuthInfoVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/LoginIpVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/OrderResponStatusVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/OrderResponSubErrorVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/OrderResponseVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/PayOrderVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/SettingSiteVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/SysQuartzJobListVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/SysQuartzLogListVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/dhaddcar/DhAddCarListVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/dhaddcar/DhAddCarVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/dhaddcar/DhAddCarYdParamsVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/dhcargood/DhCarGoodKeyVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/dhcargood/DhCarGoodLinkVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/dhcarorder/DhAddCarOrderListVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/service/vo/dhcarorder/DhCarOrderParamsVO.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/CacheKey.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/CallBack.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/CheckPwdValidator.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/CloseUtil.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/CronUtils.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/DateTimeValidator.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/DateUtil.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/ElAdminConstant.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/EmptyAttributeFiler.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/EncryptUtils.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/FileUtil.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/HexUtil.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/HttpClientUtil.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/HttpConnectionManager.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/IpUtils.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/JsonDealUtils.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/LoginIpUtil.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/MD5Util.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/NewStringUtils.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/OrderGetIndexUtil.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/PageUtil.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/PageUtils.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/PopularizeUtil.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/PropertiesUtil.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/QueryHelp.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/RedisUtils.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/RedissonUtil.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/RequestHolder.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/RsaUtils.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/SecurityUtils.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/ServletUtils.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/SpringContextHolder.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/StringUtil.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/StringUtils.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/ThrowableUtil.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/TransformMap.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/TransformQueryWrapper.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/TranslatorUtil.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/ValidationUtil.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/YdCallBackUtil.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/YdParamsCheck.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/YdSignUtil.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/enums/CodeBiEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/enums/CodeEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/enums/DataScopeEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/enums/RequestMethodEnum.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/excel/ExcelClassField.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/excel/ExcelExport.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/excel/ExcelImport.java delete mode 100644 wjcy-common/src/main/java/me/zhengjie/utils/excel/ExcelUtils.java delete mode 100644 wjcy-common/src/test/java/me/zhengjie/utils/EncryptUtilsTest.java delete mode 100644 wjcy-common/src/test/java/me/zhengjie/utils/FileUtilTest.java delete mode 100644 wjcy-common/src/test/java/me/zhengjie/utils/StringUtilsTest.java delete mode 100644 wjcy-generator/pom.xml delete mode 100644 wjcy-generator/src/main/java/me/zhengjie/domain/ColumnInfo.java delete mode 100644 wjcy-generator/src/main/java/me/zhengjie/domain/GenConfig.java delete mode 100644 wjcy-generator/src/main/java/me/zhengjie/domain/vo/TableInfo.java delete mode 100644 wjcy-generator/src/main/java/me/zhengjie/repository/ColumnInfoRepository.java delete mode 100644 wjcy-generator/src/main/java/me/zhengjie/repository/GenConfigRepository.java delete mode 100644 wjcy-generator/src/main/java/me/zhengjie/rest/GenConfigController.java delete mode 100644 wjcy-generator/src/main/java/me/zhengjie/rest/GeneratorController.java delete mode 100644 wjcy-generator/src/main/java/me/zhengjie/service/GenConfigService.java delete mode 100644 wjcy-generator/src/main/java/me/zhengjie/service/GeneratorService.java delete mode 100644 wjcy-generator/src/main/java/me/zhengjie/service/impl/GenConfigServiceImpl.java delete mode 100644 wjcy-generator/src/main/java/me/zhengjie/service/impl/GeneratorServiceImpl.java delete mode 100644 wjcy-generator/src/main/java/me/zhengjie/utils/ColUtil.java delete mode 100644 wjcy-generator/src/main/java/me/zhengjie/utils/GenUtil.java delete mode 100644 wjcy-logging/pom.xml delete mode 100644 wjcy-logging/src/main/java/me/zhengjie/annotation/Log.java delete mode 100644 wjcy-logging/src/main/java/me/zhengjie/annotation/type/LogActionType.java delete mode 100644 wjcy-logging/src/main/java/me/zhengjie/annotation/type/LogDaoType.java delete mode 100644 wjcy-logging/src/main/java/me/zhengjie/annotation/type/LogGetIdType.java delete mode 100644 wjcy-logging/src/main/java/me/zhengjie/annotation/type/LogGetValueType.java delete mode 100644 wjcy-logging/src/main/java/me/zhengjie/aspect/LogAspect.java delete mode 100644 wjcy-logging/src/main/java/me/zhengjie/domain/Log.java delete mode 100644 wjcy-logging/src/main/java/me/zhengjie/enums/LogTypeEnum.java delete mode 100644 wjcy-logging/src/main/java/me/zhengjie/repository/LogRepository.java delete mode 100644 wjcy-logging/src/main/java/me/zhengjie/rest/LogController.java delete mode 100644 wjcy-logging/src/main/java/me/zhengjie/service/LogService.java delete mode 100644 wjcy-logging/src/main/java/me/zhengjie/service/dto/LogErrorDTO.java delete mode 100644 wjcy-logging/src/main/java/me/zhengjie/service/dto/LogQueryCriteria.java delete mode 100644 wjcy-logging/src/main/java/me/zhengjie/service/dto/LogSmallDTO.java delete mode 100644 wjcy-logging/src/main/java/me/zhengjie/service/impl/LogServiceImpl.java delete mode 100644 wjcy-logging/src/main/java/me/zhengjie/service/mapstruct/LogErrorMapper.java delete mode 100644 wjcy-logging/src/main/java/me/zhengjie/service/mapstruct/LogSmallMapper.java delete mode 100644 wjcy-system/pom.xml delete mode 100644 wjcy-system/src/main/java/me/zhengjie/AppRun.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/aspect/FormSubmissionAspect.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/config/ConfigurerAdapter.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/config/CorsConfig.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/config/GoogleAuthProperties.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/config/WebSocketConfig.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/config/thread/AsyncTaskExecutePool.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/config/thread/AsyncTaskProperties.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/config/thread/TheadFactoryName.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/config/thread/ThreadPoolExecutorUtil.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/aspect/LogAspect.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/capital/controller/FileUploadController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/capital/controller/GoogleAuthController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/capital/controller/LoginIpController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/capital/controller/SettingSiteController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/capital/dto/AddLoginIpDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/capital/dto/EditLoginIpDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/capital/dto/IdDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/capital/dto/RelSettingSiteDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/capital/dto/SettingSiteDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtApplyController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtBrowseController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtBuyerController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtCardController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtClickFarmingController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtClickOrderController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtCompanyController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtDhPayController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtExcelController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtExcelInfoController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtOrderController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtPlatformController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtRebotController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtVpnController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/DhAddCarCatchController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/DhAddCarController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/DhAddCarOrderController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/QuartzLogController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/SdsController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/SysQuartzJobController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/YdCallBackController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/BossTaskCallBackController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/ClickFarmingCallBackController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/ClickFarmingSuppleMentCallBackController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/ClickOrderCallBackController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/CtbrowseCallBackController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/DhAddCarCallBackController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/DhCarOrderCallBackController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/DhCatchOrderCallBackController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtApplyAddDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtApplyListDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtApplyUpdateDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtBrowseAddDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtBrowseListDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtBrowseUpdateDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtBuyerAddDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtBuyerListDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtBuyerUpdateDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtCardAddDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtCardListDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtCardUpdateDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtClickFarmingAddDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtClickFarmingDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtClickFarmingEditDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtClickOrderAddDto.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtClickOrderCommentDto.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtClickOrderListDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtClickOrderSupplementDto.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtCompanyAddDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtCompanyListDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtCompanyUpdateDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtDhPayAddDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtDhPayListDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtExcelAddDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtExcelImportInfoListDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtExcelListDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtExcelUpdateDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtOrderListDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtPlatformAddDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtPlatformListDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtPlatformUpdateDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtRebotAddDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtRebotListDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtRebotUpdateDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtRebotUpdateStatusDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtVpnAddDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtVpnListDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtVpnUpdateDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/DhCarGoodWellReceivedDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/DhCarWellReceivedDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/IdDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/SearchOrderListDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/SysQuartzJobAddDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/SysQuartzJobListDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/SysQuartzJobUpdateDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/SysQuartzLogListDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhaddcar/DhAddCarAddDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhaddcar/DhAddCarEditDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhaddcar/DhAddCarListDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhcargood/DhCarGoodKeyAddDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhcargood/DhCarGoodKeyEditDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhcargood/DhCarGoodLinkAddDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhcargood/DhCarGoodLinkEditDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhcarorder/DhAddCarOrderListDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/domain/App.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/domain/Database.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/domain/Deploy.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/domain/DeployHistory.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/domain/ServerDeploy.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/repository/AppRepository.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/repository/DatabaseRepository.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/repository/DeployHistoryRepository.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/repository/DeployRepository.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/repository/ServerDeployRepository.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/rest/AppController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/rest/DatabaseController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/rest/DeployController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/rest/DeployHistoryController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/rest/ServerDeployController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/AppService.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/DatabaseService.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/DeployHistoryService.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/DeployService.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/ServerDeployService.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/AppDto.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/AppQueryCriteria.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/DatabaseDto.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/DatabaseQueryCriteria.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/DeployDto.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/DeployHistoryDto.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/DeployHistoryQueryCriteria.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/DeployQueryCriteria.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/ServerDeployDto.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/ServerDeployQueryCriteria.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/impl/AppServiceImpl.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/impl/DatabaseServiceImpl.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/impl/DeployHistoryServiceImpl.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/impl/DeployServiceImpl.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/impl/ServerDeployServiceImpl.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/mapstruct/AppMapper.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/mapstruct/DatabaseMapper.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/mapstruct/DeployHistoryMapper.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/mapstruct/DeployMapper.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/mapstruct/ServerDeployMapper.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/util/DataTypeEnum.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/util/ExecuteShellUtil.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/util/ScpClientUtil.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/util/SqlUtils.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/websocket/MsgType.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/websocket/SocketMsg.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/mnt/websocket/WebSocketServer.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/config/JobRunner.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/config/QuartzConfig.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/domain/QuartzJob.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/domain/QuartzLog.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/repository/QuartzJobRepository.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/repository/QuartzLogRepository.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/rest/QuartzJobController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/service/QuartzJobService.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/service/SysQuartzJobService.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/service/dto/JobQueryCriteria.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/service/impl/QuartzJobServiceImpl.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/service/impl/SysQuartzJobServiceImpl.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/BossTask.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/BossTask22.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/BrowseTask.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/ClickFarmSuppleMentTask.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/ClickFarmTask.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/DhAddCarTask.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/DhCatchOrderTask.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/DhPayTask.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/DhWellReceivedTask.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/ExcelToOrderTask.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/ExcelmportTask.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/OrderToPayTask.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/RebotStatusTask.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/TestTask.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/WellReceivedTask.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/utils/ExecutionJob.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/utils/QuartzManage.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/utils/QuartzRunnable.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/quartz/utils/YdApiUtil.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/security/config/ConfigBeanConfiguration.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/security/config/SecurityConfig.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/security/config/bean/LoginCode.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/security/config/bean/LoginCodeEnum.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/security/config/bean/LoginProperties.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/security/config/bean/SecurityProperties.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/security/rest/AuthorizationController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/security/rest/OnlineController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/security/security/JwtAccessDeniedHandler.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/security/security/JwtAuthenticationEntryPoint.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/security/security/TokenConfigurer.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/security/security/TokenFilter.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/security/security/TokenProvider.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/security/service/OnlineUserService.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/security/service/UserCacheClean.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/security/service/UserDetailsServiceImpl.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/security/service/dto/AuthUserDto.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/security/service/dto/JwtUserDto.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/security/service/dto/OnlineUserDto.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/domain/Dept.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/domain/Dict.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/domain/DictDetail.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/domain/Job.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/domain/Menu.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/domain/Role.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/domain/User.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/domain/vo/MenuMetaVo.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/domain/vo/MenuVo.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/domain/vo/UserPassVo.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/repository/DeptRepository.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/repository/DictDetailRepository.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/repository/DictRepository.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/repository/JobRepository.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/repository/MenuRepository.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/repository/RoleRepository.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/repository/UserRepository.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/rest/DeptController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/rest/DictController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/rest/DictDetailController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/rest/JobController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/rest/LimitController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/rest/MenuController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/rest/MonitorController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/rest/RoleController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/rest/UserController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/rest/VerifyController.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/DataService.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/DeptService.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/DictDetailService.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/DictService.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/JobService.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/MenuService.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/MonitorService.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/RoleService.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/UserService.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/VerifyService.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DeptDto.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DeptQueryCriteria.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DeptSmallDto.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DictDetailDto.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DictDetailQueryCriteria.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DictDto.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DictQueryCriteria.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DictSmallDto.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/GoogleAuthCodeDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/GoogleAuthGenSecretDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/GoogleAuthQrBarCodeUrlDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/JobDto.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/JobQueryCriteria.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/JobSmallDto.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/MenuDto.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/MenuQueryCriteria.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/RoleDto.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/RoleQueryCriteria.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/RoleSmallDto.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/UpdateGoogleAuthDTO.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/UserDto.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/UserQueryCriteria.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/DataServiceImpl.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/DeptServiceImpl.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/DictDetailServiceImpl.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/DictServiceImpl.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/JobServiceImpl.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/MenuServiceImpl.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/MonitorServiceImpl.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/RoleServiceImpl.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/UserServiceImpl.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/VerifyServiceImpl.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/DeptMapper.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/DeptSmallMapper.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/DictDetailMapper.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/DictMapper.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/DictSmallMapper.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/JobMapper.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/JobSmallMapper.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/MenuMapper.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/RoleMapper.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/RoleSmallMapper.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/UserMapper.java delete mode 100644 wjcy-system/src/main/java/me/zhengjie/modules/utils/GoogleAuthenticatorUtil.java delete mode 100644 wjcy-system/src/main/resources/banner.txt delete mode 100644 wjcy-system/src/main/resources/config/application-dev.yml delete mode 100644 wjcy-system/src/main/resources/config/application-local.yml delete mode 100644 wjcy-system/src/main/resources/config/application-prod.yml delete mode 100644 wjcy-system/src/main/resources/config/application-xxs.yml delete mode 100644 wjcy-system/src/main/resources/config/application.yml delete mode 100644 wjcy-system/src/main/resources/generator.properties delete mode 100644 wjcy-system/src/main/resources/ip2region/ip2region.db delete mode 100644 wjcy-system/src/main/resources/log4j2.xml delete mode 100644 wjcy-system/src/main/resources/log4jdbc.log4j2.properties delete mode 100644 wjcy-system/src/main/resources/template/email/email.ftl delete mode 100644 wjcy-system/src/main/resources/template/email/taskAlarm.ftl delete mode 100644 wjcy-system/src/main/resources/template/generator/admin/Controller.ftl delete mode 100644 wjcy-system/src/main/resources/template/generator/admin/Dto.ftl delete mode 100644 wjcy-system/src/main/resources/template/generator/admin/Entity.ftl delete mode 100644 wjcy-system/src/main/resources/template/generator/admin/Mapper.ftl delete mode 100644 wjcy-system/src/main/resources/template/generator/admin/QueryCriteria.ftl delete mode 100644 wjcy-system/src/main/resources/template/generator/admin/Repository.ftl delete mode 100644 wjcy-system/src/main/resources/template/generator/admin/Service.ftl delete mode 100644 wjcy-system/src/main/resources/template/generator/admin/ServiceImpl.ftl delete mode 100644 wjcy-system/src/main/resources/template/generator/front/api.ftl delete mode 100644 wjcy-system/src/main/resources/template/generator/front/index.ftl delete mode 100644 wjcy-system/src/main/resources/templates/index.html delete mode 100644 wjcy-system/src/test/java/me/zhengjie/CtBuyerControllerTest.java delete mode 100644 wjcy-system/src/test/java/me/zhengjie/CtPlatformControllerTest.java delete mode 100644 wjcy-system/src/test/java/me/zhengjie/DhApiTest.java delete mode 100644 wjcy-system/src/test/java/me/zhengjie/ExcelUserTest.java delete mode 100644 wjcy-system/src/test/java/me/zhengjie/SettingSiteServiceTest.java delete mode 100644 wjcy-system/src/test/java/me/zhengjie/TransactionSignDemo.java delete mode 100644 wjcy-tools/pom.xml delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/config/MultipartConfig.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/domain/AlipayConfig.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/domain/EmailConfig.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/domain/LocalStorage.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/domain/QiniuConfig.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/domain/QiniuContent.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/domain/vo/EmailVo.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/domain/vo/TradeVo.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/repository/AliPayRepository.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/repository/EmailRepository.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/repository/LocalStorageRepository.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/repository/QiNiuConfigRepository.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/repository/QiniuContentRepository.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/rest/AliPayController.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/rest/EmailController.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/rest/LocalStorageController.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/rest/QiniuController.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/service/AliPayService.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/service/EmailService.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/service/LocalStorageService.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/service/QiNiuService.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/service/dto/LocalStorageDto.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/service/dto/LocalStorageQueryCriteria.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/service/dto/PictureQueryCriteria.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/service/dto/QiniuQueryCriteria.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/service/impl/AliPayServiceImpl.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/service/impl/EmailServiceImpl.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/service/impl/LocalStorageServiceImpl.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/service/impl/QiNiuServiceImpl.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/service/mapstruct/LocalStorageMapper.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/utils/AliPayStatusEnum.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/utils/AlipayUtils.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/utils/QiNiuUtil.java delete mode 100644 wjcy-tools/src/main/java/me/zhengjie/utils/RSACoderUtil.java diff --git a/.gitignore b/.gitignore index 549e00a..ff317e6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,15 @@ -HELP.md +###################################################################### +# Build Tools + +.gradle +/build/ +!gradle/wrapper/gradle-wrapper.jar + target/ !.mvn/wrapper/maven-wrapper.jar -!**/src/main/**/target/ -!**/src/test/**/target/ + +###################################################################### +# IDE ### STS ### .apt_generated @@ -11,7 +18,6 @@ target/ .project .settings .springBeans -.sts4-cache ### IntelliJ IDEA ### .idea @@ -19,15 +25,24 @@ target/ *.iml *.ipr +### JRebel ### +rebel.xml + ### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ -!**/src/main/**/build/ -!**/src/test/**/build/ - -### VS Code ### -.vscode/ +nbproject/private/ +build/* +nbbuild/ +dist/ +nbdist/ +.nb-gradle/ + +###################################################################### +# Others +*.log +*.xml.versionsBackup +*.swp + +!*/build/*.java +!*/build/*.html +!*/build/*.xml +/custom-ui/node_modules diff --git a/LICENSE b/LICENSE index ca38718..8564f29 100644 --- a/LICENSE +++ b/LICENSE @@ -1,191 +1,20 @@ -Apache License -Version 2.0, January 2004 -http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - -"License" shall mean the terms and conditions for use, reproduction, and -distribution as defined by Sections 1 through 9 of this document. - -"Licensor" shall mean the copyright owner or entity authorized by the copyright -owner that is granting the License. - -"Legal Entity" shall mean the union of the acting entity and all other entities -that control, are controlled by, or are under common control with that entity. -For the purposes of this definition, "control" means (i) the power, direct or -indirect, to cause the direction or management of such entity, whether by -contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the -outstanding shares, or (iii) beneficial ownership of such entity. - -"You" (or "Your") shall mean an individual or Legal Entity exercising -permissions granted by this License. - -"Source" form shall mean the preferred form for making modifications, including -but not limited to software source code, documentation source, and configuration -files. - -"Object" form shall mean any form resulting from mechanical transformation or -translation of a Source form, including but not limited to compiled object code, -generated documentation, and conversions to other media types. - -"Work" shall mean the work of authorship, whether in Source or Object form, made -available under the License, as indicated by a copyright notice that is included -in or attached to the work (an example is provided in the Appendix below). - -"Derivative Works" shall mean any work, whether in Source or Object form, that -is based on (or derived from) the Work and for which the editorial revisions, -annotations, elaborations, or other modifications represent, as a whole, an -original work of authorship. For the purposes of this License, Derivative Works -shall not include works that remain separable from, or merely link (or bind by -name) to the interfaces of, the Work and Derivative Works thereof. - -"Contribution" shall mean any work of authorship, including the original version -of the Work and any modifications or additions to that Work or Derivative Works -thereof, that is intentionally submitted to Licensor for inclusion in the Work -by the copyright owner or by an individual or Legal Entity authorized to submit -on behalf of the copyright owner. For the purposes of this definition, -"submitted" means any form of electronic, verbal, or written communication sent -to the Licensor or its representatives, including but not limited to -communication on electronic mailing lists, source code control systems, and -issue tracking systems that are managed by, or on behalf of, the Licensor for -the purpose of discussing and improving the Work, but excluding communication -that is conspicuously marked or otherwise designated in writing by the copyright -owner as "Not a Contribution." - -"Contributor" shall mean Licensor and any individual or Legal Entity on behalf -of whom a Contribution has been received by Licensor and subsequently -incorporated within the Work. - -2. Grant of Copyright License. - -Subject to the terms and conditions of this License, each Contributor hereby -grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, -irrevocable copyright license to reproduce, prepare Derivative Works of, -publicly display, publicly perform, sublicense, and distribute the Work and such -Derivative Works in Source or Object form. - -3. Grant of Patent License. - -Subject to the terms and conditions of this License, each Contributor hereby -grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, -irrevocable (except as stated in this section) patent license to make, have -made, use, offer to sell, sell, import, and otherwise transfer the Work, where -such license applies only to those patent claims licensable by such Contributor -that are necessarily infringed by their Contribution(s) alone or by combination -of their Contribution(s) with the Work to which such Contribution(s) was -submitted. If You institute patent litigation against any entity (including a -cross-claim or counterclaim in a lawsuit) alleging that the Work or a -Contribution incorporated within the Work constitutes direct or contributory -patent infringement, then any patent licenses granted to You under this License -for that Work shall terminate as of the date such litigation is filed. - -4. Redistribution. - -You may reproduce and distribute copies of the Work or Derivative Works thereof -in any medium, with or without modifications, and in Source or Object form, -provided that You meet the following conditions: - -You must give any other recipients of the Work or Derivative Works a copy of -this License; and -You must cause any modified files to carry prominent notices stating that You -changed the files; and -You must retain, in the Source form of any Derivative Works that You distribute, -all copyright, patent, trademark, and attribution notices from the Source form -of the Work, excluding those notices that do not pertain to any part of the -Derivative Works; and -If the Work includes a "NOTICE" text file as part of its distribution, then any -Derivative Works that You distribute must include a readable copy of the -attribution notices contained within such NOTICE file, excluding those notices -that do not pertain to any part of the Derivative Works, in at least one of the -following places: within a NOTICE text file distributed as part of the -Derivative Works; within the Source form or documentation, if provided along -with the Derivative Works; or, within a display generated by the Derivative -Works, if and wherever such third-party notices normally appear. The contents of -the NOTICE file are for informational purposes only and do not modify the -License. You may add Your own attribution notices within Derivative Works that -You distribute, alongside or as an addendum to the NOTICE text from the Work, -provided that such additional attribution notices cannot be construed as -modifying the License. -You may add Your own copyright statement to Your modifications and may provide -additional or different license terms and conditions for use, reproduction, or -distribution of Your modifications, or for any such Derivative Works as a whole, -provided Your use, reproduction, and distribution of the Work otherwise complies -with the conditions stated in this License. - -5. Submission of Contributions. - -Unless You explicitly state otherwise, any Contribution intentionally submitted -for inclusion in the Work by You to the Licensor shall be under the terms and -conditions of this License, without any additional terms or conditions. -Notwithstanding the above, nothing herein shall supersede or modify the terms of -any separate license agreement you may have executed with Licensor regarding -such Contributions. - -6. Trademarks. - -This License does not grant permission to use the trade names, trademarks, -service marks, or product names of the Licensor, except as required for -reasonable and customary use in describing the origin of the Work and -reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. - -Unless required by applicable law or agreed to in writing, Licensor provides the -Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, -including, without limitation, any warranties or conditions of TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are -solely responsible for determining the appropriateness of using or -redistributing the Work and assume any risks associated with Your exercise of -permissions under this License. - -8. Limitation of Liability. - -In no event and under no legal theory, whether in tort (including negligence), -contract, or otherwise, unless required by applicable law (such as deliberate -and grossly negligent acts) or agreed to in writing, shall any Contributor be -liable to You for damages, including any direct, indirect, special, incidental, -or consequential damages of any character arising as a result of this License or -out of the use or inability to use the Work (including but not limited to -damages for loss of goodwill, work stoppage, computer failure or malfunction, or -any and all other commercial damages or losses), even if such Contributor has -been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. - -While redistributing the Work or Derivative Works thereof, You may choose to -offer, and charge a fee for, acceptance of support, warranty, indemnity, or -other liability obligations and/or rights consistent with this License. However, -in accepting such obligations, You may act only on Your own behalf and on Your -sole responsibility, not on behalf of any other Contributor, and only if You -agree to indemnify, defend, and hold each Contributor harmless for any liability -incurred by, or claims asserted against, such Contributor by reason of your -accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work - -To apply the Apache License to your work, attach the following boilerplate -notice, with the fields enclosed by brackets "{}" replaced with your own -identifying information. (Don't include the brackets!) The text should be -enclosed in the appropriate comment syntax for the file format. We also -recommend that a file or class name and description of purpose be included on -the same "printed page" as the copyright notice for easier identification within -third-party archives. - - Copyright 2019-2020 Zheng Jie - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file +The MIT License (MIT) + +Copyright (c) 2018 RuoYi + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index 484acf5..b129538 100644 --- a/README.md +++ b/README.md @@ -1,83 +1,45 @@ -

EL-ADMIN 后台管理系统

-
-#### 项目简介 -一个基于 Spring Boot 2.1.0 、 Spring Boot Jpa、 JWT、Spring Security、Redis、Vue的前后端分离的后台管理系统 - -**开发文档:** [https://el-admin.vip](https://el-admin.vip) - -**体验地址:** [https://el-admin.xin](https://el-admin.xin) - -**账号密码:** `admin / 123456` - -#### 项目源码 - -| | 后端源码 | 前端源码 | -|--- |--- | --- | -| github | https://github.com/elunez/eladmin | https://github.com/elunez/eladmin-web | -| 码云 | https://gitee.com/elunez/eladmin | https://gitee.com/elunez/eladmin-web | - -#### 主要特性 -- 使用最新技术栈,社区资源丰富。 -- 高效率开发,代码生成器可一键生成前后端代码 -- 支持数据字典,可方便地对一些状态进行管理 -- 支持接口限流,避免恶意请求导致服务层压力过大 -- 支持接口级别的功能权限与数据权限,可自定义操作 -- 自定义权限注解与匿名接口注解,可快速对接口拦截与放行 -- 对一些常用地前端组件封装:表格数据请求、数据字典等 -- 前后端统一异常拦截处理,统一输出异常,避免繁琐的判断 -- 支持在线用户管理与服务器性能监控,支持限制单用户登录 -- 支持运维管理,可方便地对远程服务器的应用进行部署与管理 - -#### 系统功能 -- 用户管理:提供用户的相关配置,新增用户后,默认密码为123456 -- 角色管理:对权限与菜单进行分配,可根据部门设置角色的数据权限 -- 菜单管理:已实现菜单动态路由,后端可配置化,支持多级菜单 -- 部门管理:可配置系统组织架构,树形表格展示 -- 岗位管理:配置各个部门的职位 -- 字典管理:可维护常用一些固定的数据,如:状态,性别等 -- 系统日志:记录用户操作日志与异常日志,方便开发人员定位排错 -- SQL监控:采用druid 监控数据库访问性能,默认用户名admin,密码123456 -- 定时任务:整合Quartz做定时任务,加入任务日志,任务运行情况一目了然 -- 代码生成:高灵活度生成前后端代码,减少大量重复的工作任务 -- 邮件工具:配合富文本,发送html格式的邮件 -- 七牛云存储:可同步七牛云存储的数据到系统,无需登录七牛云直接操作云数据 -- 支付宝支付:整合了支付宝支付并且提供了测试账号,可自行测试 -- 服务监控:监控服务器的负载情况 -- 运维管理:一键部署你的应用 - -#### 项目结构 -项目采用按功能分模块的开发方式,结构如下 - -- `capiltal-common` 为系统的公共模块,各种工具类,公共配置存在该模块 - -- `capiltal-client` 为客户端api模块,也是最终需要打包部署的模块 - -- `capiltal-system` 为系统核心模块也是项目入口模块,也是最终需要打包部署的模块 - -- `capiltal-logging` 为系统的日志模块,其他模块如果需要记录日志需要引入该模块 - -- `capiltal-tools` 为第三方工具模块,包含:图床、邮件、云存储、本地存储、支付宝 - -- `capiltal-generator` 为系统的代码生成模块,代码生成的模板在 system 模块中 - -#### 详细结构 - -``` -- capiltal-common 公共模块 - - annotation 为系统自定义注解 - - aspect 自定义注解的切面 - - base 提供了Entity、DTO基类和mapstruct的通用mapper - - config 自定义权限实现、redis配置、swagger配置、Rsa配置等 - - dao MybatiesPlus Dao - - mapper mybatiesPlus Mapper - - exception 项目统一异常的处理 - - utils 系统通用工具类 -- capiltal-system 系统核心模块(系统启动入口) - - config 配置跨域与静态资源,与数据权限 - - thread 线程池相关 - - modules 系统相关模块(登录授权、系统监控、定时任务、运维管理等) -- capiltal-logging 系统日志模块 -- capiltal-tools 系统第三方工具模块 -- capiltal-generator 系统代码生成模块 -``` - +## 内置功能 + +1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。 +2. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。 +3. 岗位管理:配置系统用户所属担任职务。 +4. 菜单管理:配置系统菜单,操作权限,按钮权限标识等。 +5. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。 +6. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。 +7. 参数管理:对系统动态配置常用参数。 +8. 通知公告:系统通知公告信息发布维护。 +9. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。 +10. 登录日志:系统登录日志记录查询包含登录异常。 +11. 在线用户:当前系统中活跃用户状态监控。 +12. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。 +13. 代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载 。 +14. 系统接口:根据业务代码自动生成相关的api接口文档。 +15. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。 +16. 缓存监控:对系统的缓存信息查询,命令统计等。 +17. 在线构建器:拖动表单元素生成相应的HTML代码。 +18. 连接池监视:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。 + + +前端开发 +# 克隆项目 +git clone https://gitee.com/y_project/RuoYi-Vue + +# 进入项目目录 +cd ruoyi-ui + +# 安装依赖 +npm install + +# 建议不要直接使用 cnpm 安装依赖,会有各种诡异的 bug。可以通过如下操作解决 npm 下载速度慢的问题 +npm install --registry=https://registry.npmmirror.com + +### 启动服务 +npm run dev + +### 发布 + +# 构建测试环境 +npm run build:stage + +# 构建生产环境 +npm run build:prod diff --git a/bin/clean.bat b/bin/clean.bat new file mode 100644 index 0000000..24c0974 --- /dev/null +++ b/bin/clean.bat @@ -0,0 +1,12 @@ +@echo off +echo. +echo [Ϣ] target· +echo. + +%~d0 +cd %~dp0 + +cd .. +call mvn clean + +pause \ No newline at end of file diff --git a/bin/package.bat b/bin/package.bat new file mode 100644 index 0000000..c693ec0 --- /dev/null +++ b/bin/package.bat @@ -0,0 +1,12 @@ +@echo off +echo. +echo [Ϣ] Weḅwar/jarļ +echo. + +%~d0 +cd %~dp0 + +cd .. +call mvn clean package -Dmaven.test.skip=true + +pause \ No newline at end of file diff --git a/bin/run.bat b/bin/run.bat new file mode 100644 index 0000000..41efbd0 --- /dev/null +++ b/bin/run.bat @@ -0,0 +1,14 @@ +@echo off +echo. +echo [Ϣ] ʹJarWeb̡ +echo. + +cd %~dp0 +cd ../ruoyi-admin/target + +set JAVA_OPTS=-Xms256m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m + +java -jar %JAVA_OPTS% ruoyi-admin.jar + +cd bin +pause \ No newline at end of file diff --git a/custom-ui/.editorconfig b/custom-ui/.editorconfig new file mode 100644 index 0000000..7034f9b --- /dev/null +++ b/custom-ui/.editorconfig @@ -0,0 +1,22 @@ +# 告诉EditorConfig插件,这是根文件,不用继续往上查找 +root = true + +# 匹配全部文件 +[*] +# 设置字符集 +charset = utf-8 +# 缩进风格,可选space、tab +indent_style = space +# 缩进的空格数 +indent_size = 2 +# 结尾换行符,可选lf、cr、crlf +end_of_line = lf +# 在文件结尾插入新行 +insert_final_newline = true +# 删除一行中的前后空格 +trim_trailing_whitespace = true + +# 匹配md结尾的文件 +[*.md] +insert_final_newline = false +trim_trailing_whitespace = false diff --git a/custom-ui/.env.development b/custom-ui/.env.development new file mode 100644 index 0000000..d74af37 --- /dev/null +++ b/custom-ui/.env.development @@ -0,0 +1,11 @@ +# 页面标题 +VUE_APP_TITLE = 后台管理系统 + +# 开发环境配置 +ENV = 'development' + +# 后台管理系统/开发环境 +VUE_APP_BASE_API = '/dev-api' + +# 路由懒加载 +VUE_CLI_BABEL_TRANSPILE_MODULES = true diff --git a/custom-ui/.env.production b/custom-ui/.env.production new file mode 100644 index 0000000..f617a43 --- /dev/null +++ b/custom-ui/.env.production @@ -0,0 +1,8 @@ +# 页面标题 +VUE_APP_TITLE = 后台管理系统 + +# 生产环境配置 +ENV = 'production' + +# 后台管理系统/生产环境 +VUE_APP_BASE_API = '/prod-api' diff --git a/custom-ui/.env.staging b/custom-ui/.env.staging new file mode 100644 index 0000000..42f8f78 --- /dev/null +++ b/custom-ui/.env.staging @@ -0,0 +1,10 @@ +# 页面标题 +VUE_APP_TITLE = 后台管理系统 + +NODE_ENV = production + +# 测试环境配置 +ENV = 'staging' + +# 后台管理系统/测试环境 +VUE_APP_BASE_API = '/stage-api' diff --git a/custom-ui/.eslintignore b/custom-ui/.eslintignore new file mode 100644 index 0000000..89be6f6 --- /dev/null +++ b/custom-ui/.eslintignore @@ -0,0 +1,10 @@ +# 忽略build目录下类型为js的文件的语法检查 +build/*.js +# 忽略src/assets目录下文件的语法检查 +src/assets +# 忽略public目录下文件的语法检查 +public +# 忽略当前目录下为js的文件的语法检查 +*.js +# 忽略当前目录下为vue的文件的语法检查 +*.vue \ No newline at end of file diff --git a/custom-ui/.eslintrc.js b/custom-ui/.eslintrc.js new file mode 100644 index 0000000..82bbdee --- /dev/null +++ b/custom-ui/.eslintrc.js @@ -0,0 +1,199 @@ +// ESlint 检查配置 +module.exports = { + root: true, + parserOptions: { + parser: 'babel-eslint', + sourceType: 'module' + }, + env: { + browser: true, + node: true, + es6: true, + }, + extends: ['plugin:vue/recommended', 'eslint:recommended'], + + // add your custom rules here + //it is base on https://github.com/vuejs/eslint-config-vue + rules: { + "vue/max-attributes-per-line": [2, { + "singleline": 10, + "multiline": { + "max": 1, + "allowFirstLine": false + } + }], + "vue/singleline-html-element-content-newline": "off", + "vue/multiline-html-element-content-newline":"off", + "vue/name-property-casing": ["error", "PascalCase"], + "vue/no-v-html": "off", + 'accessor-pairs': 2, + 'arrow-spacing': [2, { + 'before': true, + 'after': true + }], + 'block-spacing': [2, 'always'], + 'brace-style': [2, '1tbs', { + 'allowSingleLine': true + }], + 'camelcase': [0, { + 'properties': 'always' + }], + 'comma-dangle': [2, 'never'], + 'comma-spacing': [2, { + 'before': false, + 'after': true + }], + 'comma-style': [2, 'last'], + 'constructor-super': 2, + 'curly': [2, 'multi-line'], + 'dot-location': [2, 'property'], + 'eol-last': 2, + 'eqeqeq': ["error", "always", {"null": "ignore"}], + 'generator-star-spacing': [2, { + 'before': true, + 'after': true + }], + 'handle-callback-err': [2, '^(err|error)$'], + 'indent': [2, 2, { + 'SwitchCase': 1 + }], + 'jsx-quotes': [2, 'prefer-single'], + 'key-spacing': [2, { + 'beforeColon': false, + 'afterColon': true + }], + 'keyword-spacing': [2, { + 'before': true, + 'after': true + }], + 'new-cap': [2, { + 'newIsCap': true, + 'capIsNew': false + }], + 'new-parens': 2, + 'no-array-constructor': 2, + 'no-caller': 2, + 'no-console': 'off', + 'no-class-assign': 2, + 'no-cond-assign': 2, + 'no-const-assign': 2, + 'no-control-regex': 0, + 'no-delete-var': 2, + 'no-dupe-args': 2, + 'no-dupe-class-members': 2, + 'no-dupe-keys': 2, + 'no-duplicate-case': 2, + 'no-empty-character-class': 2, + 'no-empty-pattern': 2, + 'no-eval': 2, + 'no-ex-assign': 2, + 'no-extend-native': 2, + 'no-extra-bind': 2, + 'no-extra-boolean-cast': 2, + 'no-extra-parens': [2, 'functions'], + 'no-fallthrough': 2, + 'no-floating-decimal': 2, + 'no-func-assign': 2, + 'no-implied-eval': 2, + 'no-inner-declarations': [2, 'functions'], + 'no-invalid-regexp': 2, + 'no-irregular-whitespace': 2, + 'no-iterator': 2, + 'no-label-var': 2, + 'no-labels': [2, { + 'allowLoop': false, + 'allowSwitch': false + }], + 'no-lone-blocks': 2, + 'no-mixed-spaces-and-tabs': 2, + 'no-multi-spaces': 2, + 'no-multi-str': 2, + 'no-multiple-empty-lines': [2, { + 'max': 1 + }], + 'no-native-reassign': 2, + 'no-negated-in-lhs': 2, + 'no-new-object': 2, + 'no-new-require': 2, + 'no-new-symbol': 2, + 'no-new-wrappers': 2, + 'no-obj-calls': 2, + 'no-octal': 2, + 'no-octal-escape': 2, + 'no-path-concat': 2, + 'no-proto': 2, + 'no-redeclare': 2, + 'no-regex-spaces': 2, + 'no-return-assign': [2, 'except-parens'], + 'no-self-assign': 2, + 'no-self-compare': 2, + 'no-sequences': 2, + 'no-shadow-restricted-names': 2, + 'no-spaced-func': 2, + 'no-sparse-arrays': 2, + 'no-this-before-super': 2, + 'no-throw-literal': 2, + 'no-trailing-spaces': 2, + 'no-undef': 2, + 'no-undef-init': 2, + 'no-unexpected-multiline': 2, + 'no-unmodified-loop-condition': 2, + 'no-unneeded-ternary': [2, { + 'defaultAssignment': false + }], + 'no-unreachable': 2, + 'no-unsafe-finally': 2, + 'no-unused-vars': [2, { + 'vars': 'all', + 'args': 'none' + }], + 'no-useless-call': 2, + 'no-useless-computed-key': 2, + 'no-useless-constructor': 2, + 'no-useless-escape': 0, + 'no-whitespace-before-property': 2, + 'no-with': 2, + 'one-var': [2, { + 'initialized': 'never' + }], + 'operator-linebreak': [2, 'after', { + 'overrides': { + '?': 'before', + ':': 'before' + } + }], + 'padded-blocks': [2, 'never'], + 'quotes': [2, 'single', { + 'avoidEscape': true, + 'allowTemplateLiterals': true + }], + 'semi': [2, 'never'], + 'semi-spacing': [2, { + 'before': false, + 'after': true + }], + 'space-before-blocks': [2, 'always'], + 'space-before-function-paren': [2, 'never'], + 'space-in-parens': [2, 'never'], + 'space-infix-ops': 2, + 'space-unary-ops': [2, { + 'words': true, + 'nonwords': false + }], + 'spaced-comment': [2, 'always', { + 'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ','] + }], + 'template-curly-spacing': [2, 'never'], + 'use-isnan': 2, + 'valid-typeof': 2, + 'wrap-iife': [2, 'any'], + 'yield-star-spacing': [2, 'both'], + 'yoda': [2, 'never'], + 'prefer-const': 2, + 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0, + 'object-curly-spacing': [2, 'always', { + objectsInObjects: false + }], + 'array-bracket-spacing': [2, 'never'] + } +} diff --git a/custom-ui/README.md b/custom-ui/README.md new file mode 100644 index 0000000..00c0ab8 --- /dev/null +++ b/custom-ui/README.md @@ -0,0 +1,30 @@ +## 开发 + +```bash +# 克隆项目 +git clone https://gitee.com/y_project/RuoYi-Vue + +# 进入项目目录 +cd ruoyi-ui + +# 安装依赖 +npm install + +# 建议不要直接使用 cnpm 安装依赖,会有各种诡异的 bug。可以通过如下操作解决 npm 下载速度慢的问题 +npm install --registry=https://registry.npmmirror.com + +# 启动服务 +npm run dev +``` + +浏览器访问 http://localhost:80 + +## 发布 + +```bash +# 构建测试环境 +npm run build:stage + +# 构建生产环境 +npm run build:prod +``` \ No newline at end of file diff --git a/custom-ui/babel.config.js b/custom-ui/babel.config.js new file mode 100644 index 0000000..c8267b2 --- /dev/null +++ b/custom-ui/babel.config.js @@ -0,0 +1,13 @@ +module.exports = { + presets: [ + // https://github.com/vuejs/vue-cli/tree/master/packages/@vue/babel-preset-app + '@vue/cli-plugin-babel/preset' + ], + 'env': { + 'development': { + // babel-plugin-dynamic-import-node plugin only does one thing by converting all import() to require(). + // This plugin can significantly increase the speed of hot updates, when you have a large number of pages. + 'plugins': ['dynamic-import-node'] + } + } +} \ No newline at end of file diff --git a/custom-ui/bin/build.bat b/custom-ui/bin/build.bat new file mode 100644 index 0000000..dda590d --- /dev/null +++ b/custom-ui/bin/build.bat @@ -0,0 +1,12 @@ +@echo off +echo. +echo [Ϣ] Weḅdistļ +echo. + +%~d0 +cd %~dp0 + +cd .. +npm run build:prod + +pause \ No newline at end of file diff --git a/custom-ui/bin/package.bat b/custom-ui/bin/package.bat new file mode 100644 index 0000000..0e5bc0f --- /dev/null +++ b/custom-ui/bin/package.bat @@ -0,0 +1,12 @@ +@echo off +echo. +echo [Ϣ] װWeḅnode_modulesļ +echo. + +%~d0 +cd %~dp0 + +cd .. +npm install --registry=https://registry.npmmirror.com + +pause \ No newline at end of file diff --git a/custom-ui/bin/run-web.bat b/custom-ui/bin/run-web.bat new file mode 100644 index 0000000..d30deae --- /dev/null +++ b/custom-ui/bin/run-web.bat @@ -0,0 +1,12 @@ +@echo off +echo. +echo [Ϣ] ʹ Vue CLI Web ̡ +echo. + +%~d0 +cd %~dp0 + +cd .. +npm run dev + +pause \ No newline at end of file diff --git a/custom-ui/build/index.js b/custom-ui/build/index.js new file mode 100644 index 0000000..0c57de2 --- /dev/null +++ b/custom-ui/build/index.js @@ -0,0 +1,35 @@ +const { run } = require('runjs') +const chalk = require('chalk') +const config = require('../vue.config.js') +const rawArgv = process.argv.slice(2) +const args = rawArgv.join(' ') + +if (process.env.npm_config_preview || rawArgv.includes('--preview')) { + const report = rawArgv.includes('--report') + + run(`vue-cli-service build ${args}`) + + const port = 9526 + const publicPath = config.publicPath + + var connect = require('connect') + var serveStatic = require('serve-static') + const app = connect() + + app.use( + publicPath, + serveStatic('./dist', { + index: ['index.html', '/'] + }) + ) + + app.listen(port, function () { + console.log(chalk.green(`> Preview at http://localhost:${port}${publicPath}`)) + if (report) { + console.log(chalk.green(`> Report at http://localhost:${port}${publicPath}report.html`)) + } + + }) +} else { + run(`vue-cli-service build ${args}`) +} diff --git a/custom-ui/package-lock.json b/custom-ui/package-lock.json new file mode 100644 index 0000000..78c1b48 --- /dev/null +++ b/custom-ui/package-lock.json @@ -0,0 +1,15631 @@ +{ + "name": "ruoyi", + "version": "3.8.5", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@achrinza/node-ipc": { + "version": "9.2.2", + "resolved": "https://registry.npmmirror.com/@achrinza/node-ipc/-/node-ipc-9.2.2.tgz", + "integrity": "sha512-b90U39dx0cU6emsOvy5hxU4ApNXnE3+Tuo8XQZfiKTGelDwpMwBVgBP7QX6dGTcJgu/miyJuNJ/2naFBliNWEw==", + "dev": true, + "requires": { + "@node-ipc/js-queue": "2.0.3", + "event-pubsub": "4.3.0", + "js-message": "1.0.7" + } + }, + "@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "@babel/code-frame": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.24.6.tgz", + "integrity": "sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.24.6", + "picocolors": "^1.0.0" + } + }, + "@babel/compat-data": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.24.6.tgz", + "integrity": "sha512-aC2DGhBq5eEdyXWqrDInSqQjO0k8xtPRf5YylULqx8MCd6jBtzqfta/3ETMRpuKIc5hyswfO80ObyA1MvkCcUQ==", + "dev": true + }, + "@babel/core": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.24.6.tgz", + "integrity": "sha512-qAHSfAdVyFmIvl0VHELib8xar7ONuSHrE2hLnsaWkYNTI68dmi1x8GYDhJjMI/e7XWal9QBlZkwbOnkcw7Z8gQ==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.6", + "@babel/generator": "^7.24.6", + "@babel/helper-compilation-targets": "^7.24.6", + "@babel/helper-module-transforms": "^7.24.6", + "@babel/helpers": "^7.24.6", + "@babel/parser": "^7.24.6", + "@babel/template": "^7.24.6", + "@babel/traverse": "^7.24.6", + "@babel/types": "^7.24.6", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.24.6.tgz", + "integrity": "sha512-S7m4eNa6YAPJRHmKsLHIDJhNAGNKoWNiWefz1MBbpnt8g9lvMDl1hir4P9bo/57bQEmuwEhnRU/AMWsD0G/Fbg==", + "dev": true, + "requires": { + "@babel/types": "^7.24.6", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.6.tgz", + "integrity": "sha512-DitEzDfOMnd13kZnDqns1ccmftwJTS9DMkyn9pYTxulS7bZxUxpMly3Nf23QQ6NwA4UB8lAqjbqWtyvElEMAkg==", + "dev": true, + "requires": { + "@babel/types": "^7.24.6" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.6.tgz", + "integrity": "sha512-+wnfqc5uHiMYtvRX7qu80Toef8BXeh4HHR1SPeonGb1SKPniNEd4a/nlaJJMv/OIEYvIVavvo0yR7u10Gqz0Iw==", + "dev": true, + "requires": { + "@babel/types": "^7.24.6" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.6.tgz", + "integrity": "sha512-VZQ57UsDGlX/5fFA7GkVPplZhHsVc+vuErWgdOiysI9Ksnw0Pbbd6pnPiR/mmJyKHgyIW0c7KT32gmhiF+cirg==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.24.6", + "@babel/helper-validator-option": "^7.24.6", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.6.tgz", + "integrity": "sha512-djsosdPJVZE6Vsw3kk7IPRWethP94WHGOhQTc67SNXE0ZzMhHgALw8iGmYS0TD1bbMM0VDROy43od7/hN6WYcA==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.24.6", + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-function-name": "^7.24.6", + "@babel/helper-member-expression-to-functions": "^7.24.6", + "@babel/helper-optimise-call-expression": "^7.24.6", + "@babel/helper-replace-supers": "^7.24.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6", + "@babel/helper-split-export-declaration": "^7.24.6", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.6.tgz", + "integrity": "sha512-C875lFBIWWwyv6MHZUG9HmRrlTDgOsLWZfYR0nW69gaKJNe0/Mpxx5r0EID2ZdHQkdUmQo2t0uNckTL08/1BgA==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.24.6", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@babel/helper-define-polyfill-provider": { + "version": "0.6.2", + "resolved": "https://registry.npmmirror.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "dev": true, + "requires": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + } + }, + "@babel/helper-environment-visitor": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.6.tgz", + "integrity": "sha512-Y50Cg3k0LKLMjxdPjIl40SdJgMB85iXn27Vk/qbHZCFx/o5XO3PSnpi675h1KEmmDb6OFArfd5SCQEQ5Q4H88g==", + "dev": true + }, + "@babel/helper-function-name": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-function-name/-/helper-function-name-7.24.6.tgz", + "integrity": "sha512-xpeLqeeRkbxhnYimfr2PC+iA0Q7ljX/d1eZ9/inYbmfG2jpl8Lu3DyXvpOAnrS5kxkfOWJjioIMQsaMBXFI05w==", + "dev": true, + "requires": { + "@babel/template": "^7.24.6", + "@babel/types": "^7.24.6" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.6.tgz", + "integrity": "sha512-SF/EMrC3OD7dSta1bLJIlrsVxwtd0UpjRJqLno6125epQMJ/kyFmpTT4pbvPbdQHzCHg+biQ7Syo8lnDtbR+uA==", + "dev": true, + "requires": { + "@babel/types": "^7.24.6" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.6.tgz", + "integrity": "sha512-OTsCufZTxDUsv2/eDXanw/mUZHWOxSbEmC3pP8cgjcy5rgeVPWWMStnv274DV60JtHxTk0adT0QrCzC4M9NWGg==", + "dev": true, + "requires": { + "@babel/types": "^7.24.6" + } + }, + "@babel/helper-module-imports": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.24.6.tgz", + "integrity": "sha512-a26dmxFJBF62rRO9mmpgrfTLsAuyHk4e1hKTUkD/fcMfynt8gvEKwQPQDVxWhca8dHoDck+55DFt42zV0QMw5g==", + "dev": true, + "requires": { + "@babel/types": "^7.24.6" + } + }, + "@babel/helper-module-transforms": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.24.6.tgz", + "integrity": "sha512-Y/YMPm83mV2HJTbX1Qh2sjgjqcacvOlhbzdCCsSlblOKjSYmQqEbO6rUniWQyRo9ncyfjT8hnUjlG06RXDEmcA==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-module-imports": "^7.24.6", + "@babel/helper-simple-access": "^7.24.6", + "@babel/helper-split-export-declaration": "^7.24.6", + "@babel/helper-validator-identifier": "^7.24.6" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.6.tgz", + "integrity": "sha512-3SFDJRbx7KuPRl8XDUr8O7GAEB8iGyWPjLKJh/ywP/Iy9WOmEfMrsWbaZpvBu2HSYn4KQygIsz0O7m8y10ncMA==", + "dev": true, + "requires": { + "@babel/types": "^7.24.6" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.6.tgz", + "integrity": "sha512-MZG/JcWfxybKwsA9N9PmtF2lOSFSEMVCpIRrbxccZFLJPrJciJdG/UhSh5W96GEteJI2ARqm5UAHxISwRDLSNg==", + "dev": true + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.6.tgz", + "integrity": "sha512-1Qursq9ArRZPAMOZf/nuzVW8HgJLkTB9y9LfP4lW2MVp4e9WkLJDovfKBxoDcCk6VuzIxyqWHyBoaCtSRP10yg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.24.6", + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-wrap-function": "^7.24.6" + } + }, + "@babel/helper-replace-supers": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-replace-supers/-/helper-replace-supers-7.24.6.tgz", + "integrity": "sha512-mRhfPwDqDpba8o1F8ESxsEkJMQkUF8ZIWrAc0FtWhxnjfextxMWxr22RtFizxxSYLjVHDeMgVsRq8BBZR2ikJQ==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-member-expression-to-functions": "^7.24.6", + "@babel/helper-optimise-call-expression": "^7.24.6" + } + }, + "@babel/helper-simple-access": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-simple-access/-/helper-simple-access-7.24.6.tgz", + "integrity": "sha512-nZzcMMD4ZhmB35MOOzQuiGO5RzL6tJbsT37Zx8M5L/i9KSrukGXWTjLe1knIbb/RmxoJE9GON9soq0c0VEMM5g==", + "dev": true, + "requires": { + "@babel/types": "^7.24.6" + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.6.tgz", + "integrity": "sha512-jhbbkK3IUKc4T43WadP96a27oYti9gEf1LdyGSP2rHGH77kwLwfhO7TgwnWvxxQVmke0ImmCSS47vcuxEMGD3Q==", + "dev": true, + "requires": { + "@babel/types": "^7.24.6" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.6.tgz", + "integrity": "sha512-CvLSkwXGWnYlF9+J3iZUvwgAxKiYzK3BWuo+mLzD/MDGOZDj7Gq8+hqaOkMxmJwmlv0iu86uH5fdADd9Hxkymw==", + "dev": true, + "requires": { + "@babel/types": "^7.24.6" + } + }, + "@babel/helper-string-parser": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.24.6.tgz", + "integrity": "sha512-WdJjwMEkmBicq5T9fm/cHND3+UlFa2Yj8ALLgmoSQAJZysYbBjw+azChSGPN4DSPLXOcooGRvDwZWMcF/mLO2Q==", + "dev": true + }, + "@babel/helper-validator-identifier": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.6.tgz", + "integrity": "sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-validator-option/-/helper-validator-option-7.24.6.tgz", + "integrity": "sha512-Jktc8KkF3zIkePb48QO+IapbXlSapOW9S+ogZZkcO6bABgYAxtZcjZ/O005111YLf+j4M84uEgwYoidDkXbCkQ==", + "dev": true + }, + "@babel/helper-wrap-function": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-wrap-function/-/helper-wrap-function-7.24.6.tgz", + "integrity": "sha512-f1JLrlw/jbiNfxvdrfBgio/gRBk3yTAEJWirpAkiJG2Hb22E7cEYKHWo0dFPTv/niPovzIdPdEDetrv6tC6gPQ==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.24.6", + "@babel/template": "^7.24.6", + "@babel/types": "^7.24.6" + } + }, + "@babel/helpers": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.24.6.tgz", + "integrity": "sha512-V2PI+NqnyFu1i0GyTd/O/cTpxzQCYioSkUIRmgo7gFEHKKCg5w46+r/A6WeUR1+P3TeQ49dspGPNd/E3n9AnnA==", + "dev": true, + "requires": { + "@babel/template": "^7.24.6", + "@babel/types": "^7.24.6" + } + }, + "@babel/highlight": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/highlight/-/highlight-7.24.6.tgz", + "integrity": "sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.24.6", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } + } + }, + "@babel/parser": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.24.6.tgz", + "integrity": "sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q==", + "dev": true + }, + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.6.tgz", + "integrity": "sha512-bYndrJ6Ph6Ar+GaB5VAc0JPoP80bQCm4qon6JEzXfRl5QZyQ8Ur1K6k7htxWmPA5z+k7JQvaMUrtXlqclWYzKw==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.6.tgz", + "integrity": "sha512-iVuhb6poq5ikqRq2XWU6OQ+R5o9wF+r/or9CeUyovgptz0UlnK4/seOQ1Istu/XybYjAhQv1FRSSfHHufIku5Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.6.tgz", + "integrity": "sha512-c8TER5xMDYzzFcGqOEp9l4hvB7dcbhcGjcLVwxWfe4P5DOafdwjsBJZKsmv+o3aXh7NhopvayQIovHrh2zSRUQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6", + "@babel/plugin-transform-optional-chaining": "^7.24.6" + } + }, + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.6.tgz", + "integrity": "sha512-z8zEjYmwBUHN/pCF3NuWBhHQjJCrd33qAi8MgANfMrAvn72k2cImT8VjK9LJFu4ysOLJqhfkYYb3MvwANRUNZQ==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-proposal-decorators": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.24.6.tgz", + "integrity": "sha512-8DjR0/DzlBhz2SVi9a19/N2U5+C3y3rseXuyoKL9SP8vnbewscj1eHZtL6kpEn4UCuUmqEo0mvqyDYRFoN2gpA==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-decorators": "^7.24.6" + } + }, + "@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmmirror.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-decorators": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.24.6.tgz", + "integrity": "sha512-gInH8LEqBp+wkwTVihCd/qf+4s28g81FZyvlIbAurHk9eSiItEKG7E0uNK2UdpgsD79aJVAW3R3c85h0YJ0jsw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-import-assertions": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.6.tgz", + "integrity": "sha512-BE6o2BogJKJImTmGpkmOic4V0hlRRxVtzqxiSPa8TIFxyhi4EFjHm08nq1M4STK4RytuLMgnSz0/wfflvGFNOg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-syntax-import-attributes": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.6.tgz", + "integrity": "sha512-D+CfsVZousPXIdudSII7RGy52+dYRtbyKAZcvtQKq/NpsivyMVduepzcLqG5pMBugtMdedxdC8Ramdpcne9ZWQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.6.tgz", + "integrity": "sha512-lWfvAIFNWMlCsU0DRUun2GpFwZdGTukLaHJqRh1JRb80NdAP5Sb1HDHB5X9P9OtgZHQl089UzQkpYlBq2VTPRw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.6.tgz", + "integrity": "sha512-jSSSDt4ZidNMggcLx8SaKsbGNEfIl0PHx/4mFEulorE7bpYLbN0d3pDW3eJ7Y5Z3yPhy3L3NaPCYyTUY7TuugQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-transform-async-generator-functions": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.6.tgz", + "integrity": "sha512-VEP2o4iR2DqQU6KPgizTW2mnMx6BG5b5O9iQdrW9HesLkv8GIA8x2daXBQxw1MrsIkFQGA/iJ204CKoQ8UcnAA==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-remap-async-to-generator": "^7.24.6", + "@babel/plugin-syntax-async-generators": "^7.8.4" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.6.tgz", + "integrity": "sha512-NTBA2SioI3OsHeIn6sQmhvXleSl9T70YY/hostQLveWs0ic+qvbA3fa0kwAwQ0OA/XGaAerNZRQGJyRfhbJK4g==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-remap-async-to-generator": "^7.24.6" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.6.tgz", + "integrity": "sha512-XNW7jolYHW9CwORrZgA/97tL/k05qe/HL0z/qqJq1mdWhwwCM6D4BJBV7wAz9HgFziN5dTOG31znkVIzwxv+vw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.6.tgz", + "integrity": "sha512-S/t1Xh4ehW7sGA7c1j/hiOBLnEYCp/c2sEG4ZkL8kI1xX9tW2pqJTCHKtdhe/jHKt8nG0pFCrDHUXd4DvjHS9w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-transform-class-properties": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.6.tgz", + "integrity": "sha512-j6dZ0Z2Z2slWLR3kt9aOmSIrBvnntWjMDN/TVcMPxhXMLmJVqX605CBRlcGI4b32GMbfifTEsdEjGjiE+j/c3A==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-transform-class-static-block": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.6.tgz", + "integrity": "sha512-1QSRfoPI9RoLRa8Mnakc6v3e0gJxiZQTYrMfLn+mD0sz5+ndSzwymp2hDcYJTyT0MOn0yuWzj8phlIvO72gTHA==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.6.tgz", + "integrity": "sha512-+fN+NO2gh8JtRmDSOB6gaCVo36ha8kfCW1nMq2Gc0DABln0VcHN4PrALDvF5/diLzIRKptC7z/d7Lp64zk92Fg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.24.6", + "@babel/helper-compilation-targets": "^7.24.6", + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-function-name": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-replace-supers": "^7.24.6", + "@babel/helper-split-export-declaration": "^7.24.6", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.6.tgz", + "integrity": "sha512-cRzPobcfRP0ZtuIEkA8QzghoUpSB3X3qSH5W2+FzG+VjWbJXExtx0nbRqwumdBN1x/ot2SlTNQLfBCnPdzp6kg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/template": "^7.24.6" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.6.tgz", + "integrity": "sha512-YLW6AE5LQpk5npNXL7i/O+U9CE4XsBCuRPgyjl1EICZYKmcitV+ayuuUGMJm2lC1WWjXYszeTnIxF/dq/GhIZQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.6.tgz", + "integrity": "sha512-rCXPnSEKvkm/EjzOtLoGvKseK+dS4kZwx1HexO3BtRtgL0fQ34awHn34aeSHuXtZY2F8a1X8xqBBPRtOxDVmcA==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.6.tgz", + "integrity": "sha512-/8Odwp/aVkZwPFJMllSbawhDAO3UJi65foB00HYnK/uXvvCPm0TAXSByjz1mpRmp0q6oX2SIxpkUOpPFHk7FLA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-transform-dynamic-import": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.6.tgz", + "integrity": "sha512-vpq8SSLRTBLOHUZHSnBqVo0AKX3PBaoPs2vVzYVWslXDTDIpwAcCDtfhUcHSQQoYoUvcFPTdC8TZYXu9ZnLT/w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.6.tgz", + "integrity": "sha512-EemYpHtmz0lHE7hxxxYEuTYOOBZ43WkDgZ4arQ4r+VX9QHuNZC+WH3wUWmRNvR8ECpTRne29aZV6XO22qpOtdA==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-transform-export-namespace-from": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.6.tgz", + "integrity": "sha512-inXaTM1SVrIxCkIJ5gqWiozHfFMStuGbGJAxZFBoHcRRdDP0ySLb3jH6JOwmfiinPwyMZqMBX+7NBDCO4z0NSA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.6.tgz", + "integrity": "sha512-n3Sf72TnqK4nw/jziSqEl1qaWPbCRw2CziHH+jdRYvw4J6yeCzsj4jdw8hIntOEeDGTmHVe2w4MVL44PN0GMzg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.6.tgz", + "integrity": "sha512-sOajCu6V0P1KPljWHKiDq6ymgqB+vfo3isUS4McqW1DZtvSVU2v/wuMhmRmkg3sFoq6GMaUUf8W4WtoSLkOV/Q==", + "dev": true, + "requires": { + "@babel/helper-compilation-targets": "^7.24.6", + "@babel/helper-function-name": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-transform-json-strings": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.6.tgz", + "integrity": "sha512-Uvgd9p2gUnzYJxVdBLcU0KurF8aVhkmVyMKW4MIY1/BByvs3EBpv45q01o7pRTVmTvtQq5zDlytP3dcUgm7v9w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-json-strings": "^7.8.3" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.6.tgz", + "integrity": "sha512-f2wHfR2HF6yMj+y+/y07+SLqnOSwRp8KYLpQKOzS58XLVlULhXbiYcygfXQxJlMbhII9+yXDwOUFLf60/TL5tw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-transform-logical-assignment-operators": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.6.tgz", + "integrity": "sha512-EKaWvnezBCMkRIHxMJSIIylzhqK09YpiJtDbr2wsXTwnO0TxyjMUkaw4RlFIZMIS0iDj0KyIg7H7XCguHu/YDA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.6.tgz", + "integrity": "sha512-9g8iV146szUo5GWgXpRbq/GALTnY+WnNuRTuRHWWFfWGbP9ukRL0aO/jpu9dmOPikclkxnNsjY8/gsWl6bmZJQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.6.tgz", + "integrity": "sha512-eAGogjZgcwqAxhyFgqghvoHRr+EYRQPFjUXrTYKBRb5qPnAVxOOglaxc4/byHqjvq/bqO2F3/CGwTHsgKJYHhQ==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.6.tgz", + "integrity": "sha512-JEV8l3MHdmmdb7S7Cmx6rbNEjRCgTQMZxllveHO0mx6uiclB0NflCawlQQ6+o5ZrwjUBYPzHm2XoK4wqGVUFuw==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-simple-access": "^7.24.6" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.6.tgz", + "integrity": "sha512-xg1Z0J5JVYxtpX954XqaaAT6NpAY6LtZXvYFCJmGFJWwtlz2EmJoR8LycFRGNE8dBKizGWkGQZGegtkV8y8s+w==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.24.6", + "@babel/helper-module-transforms": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-validator-identifier": "^7.24.6" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.6.tgz", + "integrity": "sha512-esRCC/KsSEUvrSjv5rFYnjZI6qv4R1e/iHQrqwbZIoRJqk7xCvEUiN7L1XrmW5QSmQe3n1XD88wbgDTWLbVSyg==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.6.tgz", + "integrity": "sha512-6DneiCiu91wm3YiNIGDWZsl6GfTTbspuj/toTEqLh9d4cx50UIzSdg+T96p8DuT7aJOBRhFyaE9ZvTHkXrXr6Q==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.6.tgz", + "integrity": "sha512-f8liz9JG2Va8A4J5ZBuaSdwfPqN6axfWRK+y66fjKYbwf9VBLuq4WxtinhJhvp1w6lamKUwLG0slK2RxqFgvHA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.6.tgz", + "integrity": "sha512-+QlAiZBMsBK5NqrBWFXCYeXyiU1y7BQ/OYaiPAcQJMomn5Tyg+r5WuVtyEuvTbpV7L25ZSLfE+2E9ywj4FD48A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + } + }, + "@babel/plugin-transform-numeric-separator": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.6.tgz", + "integrity": "sha512-6voawq8T25Jvvnc4/rXcWZQKKxUNZcKMS8ZNrjxQqoRFernJJKjE3s18Qo6VFaatG5aiX5JV1oPD7DbJhn0a4Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-transform-object-rest-spread": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.6.tgz", + "integrity": "sha512-OKmi5wiMoRW5Smttne7BwHM8s/fb5JFs+bVGNSeHWzwZkWXWValR1M30jyXo1s/RaqgwwhEC62u4rFH/FBcBPg==", + "dev": true, + "requires": { + "@babel/helper-compilation-targets": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.24.6" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.6.tgz", + "integrity": "sha512-N/C76ihFKlZgKfdkEYKtaRUtXZAgK7sOY4h2qrbVbVTXPrKGIi8aww5WGe/+Wmg8onn8sr2ut6FXlsbu/j6JHg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-replace-supers": "^7.24.6" + } + }, + "@babel/plugin-transform-optional-catch-binding": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.6.tgz", + "integrity": "sha512-L5pZ+b3O1mSzJ71HmxSCmTVd03VOT2GXOigug6vDYJzE5awLI7P1g0wFcdmGuwSDSrQ0L2rDOe/hHws8J1rv3w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + } + }, + "@babel/plugin-transform-optional-chaining": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.6.tgz", + "integrity": "sha512-cHbqF6l1QP11OkYTYQ+hhVx1E017O5ZcSPXk9oODpqhcAD1htsWG2NpHrrhthEO2qZomLK0FXS+u7NfrkF5aOQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.6.tgz", + "integrity": "sha512-ST7guE8vLV+vI70wmAxuZpIKzVjvFX9Qs8bl5w6tN/6gOypPWUmMQL2p7LJz5E63vEGrDhAiYetniJFyBH1RkA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-transform-private-methods": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.6.tgz", + "integrity": "sha512-T9LtDI0BgwXOzyXrvgLTT8DFjCC/XgWLjflczTLXyvxbnSR/gpv0hbmzlHE/kmh9nOvlygbamLKRo6Op4yB6aw==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-transform-private-property-in-object": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.6.tgz", + "integrity": "sha512-Qu/ypFxCY5NkAnEhCF86Mvg3NSabKsh/TPpBVswEdkGl7+FbsYHy1ziRqJpwGH4thBdQHh8zx+z7vMYmcJ7iaQ==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.24.6", + "@babel/helper-create-class-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.6.tgz", + "integrity": "sha512-oARaglxhRsN18OYsnPTpb8TcKQWDYNsPNmTnx5++WOAsUJ0cSC/FZVlIJCKvPbU4yn/UXsS0551CFKJhN0CaMw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.6.tgz", + "integrity": "sha512-SMDxO95I8WXRtXhTAc8t/NFQUT7VYbIWwJCJgEli9ml4MhqUMh4S6hxgH6SmAC3eAQNWCDJFxcFeEt9w2sDdXg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6", + "regenerator-transform": "^0.15.2" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.6.tgz", + "integrity": "sha512-DcrgFXRRlK64dGE0ZFBPD5egM2uM8mgfrvTMOSB2yKzOtjpGegVYkzh3s1zZg1bBck3nkXiaOamJUqK3Syk+4A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-transform-runtime": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.6.tgz", + "integrity": "sha512-W3gQydMb0SY99y/2lV0Okx2xg/8KzmZLQsLaiCmwNRl1kKomz14VurEm+2TossUb+sRvBCnGe+wx8KtIgDtBbQ==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.1", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.6.tgz", + "integrity": "sha512-xnEUvHSMr9eOWS5Al2YPfc32ten7CXdH7Zwyyk7IqITg4nX61oHj+GxpNvl+y5JHjfN3KXE2IV55wAWowBYMVw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.6.tgz", + "integrity": "sha512-h/2j7oIUDjS+ULsIrNZ6/TKG97FgmEk1PXryk/HQq6op4XUUUwif2f69fJrzK0wza2zjCS1xhXmouACaWV5uPA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.6" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.6.tgz", + "integrity": "sha512-fN8OcTLfGmYv7FnDrsjodYBo1DhPL3Pze/9mIIE2MGCT1KgADYIOD7rEglpLHZj8PZlC/JFX5WcD+85FLAQusw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.6.tgz", + "integrity": "sha512-BJbEqJIcKwrqUP+KfUIkxz3q8VzXe2R8Wv8TaNgO1cx+nNavxn/2+H8kp9tgFSOL6wYPPEgFvU6IKS4qoGqhmg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.6.tgz", + "integrity": "sha512-IshCXQ+G9JIFJI7bUpxTE/oA2lgVLAIK8q1KdJNoPXOpvRaNjMySGuvLfBw/Xi2/1lLo953uE8hyYSDW3TSYig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.6.tgz", + "integrity": "sha512-bKl3xxcPbkQQo5eX9LjjDpU2xYHeEeNQbOhj0iPvetSzA+Tu9q/o5lujF4Sek60CM6MgYvOS/DJuwGbiEYAnLw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-transform-unicode-property-regex": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.6.tgz", + "integrity": "sha512-8EIgImzVUxy15cZiPii9GvLZwsy7Vxc+8meSlR3cXFmBIl5W5Tn9LGBf7CDKkHj4uVfNXCJB8RsVfnmY61iedA==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.6.tgz", + "integrity": "sha512-pssN6ExsvxaKU638qcWb81RrvvgZom3jDgU/r5xFZ7TONkZGFf4MhI2ltMb8OcQWhHyxgIavEU+hgqtbKOmsPA==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/plugin-transform-unicode-sets-regex": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.6.tgz", + "integrity": "sha512-quiMsb28oXWIDK0gXLALOJRXLgICLiulqdZGOaPPd0vRT7fQp74NtdADAVu+D8s00C+0Xs0MxVP0VKF/sZEUgw==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6" + } + }, + "@babel/preset-env": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/preset-env/-/preset-env-7.24.6.tgz", + "integrity": "sha512-CrxEAvN7VxfjOG8JNF2Y/eMqMJbZPZ185amwGUBp8D9USK90xQmv7dLdFSa+VbD7fdIqcy/Mfv7WtzG8+/qxKg==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.24.6", + "@babel/helper-compilation-targets": "^7.24.6", + "@babel/helper-plugin-utils": "^7.24.6", + "@babel/helper-validator-option": "^7.24.6", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.6", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.6", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.6", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.6", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.24.6", + "@babel/plugin-syntax-import-attributes": "^7.24.6", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.24.6", + "@babel/plugin-transform-async-generator-functions": "^7.24.6", + "@babel/plugin-transform-async-to-generator": "^7.24.6", + "@babel/plugin-transform-block-scoped-functions": "^7.24.6", + "@babel/plugin-transform-block-scoping": "^7.24.6", + "@babel/plugin-transform-class-properties": "^7.24.6", + "@babel/plugin-transform-class-static-block": "^7.24.6", + "@babel/plugin-transform-classes": "^7.24.6", + "@babel/plugin-transform-computed-properties": "^7.24.6", + "@babel/plugin-transform-destructuring": "^7.24.6", + "@babel/plugin-transform-dotall-regex": "^7.24.6", + "@babel/plugin-transform-duplicate-keys": "^7.24.6", + "@babel/plugin-transform-dynamic-import": "^7.24.6", + "@babel/plugin-transform-exponentiation-operator": "^7.24.6", + "@babel/plugin-transform-export-namespace-from": "^7.24.6", + "@babel/plugin-transform-for-of": "^7.24.6", + "@babel/plugin-transform-function-name": "^7.24.6", + "@babel/plugin-transform-json-strings": "^7.24.6", + "@babel/plugin-transform-literals": "^7.24.6", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.6", + "@babel/plugin-transform-member-expression-literals": "^7.24.6", + "@babel/plugin-transform-modules-amd": "^7.24.6", + "@babel/plugin-transform-modules-commonjs": "^7.24.6", + "@babel/plugin-transform-modules-systemjs": "^7.24.6", + "@babel/plugin-transform-modules-umd": "^7.24.6", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.6", + "@babel/plugin-transform-new-target": "^7.24.6", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.6", + "@babel/plugin-transform-numeric-separator": "^7.24.6", + "@babel/plugin-transform-object-rest-spread": "^7.24.6", + "@babel/plugin-transform-object-super": "^7.24.6", + "@babel/plugin-transform-optional-catch-binding": "^7.24.6", + "@babel/plugin-transform-optional-chaining": "^7.24.6", + "@babel/plugin-transform-parameters": "^7.24.6", + "@babel/plugin-transform-private-methods": "^7.24.6", + "@babel/plugin-transform-private-property-in-object": "^7.24.6", + "@babel/plugin-transform-property-literals": "^7.24.6", + "@babel/plugin-transform-regenerator": "^7.24.6", + "@babel/plugin-transform-reserved-words": "^7.24.6", + "@babel/plugin-transform-shorthand-properties": "^7.24.6", + "@babel/plugin-transform-spread": "^7.24.6", + "@babel/plugin-transform-sticky-regex": "^7.24.6", + "@babel/plugin-transform-template-literals": "^7.24.6", + "@babel/plugin-transform-typeof-symbol": "^7.24.6", + "@babel/plugin-transform-unicode-escapes": "^7.24.6", + "@babel/plugin-transform-unicode-property-regex": "^7.24.6", + "@babel/plugin-transform-unicode-regex": "^7.24.6", + "@babel/plugin-transform-unicode-sets-regex": "^7.24.6", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.4", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.31.0", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmmirror.com/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + } + }, + "@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmmirror.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true + }, + "@babel/runtime": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.24.6.tgz", + "integrity": "sha512-Ja18XcETdEl5mzzACGd+DKgaGJzPTCow7EglgwTmHdwokzDFYh/MHua6lU6DV/hjF2IaOJ4oX2nqnjG7RElKOw==", + "requires": { + "regenerator-runtime": "^0.14.0" + } + }, + "@babel/template": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/template/-/template-7.24.6.tgz", + "integrity": "sha512-3vgazJlLwNXi9jhrR1ef8qiB65L1RK90+lEQwv4OxveHnqC3BfmnHdgySwRLzf6akhlOYenT+b7AfWq+a//AHw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.24.6", + "@babel/parser": "^7.24.6", + "@babel/types": "^7.24.6" + } + }, + "@babel/traverse": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.24.6.tgz", + "integrity": "sha512-OsNjaJwT9Zn8ozxcfoBc+RaHdj3gFmCmYoQLUII1o6ZrUwku0BMg80FoOTPx+Gi6XhcQxAYE4xyjPTo4SxEQqw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.24.6", + "@babel/generator": "^7.24.6", + "@babel/helper-environment-visitor": "^7.24.6", + "@babel/helper-function-name": "^7.24.6", + "@babel/helper-hoist-variables": "^7.24.6", + "@babel/helper-split-export-declaration": "^7.24.6", + "@babel/parser": "^7.24.6", + "@babel/types": "^7.24.6", + "debug": "^4.3.1", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.24.6", + "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.24.6.tgz", + "integrity": "sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ==", + "dev": true, + "requires": { + "@babel/helper-string-parser": "^7.24.6", + "@babel/helper-validator-identifier": "^7.24.6", + "to-fast-properties": "^2.0.0" + } + }, + "@eslint/eslintrc": { + "version": "0.2.2", + "resolved": "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-0.2.2.tgz", + "integrity": "sha512-EfB5OHNYp1F4px/LI/FEnGylop7nOqkQ1LRzCM0KccA2U8tvV8w01KBv37LbO7nW4H+YhKyo2LcJhRwjjV17QQ==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "lodash": "^4.17.19", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmmirror.com/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + } + } + }, + "@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmmirror.com/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "dev": true + }, + "@hapi/address": { + "version": "2.1.4", + "resolved": "https://registry.npmmirror.com/@hapi/address/-/address-2.1.4.tgz", + "integrity": "sha512-QD1PhQk+s31P1ixsX0H0Suoupp3VMXzIVMSwobR3F3MSUO2YCV0B7xqLcUw/Bh8yuvd3LhpyqLQWTNcRmp6IdQ==", + "dev": true + }, + "@hapi/bourne": { + "version": "1.3.2", + "resolved": "https://registry.npmmirror.com/@hapi/bourne/-/bourne-1.3.2.tgz", + "integrity": "sha512-1dVNHT76Uu5N3eJNTYcvxee+jzX4Z9lfciqRRHCU27ihbUcYi+iSc2iml5Ke1LXe1SyJCLA0+14Jh4tXJgOppA==", + "dev": true + }, + "@hapi/hoek": { + "version": "8.5.1", + "resolved": "https://registry.npmmirror.com/@hapi/hoek/-/hoek-8.5.1.tgz", + "integrity": "sha512-yN7kbciD87WzLGc5539Tn0sApjyiGHAJgKvG9W8C7O+6c7qmoQMfVs0W4bX17eqz6C78QJqqFrtgdK5EWf6Qow==", + "dev": true + }, + "@hapi/joi": { + "version": "15.1.1", + "resolved": "https://registry.npmmirror.com/@hapi/joi/-/joi-15.1.1.tgz", + "integrity": "sha512-entf8ZMOK8sc+8YfeOlM8pCfg3b5+WZIKBfUaaJT8UsjAAPjartzxIYm3TIbjvA4u+u++KbcXD38k682nVHDAQ==", + "dev": true, + "requires": { + "@hapi/address": "2.x.x", + "@hapi/bourne": "1.x.x", + "@hapi/hoek": "8.x.x", + "@hapi/topo": "3.x.x" + } + }, + "@hapi/topo": { + "version": "3.1.6", + "resolved": "https://registry.npmmirror.com/@hapi/topo/-/topo-3.1.6.tgz", + "integrity": "sha512-tAag0jEcjwH+P2quUfipd7liWCNX2F8NvYjQp2wtInsZxnMlypdw0FtAOLxtvvkO+GSRRbmNi8m/5y42PQJYCQ==", + "dev": true, + "requires": { + "@hapi/hoek": "^8.3.0" + } + }, + "@intervolga/optimize-cssnano-plugin": { + "version": "1.0.6", + "resolved": "https://registry.npmmirror.com/@intervolga/optimize-cssnano-plugin/-/optimize-cssnano-plugin-1.0.6.tgz", + "integrity": "sha512-zN69TnSr0viRSU6cEDIcuPcP67QcpQ6uHACg58FiN9PDrU6SLyGW3MR4tiISbYxy1kDWAVPwD+XwQTWE5cigAA==", + "dev": true, + "requires": { + "cssnano": "^4.0.0", + "cssnano-preset-default": "^4.0.0", + "postcss": "^7.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "@mrmlnc/readdir-enhanced": { + "version": "2.2.1", + "resolved": "https://registry.npmmirror.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", + "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", + "dev": true, + "requires": { + "call-me-maybe": "^1.0.1", + "glob-to-regexp": "^0.3.0" + } + }, + "@node-ipc/js-queue": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/@node-ipc/js-queue/-/js-queue-2.0.3.tgz", + "integrity": "sha512-fL1wpr8hhD5gT2dA1qifeVaoDFlQR5es8tFuKqjHX+kdOtdNHnxkVZbtIrR2rxnMFvehkjaZRNV2H/gPXlb0hw==", + "dev": true, + "requires": { + "easy-stack": "1.0.1" + } + }, + "@nodelib/fs.stat": { + "version": "1.1.3", + "resolved": "https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", + "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", + "dev": true + }, + "@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "dev": true, + "requires": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + }, + "dependencies": { + "semver": { + "version": "7.6.2", + "resolved": "https://registry.npmmirror.com/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true + } + } + }, + "@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "dev": true, + "requires": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "dependencies": { + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "@riophae/vue-treeselect": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/@riophae/vue-treeselect/-/vue-treeselect-0.4.0.tgz", + "integrity": "sha512-J4atYmBqXQmiPFK/0B5sXKjtnGc21mBJEiyKIDZwk0Q9XuynVFX6IJ4EpaLmUgL5Tve7HAS7wkiGGSti6Uaxcg==", + "requires": { + "@babel/runtime": "^7.3.1", + "babel-helper-vue-jsx-merge-props": "^2.0.3", + "easings-css": "^1.0.0", + "fuzzysearch": "^1.0.3", + "is-promise": "^2.1.0", + "lodash": "^4.0.0", + "material-colors": "^1.2.6", + "watch-size": "^2.0.0" + } + }, + "@soda/friendly-errors-webpack-plugin": { + "version": "1.8.1", + "resolved": "https://registry.npmmirror.com/@soda/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.8.1.tgz", + "integrity": "sha512-h2ooWqP8XuFqTXT+NyAFbrArzfQA7R6HTezADrvD9Re8fxMLTPPniLdqVTdDaO0eIoLaAwKT+d6w+5GeTk7Vbg==", + "dev": true, + "requires": { + "chalk": "^3.0.0", + "error-stack-parser": "^2.0.6", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@soda/get-current-script": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/@soda/get-current-script/-/get-current-script-1.0.2.tgz", + "integrity": "sha512-T7VNNlYVM1SgQ+VsMYhnDkcGmWhQdL0bDyGm5TlQ3GBXnJscEClUUOKduWTmm2zCnvNLC1hc3JpuXjs/nFOc5w==", + "dev": true + }, + "@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmmirror.com/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "dev": true, + "requires": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "dev": true + }, + "@types/node": { + "version": "20.12.12", + "resolved": "https://registry.npmmirror.com/@types/node/-/node-20.12.12.tgz", + "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==", + "dev": true, + "requires": { + "undici-types": "~5.26.4" + } + }, + "@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmmirror.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true + }, + "@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "dev": true + }, + "@types/q": { + "version": "1.5.8", + "resolved": "https://registry.npmmirror.com/@types/q/-/q-1.5.8.tgz", + "integrity": "sha512-hroOstUScF6zhIi+5+x0dzqrHA1EJi+Irri6b1fxolMTqqHIV/Cg77EtnQcZqZCu8hR3mX2BzIxN4/GzI68Kfw==", + "dev": true + }, + "@vue/babel-helper-vue-jsx-merge-props": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.4.0.tgz", + "integrity": "sha512-JkqXfCkUDp4PIlFdDQ0TdXoIejMtTHP67/pvxlgeY+u5k3LEdKuWZ3LK6xkxo52uDoABIVyRwqVkfLQJhk7VBA==", + "dev": true + }, + "@vue/babel-helper-vue-transform-on": { + "version": "1.2.2", + "resolved": "https://registry.npmmirror.com/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.2.2.tgz", + "integrity": "sha512-nOttamHUR3YzdEqdM/XXDyCSdxMA9VizUKoroLX6yTyRtggzQMHXcmwh8a7ZErcJttIBIc9s68a1B8GZ+Dmvsw==", + "dev": true + }, + "@vue/babel-plugin-jsx": { + "version": "1.2.2", + "resolved": "https://registry.npmmirror.com/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.2.2.tgz", + "integrity": "sha512-nYTkZUVTu4nhP199UoORePsql0l+wj7v/oyQjtThUVhJl1U+6qHuoVhIvR3bf7eVKjbCK+Cs2AWd7mi9Mpz9rA==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "~7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-jsx": "^7.23.3", + "@babel/template": "^7.23.9", + "@babel/traverse": "^7.23.9", + "@babel/types": "^7.23.9", + "@vue/babel-helper-vue-transform-on": "1.2.2", + "@vue/babel-plugin-resolve-type": "1.2.2", + "camelcase": "^6.3.0", + "html-tags": "^3.3.1", + "svg-tags": "^1.0.0" + }, + "dependencies": { + "@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dev": true, + "requires": { + "@babel/types": "^7.22.15" + } + } + } + }, + "@vue/babel-plugin-resolve-type": { + "version": "1.2.2", + "resolved": "https://registry.npmmirror.com/@vue/babel-plugin-resolve-type/-/babel-plugin-resolve-type-1.2.2.tgz", + "integrity": "sha512-EntyroPwNg5IPVdUJupqs0CFzuf6lUrVvCspmv2J1FITLeGnUCuoGNNk78dgCusxEiYj6RMkTJflGSxk5aIC4A==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.23.5", + "@babel/helper-module-imports": "~7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/parser": "^7.23.9", + "@vue/compiler-sfc": "^3.4.15" + }, + "dependencies": { + "@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dev": true, + "requires": { + "@babel/types": "^7.22.15" + } + } + } + }, + "@vue/babel-plugin-transform-vue-jsx": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/@vue/babel-plugin-transform-vue-jsx/-/babel-plugin-transform-vue-jsx-1.4.0.tgz", + "integrity": "sha512-Fmastxw4MMx0vlgLS4XBX0XiBbUFzoMGeVXuMV08wyOfXdikAFqBTuYPR0tlk+XskL19EzHc39SgjrPGY23JnA==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/plugin-syntax-jsx": "^7.2.0", + "@vue/babel-helper-vue-jsx-merge-props": "^1.4.0", + "html-tags": "^2.0.0", + "lodash.kebabcase": "^4.1.1", + "svg-tags": "^1.0.0" + }, + "dependencies": { + "html-tags": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/html-tags/-/html-tags-2.0.0.tgz", + "integrity": "sha512-+Il6N8cCo2wB/Vd3gqy/8TZhTD3QvcVeQLCnZiGkGCH3JP28IgGAY41giccp2W4R3jfyJPAP318FQTa1yU7K7g==", + "dev": true + } + } + }, + "@vue/babel-preset-app": { + "version": "4.5.19", + "resolved": "https://registry.npmmirror.com/@vue/babel-preset-app/-/babel-preset-app-4.5.19.tgz", + "integrity": "sha512-VCNRiAt2P/bLo09rYt3DLe6xXUMlhJwrvU18Ddd/lYJgC7s8+wvhgYs+MTx4OiAXdu58drGwSBO9SPx7C6J82Q==", + "dev": true, + "requires": { + "@babel/core": "^7.11.0", + "@babel/helper-compilation-targets": "^7.9.6", + "@babel/helper-module-imports": "^7.8.3", + "@babel/plugin-proposal-class-properties": "^7.8.3", + "@babel/plugin-proposal-decorators": "^7.8.3", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-jsx": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.11.0", + "@babel/preset-env": "^7.11.0", + "@babel/runtime": "^7.11.0", + "@vue/babel-plugin-jsx": "^1.0.3", + "@vue/babel-preset-jsx": "^1.2.4", + "babel-plugin-dynamic-import-node": "^2.3.3", + "core-js": "^3.6.5", + "core-js-compat": "^3.6.5", + "semver": "^6.1.0" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@vue/babel-preset-jsx": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/@vue/babel-preset-jsx/-/babel-preset-jsx-1.4.0.tgz", + "integrity": "sha512-QmfRpssBOPZWL5xw7fOuHNifCQcNQC1PrOo/4fu6xlhlKJJKSA3HqX92Nvgyx8fqHZTUGMPHmFA+IDqwXlqkSA==", + "dev": true, + "requires": { + "@vue/babel-helper-vue-jsx-merge-props": "^1.4.0", + "@vue/babel-plugin-transform-vue-jsx": "^1.4.0", + "@vue/babel-sugar-composition-api-inject-h": "^1.4.0", + "@vue/babel-sugar-composition-api-render-instance": "^1.4.0", + "@vue/babel-sugar-functional-vue": "^1.4.0", + "@vue/babel-sugar-inject-h": "^1.4.0", + "@vue/babel-sugar-v-model": "^1.4.0", + "@vue/babel-sugar-v-on": "^1.4.0" + } + }, + "@vue/babel-sugar-composition-api-inject-h": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/@vue/babel-sugar-composition-api-inject-h/-/babel-sugar-composition-api-inject-h-1.4.0.tgz", + "integrity": "sha512-VQq6zEddJHctnG4w3TfmlVp5FzDavUSut/DwR0xVoe/mJKXyMcsIibL42wPntozITEoY90aBV0/1d2KjxHU52g==", + "dev": true, + "requires": { + "@babel/plugin-syntax-jsx": "^7.2.0" + } + }, + "@vue/babel-sugar-composition-api-render-instance": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/@vue/babel-sugar-composition-api-render-instance/-/babel-sugar-composition-api-render-instance-1.4.0.tgz", + "integrity": "sha512-6ZDAzcxvy7VcnCjNdHJ59mwK02ZFuP5CnucloidqlZwVQv5CQLijc3lGpR7MD3TWFi78J7+a8J56YxbCtHgT9Q==", + "dev": true, + "requires": { + "@babel/plugin-syntax-jsx": "^7.2.0" + } + }, + "@vue/babel-sugar-functional-vue": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/@vue/babel-sugar-functional-vue/-/babel-sugar-functional-vue-1.4.0.tgz", + "integrity": "sha512-lTEB4WUFNzYt2In6JsoF9sAYVTo84wC4e+PoZWSgM6FUtqRJz7wMylaEhSRgG71YF+wfLD6cc9nqVeXN2rwBvw==", + "dev": true, + "requires": { + "@babel/plugin-syntax-jsx": "^7.2.0" + } + }, + "@vue/babel-sugar-inject-h": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/@vue/babel-sugar-inject-h/-/babel-sugar-inject-h-1.4.0.tgz", + "integrity": "sha512-muwWrPKli77uO2fFM7eA3G1lAGnERuSz2NgAxuOLzrsTlQl8W4G+wwbM4nB6iewlKbwKRae3nL03UaF5ffAPMA==", + "dev": true, + "requires": { + "@babel/plugin-syntax-jsx": "^7.2.0" + } + }, + "@vue/babel-sugar-v-model": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/@vue/babel-sugar-v-model/-/babel-sugar-v-model-1.4.0.tgz", + "integrity": "sha512-0t4HGgXb7WHYLBciZzN5s0Hzqan4Ue+p/3FdQdcaHAb7s5D9WZFGoSxEZHrR1TFVZlAPu1bejTKGeAzaaG3NCQ==", + "dev": true, + "requires": { + "@babel/plugin-syntax-jsx": "^7.2.0", + "@vue/babel-helper-vue-jsx-merge-props": "^1.4.0", + "@vue/babel-plugin-transform-vue-jsx": "^1.4.0", + "camelcase": "^5.0.0", + "html-tags": "^2.0.0", + "svg-tags": "^1.0.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmmirror.com/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "html-tags": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/html-tags/-/html-tags-2.0.0.tgz", + "integrity": "sha512-+Il6N8cCo2wB/Vd3gqy/8TZhTD3QvcVeQLCnZiGkGCH3JP28IgGAY41giccp2W4R3jfyJPAP318FQTa1yU7K7g==", + "dev": true + } + } + }, + "@vue/babel-sugar-v-on": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/@vue/babel-sugar-v-on/-/babel-sugar-v-on-1.4.0.tgz", + "integrity": "sha512-m+zud4wKLzSKgQrWwhqRObWzmTuyzl6vOP7024lrpeJM4x2UhQtRDLgYjXAw9xBXjCwS0pP9kXjg91F9ZNo9JA==", + "dev": true, + "requires": { + "@babel/plugin-syntax-jsx": "^7.2.0", + "@vue/babel-plugin-transform-vue-jsx": "^1.4.0", + "camelcase": "^5.0.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmmirror.com/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + } + } + }, + "@vue/cli-overlay": { + "version": "4.5.19", + "resolved": "https://registry.npmmirror.com/@vue/cli-overlay/-/cli-overlay-4.5.19.tgz", + "integrity": "sha512-GdxvNSmOw7NHIazCO8gTK+xZbaOmScTtxj6eHVeMbYpDYVPJ+th3VMLWNpw/b6uOjwzzcyKlA5dRQ1DAb+gF/g==", + "dev": true + }, + "@vue/cli-plugin-babel": { + "version": "4.4.6", + "resolved": "https://registry.npmmirror.com/@vue/cli-plugin-babel/-/cli-plugin-babel-4.4.6.tgz", + "integrity": "sha512-9cX9mN+4DIbcqw3rV6UBOA0t5zikIkrBLQloUzsOBOu5Xb7/UoD7inInFj7bnyHUflr5LqbdWJ+etCQcWAIIXA==", + "dev": true, + "requires": { + "@babel/core": "^7.9.6", + "@vue/babel-preset-app": "^4.4.6", + "@vue/cli-shared-utils": "^4.4.6", + "babel-loader": "^8.1.0", + "cache-loader": "^4.1.0", + "thread-loader": "^2.1.3", + "webpack": "^4.0.0" + } + }, + "@vue/cli-plugin-eslint": { + "version": "4.4.6", + "resolved": "https://registry.npmmirror.com/@vue/cli-plugin-eslint/-/cli-plugin-eslint-4.4.6.tgz", + "integrity": "sha512-3a9rVpOKPQsDgAlRkhmBMHboGobivG/47BbQGE66Z8YJxrgF/AWikP3Jy67SmxtszRkyiWfw4aJFRV9r3MzffQ==", + "dev": true, + "requires": { + "@vue/cli-shared-utils": "^4.4.6", + "eslint-loader": "^2.2.1", + "globby": "^9.2.0", + "inquirer": "^7.1.0", + "webpack": "^4.0.0", + "yorkie": "^2.0.0" + } + }, + "@vue/cli-plugin-router": { + "version": "4.5.19", + "resolved": "https://registry.npmmirror.com/@vue/cli-plugin-router/-/cli-plugin-router-4.5.19.tgz", + "integrity": "sha512-3icGzH1IbVYmMMsOwYa0lal/gtvZLebFXdE5hcQJo2mnTwngXGMTyYAzL56EgHBPjbMmRpyj6Iw9k4aVInVX6A==", + "dev": true, + "requires": { + "@vue/cli-shared-utils": "^4.5.19" + } + }, + "@vue/cli-plugin-vuex": { + "version": "4.5.19", + "resolved": "https://registry.npmmirror.com/@vue/cli-plugin-vuex/-/cli-plugin-vuex-4.5.19.tgz", + "integrity": "sha512-DUmfdkG3pCdkP7Iznd87RfE9Qm42mgp2hcrNcYQYSru1W1gX2dG/JcW8bxmeGSa06lsxi9LEIc/QD1yPajSCZw==", + "dev": true + }, + "@vue/cli-service": { + "version": "4.4.6", + "resolved": "https://registry.npmmirror.com/@vue/cli-service/-/cli-service-4.4.6.tgz", + "integrity": "sha512-k5OFGh2NnvRymCyq9DfBiNJvECUuun3pl5KMm3557IZyA5E5csv+RHoSW3dX8HHe0zXq18g52VswP1llvR9POw==", + "dev": true, + "requires": { + "@intervolga/optimize-cssnano-plugin": "^1.0.5", + "@soda/friendly-errors-webpack-plugin": "^1.7.1", + "@soda/get-current-script": "^1.0.0", + "@vue/cli-overlay": "^4.4.6", + "@vue/cli-plugin-router": "^4.4.6", + "@vue/cli-plugin-vuex": "^4.4.6", + "@vue/cli-shared-utils": "^4.4.6", + "@vue/component-compiler-utils": "^3.1.2", + "@vue/preload-webpack-plugin": "^1.1.0", + "@vue/web-component-wrapper": "^1.2.0", + "acorn": "^7.2.0", + "acorn-walk": "^7.1.1", + "address": "^1.1.2", + "autoprefixer": "^9.8.0", + "browserslist": "^4.12.0", + "cache-loader": "^4.1.0", + "case-sensitive-paths-webpack-plugin": "^2.3.0", + "cli-highlight": "^2.1.4", + "clipboardy": "^2.3.0", + "cliui": "^6.0.0", + "copy-webpack-plugin": "^5.1.1", + "css-loader": "^3.5.3", + "cssnano": "^4.1.10", + "debug": "^4.1.1", + "default-gateway": "^5.0.5", + "dotenv": "^8.2.0", + "dotenv-expand": "^5.1.0", + "file-loader": "^4.2.0", + "fs-extra": "^7.0.1", + "globby": "^9.2.0", + "hash-sum": "^2.0.0", + "html-webpack-plugin": "^3.2.0", + "launch-editor-middleware": "^2.2.1", + "lodash.defaultsdeep": "^4.6.1", + "lodash.mapvalues": "^4.6.0", + "lodash.transform": "^4.6.0", + "mini-css-extract-plugin": "^0.9.0", + "minimist": "^1.2.5", + "pnp-webpack-plugin": "^1.6.4", + "portfinder": "^1.0.26", + "postcss-loader": "^3.0.0", + "ssri": "^7.1.0", + "terser-webpack-plugin": "^2.3.6", + "thread-loader": "^2.1.3", + "url-loader": "^2.2.0", + "vue-loader": "^15.9.2", + "vue-style-loader": "^4.1.2", + "webpack": "^4.0.0", + "webpack-bundle-analyzer": "^3.8.0", + "webpack-chain": "^6.4.0", + "webpack-dev-server": "^3.11.0", + "webpack-merge": "^4.2.2" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmmirror.com/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "cacache": { + "version": "13.0.1", + "resolved": "https://registry.npmmirror.com/cacache/-/cacache-13.0.1.tgz", + "integrity": "sha512-5ZvAxd05HDDU+y9BVvcqYu2LLXmPnQ0hW62h32g4xBTgL/MppR4/04NHfj/ycM2y6lmTnbw6HVi+1eN0Psba6w==", + "dev": true, + "requires": { + "chownr": "^1.1.2", + "figgy-pudding": "^3.5.1", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.2", + "infer-owner": "^1.0.4", + "lru-cache": "^5.1.1", + "minipass": "^3.0.0", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "p-map": "^3.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^2.7.1", + "ssri": "^7.0.0", + "unique-filename": "^1.1.1" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "ssri": { + "version": "7.1.1", + "resolved": "https://registry.npmmirror.com/ssri/-/ssri-7.1.1.tgz", + "integrity": "sha512-w+daCzXN89PseTL99MkA+fxJEcU3wfaE/ah0i0lnOlpG1CYLJ2ZjzEry68YBKfLs4JfoTShrTEsJkAZuNZ/stw==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1", + "minipass": "^3.1.1" + } + }, + "terser-webpack-plugin": { + "version": "2.3.8", + "resolved": "https://registry.npmmirror.com/terser-webpack-plugin/-/terser-webpack-plugin-2.3.8.tgz", + "integrity": "sha512-/fKw3R+hWyHfYx7Bv6oPqmk4HGQcrWLtV3X6ggvPuwPNHSnzvVV51z6OaaCOus4YLjutYGOz3pEpbhe6Up2s1w==", + "dev": true, + "requires": { + "cacache": "^13.0.1", + "find-cache-dir": "^3.3.1", + "jest-worker": "^25.4.0", + "p-limit": "^2.3.0", + "schema-utils": "^2.6.6", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.6.12", + "webpack-sources": "^1.4.3" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "@vue/cli-shared-utils": { + "version": "4.5.19", + "resolved": "https://registry.npmmirror.com/@vue/cli-shared-utils/-/cli-shared-utils-4.5.19.tgz", + "integrity": "sha512-JYpdsrC/d9elerKxbEUtmSSU6QRM60rirVubOewECHkBHj+tLNznWq/EhCjswywtePyLaMUK25eTqnTSZlEE+g==", + "dev": true, + "requires": { + "@achrinza/node-ipc": "9.2.2", + "@hapi/joi": "^15.0.1", + "chalk": "^2.4.2", + "execa": "^1.0.0", + "launch-editor": "^2.2.1", + "lru-cache": "^5.1.1", + "open": "^6.3.0", + "ora": "^3.4.0", + "read-pkg": "^5.1.1", + "request": "^2.88.2", + "semver": "^6.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "@vue/compiler-core": { + "version": "3.4.27", + "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.4.27.tgz", + "integrity": "sha512-E+RyqY24KnyDXsCuQrI+mlcdW3ALND6U7Gqa/+bVwbcpcR3BRRIckFoz7Qyd4TTlnugtwuI7YgjbvsLmxb+yvg==", + "dev": true, + "requires": { + "@babel/parser": "^7.24.4", + "@vue/shared": "3.4.27", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.0" + } + }, + "@vue/compiler-dom": { + "version": "3.4.27", + "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.4.27.tgz", + "integrity": "sha512-kUTvochG/oVgE1w5ViSr3KUBh9X7CWirebA3bezTbB5ZKBQZwR2Mwj9uoSKRMFcz4gSMzzLXBPD6KpCLb9nvWw==", + "dev": true, + "requires": { + "@vue/compiler-core": "3.4.27", + "@vue/shared": "3.4.27" + } + }, + "@vue/compiler-sfc": { + "version": "3.4.27", + "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.4.27.tgz", + "integrity": "sha512-nDwntUEADssW8e0rrmE0+OrONwmRlegDA1pD6QhVeXxjIytV03yDqTey9SBDiALsvAd5U4ZrEKbMyVXhX6mCGA==", + "dev": true, + "requires": { + "@babel/parser": "^7.24.4", + "@vue/compiler-core": "3.4.27", + "@vue/compiler-dom": "3.4.27", + "@vue/compiler-ssr": "3.4.27", + "@vue/shared": "3.4.27", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.10", + "postcss": "^8.4.38", + "source-map-js": "^1.2.0" + } + }, + "@vue/compiler-ssr": { + "version": "3.4.27", + "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.4.27.tgz", + "integrity": "sha512-CVRzSJIltzMG5FcidsW0jKNQnNRYC8bT21VegyMMtHmhW3UOI7knmUehzswXLrExDLE6lQCZdrhD4ogI7c+vuw==", + "dev": true, + "requires": { + "@vue/compiler-dom": "3.4.27", + "@vue/shared": "3.4.27" + } + }, + "@vue/component-compiler-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmmirror.com/@vue/component-compiler-utils/-/component-compiler-utils-3.3.0.tgz", + "integrity": "sha512-97sfH2mYNU+2PzGrmK2haqffDpVASuib9/w2/noxiFi31Z54hW+q3izKQXXQZSNhtiUpAI36uSuYepeBe4wpHQ==", + "dev": true, + "requires": { + "consolidate": "^0.15.1", + "hash-sum": "^1.0.2", + "lru-cache": "^4.1.2", + "merge-source-map": "^1.1.0", + "postcss": "^7.0.36", + "postcss-selector-parser": "^6.0.2", + "prettier": "^1.18.2 || ^2.0.0", + "source-map": "~0.6.1", + "vue-template-es2015-compiler": "^1.9.0" + }, + "dependencies": { + "hash-sum": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/hash-sum/-/hash-sum-1.0.2.tgz", + "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==", + "dev": true + }, + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "@vue/preload-webpack-plugin": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/@vue/preload-webpack-plugin/-/preload-webpack-plugin-1.1.2.tgz", + "integrity": "sha512-LIZMuJk38pk9U9Ur4YzHjlIyMuxPlACdBIHH9/nGYVTsaGKOSnSuELiE8vS9wa+dJpIYspYUOqk+L1Q4pgHQHQ==", + "dev": true + }, + "@vue/shared": { + "version": "3.4.27", + "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.4.27.tgz", + "integrity": "sha512-DL3NmY2OFlqmYYrzp39yi3LDkKxa5vZVwxWdQ3rG0ekuWscHraeIbnI8t+aZK7qhYqEqWKTUdijadunb9pnrgA==", + "dev": true + }, + "@vue/web-component-wrapper": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/@vue/web-component-wrapper/-/web-component-wrapper-1.3.0.tgz", + "integrity": "sha512-Iu8Tbg3f+emIIMmI2ycSI8QcEuAUgPTgHwesDU1eKMLE4YC/c/sFbGc70QgMq31ijRftV0R7vCm9co6rldCeOA==", + "dev": true + }, + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", + "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", + "dev": true + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.9.0", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", + "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", + "dev": true, + "requires": { + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.9.0", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", + "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==", + "dev": true + }, + "@webassemblyjs/helper-module-context": { + "version": "1.9.0", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", + "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", + "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/floating-point-hex-parser": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-code-frame": "1.9.0", + "@webassemblyjs/helper-fsm": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmmirror.com/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmmirror.com/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmmirror.com/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmmirror.com/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmmirror.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmmirror.com/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true + }, + "address": { + "version": "1.2.2", + "resolved": "https://registry.npmmirror.com/address/-/address-1.2.2.tgz", + "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", + "dev": true + }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "dev": true + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true + }, + "alphanum-sort": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz", + "integrity": "sha512-0FcBfdcmaumGPQ0qPn7Q5qTgz/ooXgIyp1rf8ik5bGX8mpE2YHjC0P/eyQvxu1GURYQgq9ozf2mteQ5ZD9YiyQ==", + "dev": true + }, + "ansi-colors": { + "version": "3.2.4", + "resolved": "https://registry.npmmirror.com/ansi-colors/-/ansi-colors-3.2.4.tgz", + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", + "dev": true + }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmmirror.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "requires": { + "type-fest": "^0.21.3" + }, + "dependencies": { + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true + } + } + }, + "ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmmirror.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "dev": true + }, + "ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true + }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "arch": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmmirror.com/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", + "dev": true + }, + "array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "requires": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmmirror.com/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==", + "dev": true + }, + "array.prototype.reduce": { + "version": "1.0.7", + "resolved": "https://registry.npmmirror.com/array.prototype.reduce/-/array.prototype.reduce-1.0.7.tgz", + "integrity": "sha512-mzmiUCVwtiD4lgxYP8g7IYy8El8p2CSMePvIbTS7gchKir/L1fgJrk0yDKmAX6mnRQFKNADYIk8nNlTris5H1Q==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-array-method-boxes-properly": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "is-string": "^1.0.7" + } + }, + "arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "requires": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + } + }, + "asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmmirror.com/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmmirror.com/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmmirror.com/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "assert": { + "version": "1.5.1", + "resolved": "https://registry.npmmirror.com/assert/-/assert-1.5.1.tgz", + "integrity": "sha512-zzw1uCAgLbsKwBfFc8CX78DDg+xZeBksSO3vwVIDDN5i94eOrPsSSyiVhmsSABFDM/OcpE2aagCat9dnWQLG1A==", + "dev": true, + "requires": { + "object.assign": "^4.1.4", + "util": "^0.10.4" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + }, + "util": { + "version": "0.10.4", + "resolved": "https://registry.npmmirror.com/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + } + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", + "dev": true + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, + "async": { + "version": "2.6.4", + "resolved": "https://registry.npmmirror.com/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "async-each": { + "version": "1.0.6", + "resolved": "https://registry.npmmirror.com/async-each/-/async-each-1.0.6.tgz", + "integrity": "sha512-c646jH1avxr+aVpndVMeAfYw7wAa6idufrlN3LPA4PmKS0QEGp6PIC9nwz0WQkkvBGAMEki3pFdtxaF39J9vvg==", + "dev": true + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "async-validator": { + "version": "1.8.5", + "resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-1.8.5.tgz", + "integrity": "sha512-tXBM+1m056MAX0E8TL2iCjg8WvSyXu0Zc8LNtYqrVeyoL3+esHRZ4SieE9fKQyyU09uONjnMEjrNBMqT0mbvmA==", + "requires": { + "babel-runtime": "6.x" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "autoprefixer": { + "version": "9.8.8", + "resolved": "https://registry.npmmirror.com/autoprefixer/-/autoprefixer-9.8.8.tgz", + "integrity": "sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA==", + "dev": true, + "requires": { + "browserslist": "^4.12.0", + "caniuse-lite": "^1.0.30001109", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "picocolors": "^0.2.1", + "postcss": "^7.0.32", + "postcss-value-parser": "^4.1.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmmirror.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "requires": { + "possible-typed-array-names": "^1.0.0" + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmmirror.com/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "dev": true + }, + "aws4": { + "version": "1.13.0", + "resolved": "https://registry.npmmirror.com/aws4/-/aws4-1.13.0.tgz", + "integrity": "sha512-3AungXC4I8kKsS9PuS4JH2nc+0bVY/mjgrephHTIi8fpEeGsTHBUJeosp0Wc1myYMElmD0B3Oc4XL/HVJ4PV2g==", + "dev": true + }, + "axios": { + "version": "0.24.0", + "resolved": "https://registry.npmmirror.com/axios/-/axios-0.24.0.tgz", + "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", + "requires": { + "follow-redirects": "^1.14.4" + } + }, + "babel-eslint": { + "version": "10.1.0", + "resolved": "https://registry.npmmirror.com/babel-eslint/-/babel-eslint-10.1.0.tgz", + "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.7.0", + "@babel/traverse": "^7.7.0", + "@babel/types": "^7.7.0", + "eslint-visitor-keys": "^1.0.0", + "resolve": "^1.12.0" + } + }, + "babel-helper-vue-jsx-merge-props": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz", + "integrity": "sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg==" + }, + "babel-loader": { + "version": "8.3.0", + "resolved": "https://registry.npmmirror.com/babel-loader/-/babel-loader-8.3.0.tgz", + "integrity": "sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q==", + "dev": true, + "requires": { + "find-cache-dir": "^3.3.1", + "loader-utils": "^2.0.0", + "make-dir": "^3.1.0", + "schema-utils": "^2.6.5" + } + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmmirror.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dev": true, + "requires": { + "object.assign": "^4.1.0" + } + }, + "babel-plugin-polyfill-corejs2": { + "version": "0.4.11", + "resolved": "https://registry.npmmirror.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "babel-plugin-polyfill-corejs3": { + "version": "0.10.4", + "resolved": "https://registry.npmmirror.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", + "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", + "dev": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.6.1", + "core-js-compat": "^3.36.1" + } + }, + "babel-plugin-polyfill-regenerator": { + "version": "0.6.2", + "resolved": "https://registry.npmmirror.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "dev": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.6.2" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmmirror.com/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + }, + "dependencies": { + "core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmmirror.com/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + } + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmmirror.com/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-descriptor": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/is-descriptor/-/is-descriptor-1.0.3.tgz", + "integrity": "sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" + } + } + } + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bfj": { + "version": "6.1.2", + "resolved": "https://registry.npmmirror.com/bfj/-/bfj-6.1.2.tgz", + "integrity": "sha512-BmBJa4Lip6BPRINSZ0BPEIfB1wUY/9rwbwvIHQA1KjX9om29B6id0wnWXq7m3bn5JrUVjeOTnVuhPT1FiHwPGw==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "check-types": "^8.0.3", + "hoopy": "^0.1.4", + "tryer": "^1.0.1" + } + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmmirror.com/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmmirror.com/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmmirror.com/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", + "dev": true + }, + "body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmmirror.com/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dev": true, + "requires": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "qs": { + "version": "6.11.0", + "resolved": "https://registry.npmmirror.com/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, + "requires": { + "side-channel": "^1.0.4" + } + } + } + }, + "bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmmirror.com/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha512-RaVTblr+OnEli0r/ud8InrU7D+G0y6aJhlxaLa6Pwty4+xoxboF1BsUI45tujvRpbj9dQVoglChqonGAsjEBYg==", + "dev": true, + "requires": { + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" + }, + "dependencies": { + "array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", + "dev": true + } + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmmirror.com/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "dev": true + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "dev": true, + "requires": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/browserify-sign/-/browserify-sign-4.2.3.tgz", + "integrity": "sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw==", + "dev": true, + "requires": { + "bn.js": "^5.2.1", + "browserify-rsa": "^4.1.0", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.5", + "hash-base": "~3.0", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.7", + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1" + }, + "dependencies": { + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha512-EeeoJKjTyt868liAlVmcv2ZsUfGHlE3Q+BICOXcZiwN3osr5Q/zFGYmTJpoIzuaSTAwndFy+GqhEwlU4L3j4Ow==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + } + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "~1.0.5" + } + }, + "browserslist": { + "version": "4.23.0", + "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + } + }, + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmmirror.com/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz", + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", + "dev": true + }, + "buffer-json": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/buffer-json/-/buffer-json-2.0.0.tgz", + "integrity": "sha512-+jjPFVqyfF1esi9fvfUs3NqM0pH1ziZ36VP4hmA/y/Ssfo/5w5xHKfTw9BwQjoJ1w/oVtpLomqwUHKdefGyuHw==", + "dev": true + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==", + "dev": true + }, + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true + }, + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmmirror.com/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "cache-loader": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/cache-loader/-/cache-loader-4.1.0.tgz", + "integrity": "sha512-ftOayxve0PwKzBF/GLsZNC9fJBXl8lkZE3TOsjkboHfVHVkL39iUEs1FO07A33mizmci5Dudt38UZrrYXDtbhw==", + "dev": true, + "requires": { + "buffer-json": "^2.0.0", + "find-cache-dir": "^3.0.0", + "loader-utils": "^1.2.3", + "mkdirp": "^0.5.1", + "neo-async": "^2.6.1", + "schema-utils": "^2.0.0" + }, + "dependencies": { + "json5": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.2", + "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-1.4.2.tgz", + "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + } + } + }, + "call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "requires": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + } + }, + "call-me-maybe": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", + "dev": true + }, + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==", + "dev": true, + "requires": { + "callsites": "^2.0.0" + } + }, + "caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==", + "dev": true, + "requires": { + "caller-callsite": "^2.0.0" + } + }, + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==", + "dev": true + }, + "camel-case": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/camel-case/-/camel-case-3.0.0.tgz", + "integrity": "sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==", + "dev": true, + "requires": { + "no-case": "^2.2.0", + "upper-case": "^1.1.1" + } + }, + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmmirror.com/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + }, + "caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "caniuse-lite": { + "version": "1.0.30001624", + "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001624.tgz", + "integrity": "sha512-0dWnQG87UevOCPYaOR49CBcLBwoZLpws+k6W37nLjWUhumP1Isusj0p2u+3KhjNloRWK9OKMgjBBzPujQHw4nA==", + "dev": true + }, + "case-sensitive-paths-webpack-plugin": { + "version": "2.4.0", + "resolved": "https://registry.npmmirror.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", + "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmmirror.com/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "dev": true + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmmirror.com/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "check-types": { + "version": "8.0.3", + "resolved": "https://registry.npmmirror.com/check-types/-/check-types-8.0.3.tgz", + "integrity": "sha512-YpeKZngUmG65rLudJ4taU7VLkOCTMhNl/u4ctNC56LQS/zJTyNH0Lrtwm1tfTsbLlwvlfsA2d1c8vCf/Kh2KwQ==", + "dev": true + }, + "chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "dependencies": { + "braces": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "requires": { + "fill-range": "^7.1.1" + } + }, + "fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true + }, + "ci-info": { + "version": "1.6.0", + "resolved": "https://registry.npmmirror.com/ci-info/-/ci-info-1.6.0.tgz", + "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", + "dev": true + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmmirror.com/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmmirror.com/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "clean-css": { + "version": "4.2.4", + "resolved": "https://registry.npmmirror.com/clean-css/-/clean-css-4.2.4.tgz", + "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==", + "dev": true, + "requires": { + "source-map": "~0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-highlight": { + "version": "2.1.11", + "resolved": "https://registry.npmmirror.com/cli-highlight/-/cli-highlight-2.1.11.tgz", + "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "highlight.js": "^10.7.1", + "mz": "^2.4.0", + "parse5": "^5.1.1", + "parse5-htmlparser2-tree-adapter": "^6.0.0", + "yargs": "^16.0.0" + }, + "dependencies": { + "highlight.js": { + "version": "10.7.3", + "resolved": "https://registry.npmmirror.com/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "dev": true + } + } + }, + "cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmmirror.com/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true + }, + "cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "requires": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + } + } + }, + "cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true + }, + "clipboard": { + "version": "2.0.8", + "resolved": "https://registry.npmmirror.com/clipboard/-/clipboard-2.0.8.tgz", + "integrity": "sha512-Y6WO0unAIQp5bLmk1zdThRhgJt/x3ks6f30s3oE3H1mgIEU33XyQjEf8gsf6DxC7NPX8Y1SsNWjUjL/ywLnnbQ==", + "requires": { + "good-listener": "^1.2.2", + "select": "^1.1.2", + "tiny-emitter": "^2.0.0" + } + }, + "clipboardy": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/clipboardy/-/clipboardy-2.3.0.tgz", + "integrity": "sha512-mKhiIL2DrQIsuXMgBgnfEHOZOryC7kY7YO//TN6c63wlEm3NG5tz+YgY5rVi29KCmq/QQjKYvM7a19+MDOTHOQ==", + "dev": true, + "requires": { + "arch": "^2.1.1", + "execa": "^1.0.0", + "is-wsl": "^2.1.1" + }, + "dependencies": { + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + } + } + } + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } + } + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==" + }, + "coa": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/coa/-/coa-2.0.2.tgz", + "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", + "dev": true, + "requires": { + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } + } + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color": { + "version": "3.2.1", + "resolved": "https://registry.npmmirror.com/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "dev": true, + "requires": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmmirror.com/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dev": true, + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmmirror.com/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true + }, + "component-emitter": { + "version": "1.3.1", + "resolved": "https://registry.npmmirror.com/component-emitter/-/component-emitter-1.3.1.tgz", + "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", + "dev": true + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmmirror.com/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npmmirror.com/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "dependencies": { + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "compression-webpack-plugin": { + "version": "5.0.2", + "resolved": "https://registry.npmmirror.com/compression-webpack-plugin/-/compression-webpack-plugin-5.0.2.tgz", + "integrity": "sha512-F2G4cQfsMZ6CiPlG22Q5EDUCqnfyZqTjyJP5cMgNYUbBg/dUzV3hto8yTFFIogDCTWooVbePHQE0qL6FrJUSsA==", + "dev": true, + "requires": { + "cacache": "^15.0.5", + "find-cache-dir": "^3.3.1", + "schema-utils": "^2.7.0", + "serialize-javascript": "^4.0.0", + "webpack-sources": "^1.4.3" + }, + "dependencies": { + "cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmmirror.com/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "dev": true, + "requires": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + } + }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmmirror.com/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "dev": true, + "requires": { + "minipass": "^3.1.1" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmmirror.com/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmmirror.com/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "connect": { + "version": "3.6.6", + "resolved": "https://registry.npmmirror.com/connect/-/connect-3.6.6.tgz", + "integrity": "sha512-OO7axMmPpu/2XuX1+2Yrg0ddju31B6xLZMWkJ5rYBu4YRmRVlOjvlY6kw2FJKiAzyxGwnrDUAG4s1Pf0sbBMCQ==", + "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.0", + "parseurl": "~1.3.2", + "utils-merge": "1.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "finalhandler": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/finalhandler/-/finalhandler-1.1.0.tgz", + "integrity": "sha512-ejnvM9ZXYzp6PUPUyQBMBf0Co5VX2gr5H2VQe2Ui2jWXNlxv+PYZo8wpAymJNJdLsG1R4p+M4aynF8KuoUEwRw==", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.3.1", + "unpipe": "~1.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmmirror.com/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha512-wuTCPGlJONk/a1kqZ4fQM2+908lC7fa7nPYpTC1EhnvqLX/IICbeP1OZGDtA374trpSq68YubKUMo8oRhN46yg==", + "dev": true + } + } + }, + "connect-history-api-fallback": { + "version": "1.6.0", + "resolved": "https://registry.npmmirror.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", + "dev": true + }, + "console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true + }, + "consolidate": { + "version": "0.15.1", + "resolved": "https://registry.npmmirror.com/consolidate/-/consolidate-0.15.1.tgz", + "integrity": "sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==", + "dev": true, + "requires": { + "bluebird": "^3.1.1" + } + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==", + "dev": true + }, + "content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmmirror.com/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "requires": { + "safe-buffer": "5.2.1" + } + }, + "content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true + }, + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmmirror.com/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "dev": true + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmmirror.com/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + } + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmmirror.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==", + "dev": true + }, + "copy-webpack-plugin": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/copy-webpack-plugin/-/copy-webpack-plugin-5.1.2.tgz", + "integrity": "sha512-Uh7crJAco3AjBvgAy9Z75CjK8IG+gxaErro71THQ+vv/bl4HaQcpkexAY8KVW/T6D2W2IRr+couF/knIRkZMIQ==", + "dev": true, + "requires": { + "cacache": "^12.0.3", + "find-cache-dir": "^2.1.0", + "glob-parent": "^3.1.0", + "globby": "^7.1.1", + "is-glob": "^4.0.1", + "loader-utils": "^1.2.3", + "minimatch": "^3.0.4", + "normalize-path": "^3.0.0", + "p-limit": "^2.2.1", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "webpack-log": "^2.0.0" + }, + "dependencies": { + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "globby": { + "version": "7.1.1", + "resolved": "https://registry.npmmirror.com/globby/-/globby-7.1.1.tgz", + "integrity": "sha512-yANWAN2DUcBtuus5Cpd+SKROzXHs2iVXFZt/Ykrfz6SAXqacLX25NZpltE+39ceMexYF4TtEadjuSTw8+3wX4g==", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "dir-glob": "^2.0.0", + "glob": "^7.1.2", + "ignore": "^3.3.5", + "pify": "^3.0.0", + "slash": "^1.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true + } + } + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmmirror.com/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "dev": true + }, + "json5": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.2", + "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-1.4.2.tgz", + "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/slash/-/slash-1.0.0.tgz", + "integrity": "sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg==", + "dev": true + } + } + }, + "core-js": { + "version": "3.25.3", + "resolved": "https://registry.npmmirror.com/core-js/-/core-js-3.25.3.tgz", + "integrity": "sha512-y1hvKXmPHvm5B7w4ln1S4uc9eV/O5+iFExSRUimnvIph11uaizFR8LFMdONN8hG3P2pipUfX4Y/fR8rAEtcHcQ==" + }, + "core-js-compat": { + "version": "3.37.1", + "resolved": "https://registry.npmmirror.com/core-js-compat/-/core-js-compat-3.37.1.tgz", + "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", + "dev": true, + "requires": { + "browserslist": "^4.23.0" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true + }, + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmmirror.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "dev": true, + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + }, + "dependencies": { + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + } + } + }, + "create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmmirror.com/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmmirror.com/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmmirror.com/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmmirror.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "css-color-names": { + "version": "0.0.4", + "resolved": "https://registry.npmmirror.com/css-color-names/-/css-color-names-0.0.4.tgz", + "integrity": "sha512-zj5D7X1U2h2zsXOAM8EyUREBnnts6H+Jm+d1M2DbiQQcUtnqgQsMrdo8JW9R80YFUmIdBZeMu5wvYM7hcgWP/Q==", + "dev": true + }, + "css-declaration-sorter": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz", + "integrity": "sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==", + "dev": true, + "requires": { + "postcss": "^7.0.1", + "timsort": "^0.3.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "css-loader": { + "version": "3.6.0", + "resolved": "https://registry.npmmirror.com/css-loader/-/css-loader-3.6.0.tgz", + "integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "cssesc": "^3.0.0", + "icss-utils": "^4.1.1", + "loader-utils": "^1.2.3", + "normalize-path": "^3.0.0", + "postcss": "^7.0.32", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^3.0.2", + "postcss-modules-scope": "^2.2.0", + "postcss-modules-values": "^3.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^2.7.0", + "semver": "^6.3.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmmirror.com/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "json5": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.2", + "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-1.4.2.tgz", + "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "css-select": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "css-select-base-adapter": { + "version": "0.1.1", + "resolved": "https://registry.npmmirror.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", + "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==", + "dev": true + }, + "css-tree": { + "version": "1.0.0-alpha.37", + "resolved": "https://registry.npmmirror.com/css-tree/-/css-tree-1.0.0-alpha.37.tgz", + "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", + "dev": true, + "requires": { + "mdn-data": "2.0.4", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "css-what": { + "version": "3.4.2", + "resolved": "https://registry.npmmirror.com/css-what/-/css-what-3.4.2.tgz", + "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==", + "dev": true + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, + "cssnano": { + "version": "4.1.11", + "resolved": "https://registry.npmmirror.com/cssnano/-/cssnano-4.1.11.tgz", + "integrity": "sha512-6gZm2htn7xIPJOHY824ERgj8cNPgPxyCSnkXc4v7YvNW+TdVfzgngHcEhy/8D11kUWRUMbke+tC+AUcUsnMz2g==", + "dev": true, + "requires": { + "cosmiconfig": "^5.0.0", + "cssnano-preset-default": "^4.0.8", + "is-resolvable": "^1.0.0", + "postcss": "^7.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "cssnano-preset-default": { + "version": "4.0.8", + "resolved": "https://registry.npmmirror.com/cssnano-preset-default/-/cssnano-preset-default-4.0.8.tgz", + "integrity": "sha512-LdAyHuq+VRyeVREFmuxUZR1TXjQm8QQU/ktoo/x7bz+SdOge1YKc5eMN6pRW7YWBmyq59CqYba1dJ5cUukEjLQ==", + "dev": true, + "requires": { + "css-declaration-sorter": "^4.0.1", + "cssnano-util-raw-cache": "^4.0.1", + "postcss": "^7.0.0", + "postcss-calc": "^7.0.1", + "postcss-colormin": "^4.0.3", + "postcss-convert-values": "^4.0.1", + "postcss-discard-comments": "^4.0.2", + "postcss-discard-duplicates": "^4.0.2", + "postcss-discard-empty": "^4.0.1", + "postcss-discard-overridden": "^4.0.1", + "postcss-merge-longhand": "^4.0.11", + "postcss-merge-rules": "^4.0.3", + "postcss-minify-font-values": "^4.0.2", + "postcss-minify-gradients": "^4.0.2", + "postcss-minify-params": "^4.0.2", + "postcss-minify-selectors": "^4.0.2", + "postcss-normalize-charset": "^4.0.1", + "postcss-normalize-display-values": "^4.0.2", + "postcss-normalize-positions": "^4.0.2", + "postcss-normalize-repeat-style": "^4.0.2", + "postcss-normalize-string": "^4.0.2", + "postcss-normalize-timing-functions": "^4.0.2", + "postcss-normalize-unicode": "^4.0.1", + "postcss-normalize-url": "^4.0.1", + "postcss-normalize-whitespace": "^4.0.2", + "postcss-ordered-values": "^4.1.2", + "postcss-reduce-initial": "^4.0.3", + "postcss-reduce-transforms": "^4.0.2", + "postcss-svgo": "^4.0.3", + "postcss-unique-selectors": "^4.0.1" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "cssnano-util-get-arguments": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz", + "integrity": "sha512-6RIcwmV3/cBMG8Aj5gucQRsJb4vv4I4rn6YjPbVWd5+Pn/fuG+YseGvXGk00XLkoZkaj31QOD7vMUpNPC4FIuw==", + "dev": true + }, + "cssnano-util-get-match": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz", + "integrity": "sha512-JPMZ1TSMRUPVIqEalIBNoBtAYbi8okvcFns4O0YIhcdGebeYZK7dMyHJiQ6GqNBA9kE0Hym4Aqym5rPdsV/4Cw==", + "dev": true + }, + "cssnano-util-raw-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz", + "integrity": "sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "cssnano-util-same-parent": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz", + "integrity": "sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==", + "dev": true + }, + "csso": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "dev": true, + "requires": { + "css-tree": "^1.1.2" + }, + "dependencies": { + "css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmmirror.com/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "dev": true, + "requires": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + } + }, + "mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmmirror.com/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "cyclist": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/cyclist/-/cyclist-1.0.2.tgz", + "integrity": "sha512-0sVXIohTfLqVIW3kb/0n6IiWF3Ifj5nm2XaSrLq2DI6fKIGa2fYAZdk917rUneaeLVpYfFcyXE2ft0fe3remsA==", + "dev": true + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmmirror.com/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "requires": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + } + }, + "data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + } + }, + "data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "requires": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + } + }, + "de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", + "dev": true + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmmirror.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "dev": true + }, + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmmirror.com/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", + "dev": true + }, + "deep-equal": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/deep-equal/-/deep-equal-1.1.2.tgz", + "integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==", + "requires": { + "is-arguments": "^1.1.1", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.5.1" + } + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "deepmerge": { + "version": "1.5.2", + "resolved": "https://registry.npmmirror.com/deepmerge/-/deepmerge-1.5.2.tgz", + "integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==" + }, + "default-gateway": { + "version": "5.0.5", + "resolved": "https://registry.npmmirror.com/default-gateway/-/default-gateway-5.0.5.tgz", + "integrity": "sha512-z2RnruVmj8hVMmAnEJMTIJNijhKCDiGjbLP+BHJFOT7ld3Bo5qcIBpVYDniqhbMIIf+jZDlkP2MkPXiQy/DBLA==", + "dev": true, + "requires": { + "execa": "^3.3.0" + }, + "dependencies": { + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "execa": { + "version": "3.4.0", + "resolved": "https://registry.npmmirror.com/execa/-/execa-3.4.0.tgz", + "integrity": "sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "p-finally": "^2.0.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + } + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "p-finally": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/p-finally/-/p-finally-2.0.1.tgz", + "integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "requires": { + "clone": "^1.0.2" + }, + "dependencies": { + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true + } + } + }, + "define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "requires": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + } + }, + "define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "requires": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-descriptor": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/is-descriptor/-/is-descriptor-1.0.3.tgz", + "integrity": "sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" + } + } + } + }, + "del": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/del/-/del-4.1.1.tgz", + "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "globby": "^6.1.0", + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" + }, + "dependencies": { + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmmirror.com/globby/-/globby-6.1.0.tgz", + "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true + } + } + }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true + }, + "delegate": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/delegate/-/delegate-3.2.0.tgz", + "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==" + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true + }, + "des.js": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/des.js/-/des.js-1.1.0.tgz", + "integrity": "sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true + }, + "detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmmirror.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmmirror.com/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "dir-glob": { + "version": "2.2.2", + "resolved": "https://registry.npmmirror.com/dir-glob/-/dir-glob-2.2.2.tgz", + "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", + "dev": true, + "requires": { + "path-type": "^3.0.0" + } + }, + "dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==", + "dev": true + }, + "dns-packet": { + "version": "1.3.4", + "resolved": "https://registry.npmmirror.com/dns-packet/-/dns-packet-1.3.4.tgz", + "integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==", + "dev": true, + "requires": { + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" + } + }, + "dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/dns-txt/-/dns-txt-2.0.2.tgz", + "integrity": "sha512-Ix5PrWjphuSoUXV/Zv5gaFHjnaJtb02F2+Si3Ht9dyJ87+Z/lMmy+dpNHtTGraNK958ndXq2i+GLkWsWHcKaBQ==", + "dev": true, + "requires": { + "buffer-indexof": "^1.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dev": true, + "requires": { + "utila": "~0.4" + } + }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true + }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true + } + } + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmmirror.com/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmmirror.com/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "requires": { + "domelementtype": "^2.2.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true + } + } + }, + "domready": { + "version": "1.0.8", + "resolved": "https://registry.npmmirror.com/domready/-/domready-1.0.8.tgz", + "integrity": "sha512-uIzsOJUNk+AdGE9a6VDeessoMCzF8RrZvJCX/W8QtyfgdR6Uofn/MvRonih3OtCO79b2VDzDOymuiABrQ4z3XA==", + "dev": true + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmmirror.com/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmmirror.com/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "requires": { + "is-obj": "^2.0.0" + } + }, + "dotenv": { + "version": "8.6.0", + "resolved": "https://registry.npmmirror.com/dotenv/-/dotenv-8.6.0.tgz", + "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", + "dev": true + }, + "dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmmirror.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", + "dev": true + }, + "duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmmirror.com/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "dev": true + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmmirror.com/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "easings-css": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/easings-css/-/easings-css-1.0.0.tgz", + "integrity": "sha512-7Uq7NdazNfVtr0RNmPAys8it0zKCuaqxJStYKEl72D3j4gbvXhhaM7iWNbqhA4C94ygCye6VuyhzBRQC4szeBg==" + }, + "easy-stack": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/easy-stack/-/easy-stack-1.0.1.tgz", + "integrity": "sha512-wK2sCs4feiiJeFXn3zvY0p41mdU5VUgbgs1rNsc/y5ngFUijdWd+iIN8eoyuZHKB8xN6BL4PdWmzqFmxNg6V2w==", + "dev": true + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmmirror.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "echarts": { + "version": "5.4.0", + "resolved": "https://registry.npmmirror.com/echarts/-/echarts-5.4.0.tgz", + "integrity": "sha512-uPsO9VRUIKAdFOoH3B0aNg7NRVdN7aM39/OjovjO9MwmWsAkfGyeXJhK+dbRi51iDrQWliXV60/XwLA7kg3z0w==", + "requires": { + "tslib": "2.3.0", + "zrender": "5.4.0" + } + }, + "editorconfig": { + "version": "0.15.3", + "resolved": "https://registry.npmmirror.com/editorconfig/-/editorconfig-0.15.3.tgz", + "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", + "requires": { + "commander": "^2.19.0", + "lru-cache": "^4.1.5", + "semver": "^5.6.0", + "sigmund": "^1.0.1" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true + }, + "ejs": { + "version": "2.7.4", + "resolved": "https://registry.npmmirror.com/ejs/-/ejs-2.7.4.tgz", + "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.4.783", + "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.783.tgz", + "integrity": "sha512-bT0jEz/Xz1fahQpbZ1D7LgmPYZ3iHVY39NcWWro1+hA2IvjiPeaXtfSqrQ+nXjApMvQRE2ASt1itSLRrebHMRQ==", + "dev": true + }, + "element-ui": { + "version": "2.15.12", + "resolved": "https://registry.npmmirror.com/element-ui/-/element-ui-2.15.12.tgz", + "integrity": "sha512-Y5FMT2BPOindU2GkDEQ5ZKUVxDawKONRNMh2eL3uBx1FOtvUJ+L6IxXLVsNxq4WnaX/UnVNgWXebl7DobygZMg==", + "requires": { + "async-validator": "~1.8.1", + "babel-helper-vue-jsx-merge-props": "^2.0.0", + "deepmerge": "^1.2.0", + "normalize-wheel": "^1.0.1", + "resize-observer-polyfill": "^1.5.0", + "throttle-debounce": "^1.0.1" + } + }, + "elliptic": { + "version": "6.5.5", + "resolved": "https://registry.npmmirror.com/elliptic/-/elliptic-6.5.5.tgz", + "integrity": "sha512-7EjbcmUm17NQFu4Pmgmq2olYMj8nwMnpcddByChSUjArp8F5DQWcIcpriwO4ZToLNAJig0yiyjswfyGNje/ixw==", + "dev": true, + "requires": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmmirror.com/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmmirror.com/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "enhanced-resolve": { + "version": "4.5.0", + "resolved": "https://registry.npmmirror.com/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", + "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmmirror.com/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + } + } + }, + "enquirer": { + "version": "2.4.1", + "resolved": "https://registry.npmmirror.com/enquirer/-/enquirer-2.4.1.tgz", + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmmirror.com/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true + } + } + }, + "entities": { + "version": "4.5.0", + "resolved": "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true + }, + "errno": { + "version": "0.1.8", + "resolved": "https://registry.npmmirror.com/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "requires": { + "prr": "~1.0.1" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmmirror.com/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmmirror.com/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "dev": true, + "requires": { + "stackframe": "^1.3.4" + } + }, + "es-abstract": { + "version": "1.23.3", + "resolved": "https://registry.npmmirror.com/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, + "requires": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + } + }, + "es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", + "dev": true + }, + "es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "requires": { + "get-intrinsic": "^1.2.4" + } + }, + "es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" + }, + "es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "requires": { + "es-errors": "^1.3.0" + } + }, + "es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "requires": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "eslint": { + "version": "7.15.0", + "resolved": "https://registry.npmmirror.com/eslint/-/eslint-7.15.0.tgz", + "integrity": "sha512-Vr64xFDT8w30wFll643e7cGrIkPEU50yIiI36OdSIDoSGguIeaLzBo0vpGvzo9RECUqq7htURfwEtKqwytkqzA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@eslint/eslintrc": "^0.2.2", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^6.0.0", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash": "^4.17.19", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + }, + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmmirror.com/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "semver": { + "version": "7.6.2", + "resolved": "https://registry.npmmirror.com/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "eslint-loader": { + "version": "2.2.1", + "resolved": "https://registry.npmmirror.com/eslint-loader/-/eslint-loader-2.2.1.tgz", + "integrity": "sha512-RLgV9hoCVsMLvOxCuNjdqOrUqIj9oJg8hF44vzJaYqsAHuY9G2YAeN3joQ9nxP0p5Th9iFSIpKo+SD8KISxXRg==", + "dev": true, + "requires": { + "loader-fs-cache": "^1.0.0", + "loader-utils": "^1.0.2", + "object-assign": "^4.0.1", + "object-hash": "^1.1.4", + "rimraf": "^2.6.1" + }, + "dependencies": { + "json5": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.2", + "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-1.4.2.tgz", + "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + } + } + }, + "eslint-plugin-vue": { + "version": "7.2.0", + "resolved": "https://registry.npmmirror.com/eslint-plugin-vue/-/eslint-plugin-vue-7.2.0.tgz", + "integrity": "sha512-4mt0yIv6rBDNtvis/g22a0ozJ12GfcdEzX77u0ICYjKlxOVtGrKGEvo0cbOObHaKDg9a9kJcoaNodqE4TPfS2A==", + "dev": true, + "requires": { + "eslint-utils": "^2.1.0", + "natural-compare": "^1.4.0", + "semver": "^7.3.2", + "vue-eslint-parser": "^7.2.0" + }, + "dependencies": { + "semver": { + "version": "7.6.2", + "resolved": "https://registry.npmmirror.com/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true + } + } + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, + "espree": { + "version": "7.3.1", + "resolved": "https://registry.npmmirror.com/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "requires": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmmirror.com/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + } + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmmirror.com/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmmirror.com/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true + }, + "event-pubsub": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/event-pubsub/-/event-pubsub-4.3.0.tgz", + "integrity": "sha512-z7IyloorXvKbFx9Bpie2+vMJKKx1fH1EN5yiTfp8CiLOTptSYy1g8H4yDpGlEdshL1PBiFtBHepF2cNsqeEeFQ==", + "dev": true + }, + "eventemitter3": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-2.0.3.tgz", + "integrity": "sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg==" + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmmirror.com/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true + }, + "eventsource": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/eventsource/-/eventsource-2.0.2.tgz", + "integrity": "sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==", + "dev": true + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmmirror.com/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmmirror.com/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + } + } + }, + "express": { + "version": "4.19.2", + "resolved": "https://registry.npmmirror.com/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dev": true, + "requires": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "qs": { + "version": "6.11.0", + "resolved": "https://registry.npmmirror.com/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, + "requires": { + "side-channel": "^1.0.4" + } + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-descriptor": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/is-descriptor/-/is-descriptor-1.0.3.tgz", + "integrity": "sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-diff": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/fast-diff/-/fast-diff-1.1.2.tgz", + "integrity": "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig==" + }, + "fast-glob": { + "version": "2.2.7", + "resolved": "https://registry.npmmirror.com/fast-glob/-/fast-glob-2.2.7.tgz", + "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", + "dev": true, + "requires": { + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.1.2", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.3", + "micromatch": "^3.1.10" + }, + "dependencies": { + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + } + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmmirror.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmmirror.com/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmmirror.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", + "dev": true + }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "file-loader": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/file-loader/-/file-loader-4.3.0.tgz", + "integrity": "sha512-aKrYPYjF1yG3oX0kWRrqrSMfgftm7oJW5M+m4owoldH5C51C0RkIwB++JbRvEW3IU6/ZG5n8UvEcdgwOt2UOWA==", + "dev": true, + "requires": { + "loader-utils": "^1.2.3", + "schema-utils": "^2.5.0" + }, + "dependencies": { + "json5": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.2", + "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-1.4.2.tgz", + "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + } + } + }, + "file-saver": { + "version": "2.0.5", + "resolved": "https://registry.npmmirror.com/file-saver/-/file-saver-2.0.5.tgz", + "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==" + }, + "filesize": { + "version": "3.6.1", + "resolved": "https://registry.npmmirror.com/filesize/-/filesize-3.6.1.tgz", + "integrity": "sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==", + "dev": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + } + } + }, + "find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmmirror.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "requires": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "dependencies": { + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==" + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmmirror.com/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "requires": { + "is-callable": "^1.1.3" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "dev": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmmirror.com/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmmirror.com/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/from2/-/from2-2.3.0.tgz", + "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmmirror.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha512-gehEzmPn2nAwr39eay+x3X34Ra+M2QlVUTLhkXPjWdeO8RF9kszk116avgBJM3ZyNHgHXBNx+VmPaFC36k0PzA==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" + }, + "function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmmirror.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + } + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", + "dev": true + }, + "functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmmirror.com/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" + }, + "fuse.js": { + "version": "6.4.3", + "resolved": "https://registry.npmmirror.com/fuse.js/-/fuse.js-6.4.3.tgz", + "integrity": "sha512-JNgngolukIrqwayWnvy6NLH63hmwKPhm63o0uyBg51jPD0j09IvAzlV1rTXfAsgxpghI7khAo6Mv+EmvjDWXig==" + }, + "fuzzysearch": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/fuzzysearch/-/fuzzysearch-1.0.3.tgz", + "integrity": "sha512-s+kNWQuI3mo9OALw0HJ6YGmMbLqEufCh2nX/zzV5CrICQ/y4AwPxM+6TIiF9ItFCHXFCyM/BfCCmN57NTIJuPg==" + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmmirror.com/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "requires": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + } + }, + "get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", + "dev": true + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "requires": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmmirror.com/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmmirror.com/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "glob-to-regexp": { + "version": "0.3.0", + "resolved": "https://registry.npmmirror.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", + "integrity": "sha512-Iozmtbqv0noj0uDDqoL0zNq0VBEfK2YFoMAZoxJe4cwphvLR+JskfF30QhXHOR4m3KrE6NLRYw+U9MRXvifyig==", + "dev": true + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmmirror.com/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "requires": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + } + }, + "globby": { + "version": "9.2.0", + "resolved": "https://registry.npmmirror.com/globby/-/globby-9.2.0.tgz", + "integrity": "sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "array-union": "^1.0.2", + "dir-glob": "^2.2.2", + "fast-glob": "^2.2.6", + "glob": "^7.1.3", + "ignore": "^4.0.3", + "pify": "^4.0.1", + "slash": "^2.0.0" + } + }, + "good-listener": { + "version": "1.2.2", + "resolved": "https://registry.npmmirror.com/good-listener/-/good-listener-1.2.2.tgz", + "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==", + "requires": { + "delegate": "^3.1.2" + } + }, + "gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "requires": { + "get-intrinsic": "^1.1.3" + } + }, + "graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "gzip-size": { + "version": "5.1.1", + "resolved": "https://registry.npmmirror.com/gzip-size/-/gzip-size-5.1.1.tgz", + "integrity": "sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA==", + "dev": true, + "requires": { + "duplexer": "^0.1.1", + "pify": "^4.0.1" + } + }, + "handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", + "dev": true + }, + "har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmmirror.com/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "dev": true, + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/has/-/has-1.0.4.tgz", + "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", + "dev": true + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true + } + } + }, + "has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "requires": { + "es-define-property": "^1.0.0" + } + }, + "has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==" + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "requires": { + "has-symbols": "^1.0.3" + } + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "hash-sum": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/hash-sum/-/hash-sum-2.0.0.tgz", + "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==", + "dev": true + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmmirror.com/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "requires": { + "function-bind": "^1.1.2" + } + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "hex-color-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz", + "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==", + "dev": true + }, + "highlight.js": { + "version": "9.18.5", + "resolved": "https://registry.npmmirror.com/highlight.js/-/highlight.js-9.18.5.tgz", + "integrity": "sha512-a5bFyofd/BHCX52/8i8uJkjr9DYwXIPnM/plwI6W7ezItLGqzt7X2G2nXuYSfsIJdkwwj/g9DG1LkcGJI/dDoA==" + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "hoopy": { + "version": "0.1.4", + "resolved": "https://registry.npmmirror.com/hoopy/-/hoopy-0.1.4.tgz", + "integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==", + "dev": true + }, + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmmirror.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmmirror.com/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "hsl-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/hsl-regex/-/hsl-regex-1.0.0.tgz", + "integrity": "sha512-M5ezZw4LzXbBKMruP+BNANf0k+19hDQMgpzBIYnya//Al+fjNct9Wf3b1WedLqdEs2hKBvxq/jh+DsHJLj0F9A==", + "dev": true + }, + "hsla-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/hsla-regex/-/hsla-regex-1.0.0.tgz", + "integrity": "sha512-7Wn5GMLuHBjZCb2bTmnDOycho0p/7UVaAeqXZGbHrBCl6Yd/xDhQJAXe6Ga9AXJH2I5zY1dEdYw2u1UptnSBJA==", + "dev": true + }, + "html-entities": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/html-entities/-/html-entities-1.4.0.tgz", + "integrity": "sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==", + "dev": true + }, + "html-minifier": { + "version": "3.5.21", + "resolved": "https://registry.npmmirror.com/html-minifier/-/html-minifier-3.5.21.tgz", + "integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==", + "dev": true, + "requires": { + "camel-case": "3.0.x", + "clean-css": "4.2.x", + "commander": "2.17.x", + "he": "1.2.x", + "param-case": "2.1.x", + "relateurl": "0.2.x", + "uglify-js": "3.4.x" + }, + "dependencies": { + "commander": { + "version": "2.17.1", + "resolved": "https://registry.npmmirror.com/commander/-/commander-2.17.1.tgz", + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", + "dev": true + } + } + }, + "html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "dev": true + }, + "html-webpack-plugin": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz", + "integrity": "sha512-Br4ifmjQojUP4EmHnRBoUIYcZ9J7M4bTMcm7u6xoIAIuq2Nte4TzXX0533owvkQKQD1WeMTTTyD4Ni4QKxS0Bg==", + "dev": true, + "requires": { + "html-minifier": "^3.2.3", + "loader-utils": "^0.2.16", + "lodash": "^4.17.3", + "pretty-error": "^2.0.2", + "tapable": "^1.0.0", + "toposort": "^1.0.0", + "util.promisify": "1.0.0" + }, + "dependencies": { + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "dev": true + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha512-knHEZMgs8BB+MInokmNTg/OyPlAddghe1YBgNwJBc5zsJi/uyIcXoSDsL/W9ymOsBoBGdPIHXYJ9+qKFwRwDng==", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmmirror.com/json5/-/json5-0.5.1.tgz", + "integrity": "sha512-4xrs1aW+6N5DalkqSVA8fxh458CXvR99WU8WLKmq4v8eWAL86Xo3BVqyd3SkA9wEVjCMqyvvRRkshAdOnBp5rw==", + "dev": true + }, + "loader-utils": { + "version": "0.2.17", + "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-0.2.17.tgz", + "integrity": "sha512-tiv66G0SmiOx+pLWMtGEkfSEejxvb6N6uRrQjfWJIT79W9GMpgKeCAmm9aVBKtd4WEgntciI8CsGqjpDoCWJug==", + "dev": true, + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0", + "object-assign": "^4.0.1" + } + }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + } + } + }, + "htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmmirror.com/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + }, + "dependencies": { + "dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + } + }, + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true + }, + "domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmmirror.com/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true + } + } + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmmirror.com/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "dev": true + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + } + }, + "http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmmirror.com/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", + "dev": true + }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmmirror.com/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "dependencies": { + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + } + } + }, + "http-proxy-middleware": { + "version": "0.19.1", + "resolved": "https://registry.npmmirror.com/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", + "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==", + "dev": true, + "requires": { + "http-proxy": "^1.17.0", + "is-glob": "^4.0.0", + "lodash": "^4.17.11", + "micromatch": "^3.1.10" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==", + "dev": true + }, + "human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "icss-utils": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/icss-utils/-/icss-utils-4.1.1.tgz", + "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", + "dev": true, + "requires": { + "postcss": "^7.0.14" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmmirror.com/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha512-DUNFN5j7Tln0D+TxzloUjKB+CtVu6myn0JEFak6dG18mNt9YkQ6lzGCdafwofISZ1lLF3xRHJ98VKy9ynkcFaA==", + "dev": true + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmmirror.com/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmmirror.com/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", + "dev": true + }, + "import-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/import-cwd/-/import-cwd-2.1.0.tgz", + "integrity": "sha512-Ew5AZzJQFqrOV5BTW3EIoHAnoie1LojZLXKcCQ/yTRyVZosBhK1x1ViYjHGf5pAFOq8ZyChZp6m/fSN7pJyZtg==", + "dev": true, + "requires": { + "import-from": "^2.1.0" + } + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==", + "dev": true, + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "import-from": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/import-from/-/import-from-2.1.0.tgz", + "integrity": "sha512-0vdnLL2wSGnhlRmzHJAg5JHjt1l2vYhzJ7tNLGbeVg0fse56tpGaH0uzH+r9Slej+BSXXEHvBKDEnVSLLE9/+w==", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + } + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmmirror.com/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha512-bup+4tap3Hympa+JBJUG7XuOsdNQ6fxt0MHyXMKuLBKn0OqsTfvUxkUrroEX1+B2VsSHvCjiIcZVxRtYa4nllA==", + "dev": true + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmmirror.com/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "inquirer": { + "version": "7.3.3", + "resolved": "https://registry.npmmirror.com/inquirer/-/inquirer-7.3.3.tgz", + "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.19", + "mute-stream": "0.0.8", + "run-async": "^2.4.0", + "rxjs": "^6.6.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + }, + "dependencies": { + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + } + } + }, + "internal-ip": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/internal-ip/-/internal-ip-4.3.0.tgz", + "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==", + "dev": true, + "requires": { + "default-gateway": "^4.2.0", + "ipaddr.js": "^1.9.0" + }, + "dependencies": { + "default-gateway": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/default-gateway/-/default-gateway-4.2.0.tgz", + "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==", + "dev": true, + "requires": { + "execa": "^1.0.0", + "ip-regex": "^2.1.0" + } + } + } + }, + "internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmmirror.com/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + } + }, + "ip": { + "version": "1.1.9", + "resolved": "https://registry.npmmirror.com/ip/-/ip-1.1.9.tgz", + "integrity": "sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==", + "dev": true + }, + "ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha512-58yWmlHpp7VYfcdTwMTvwMmqx/Elfxjd9RXTDyMsbL7lLWmhMylLEqiYVLKuLzOZqVgiWXD9MfR62Vv89VRxkw==", + "dev": true + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true + }, + "is-absolute-url": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz", + "integrity": "sha512-vOx7VprsKyllwjSkLV79NIhpyLfr3jAp7VaTCMXOJHu4m0Ew1CZ2fcjASwmV1jI3BWuWHB013M48eyeldk9gYg==", + "dev": true + }, + "is-accessor-descriptor": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.1.tgz", + "integrity": "sha512-YBUanLI8Yoihw923YeFUS5fs0fF2f5TSFTNiYAAzhhDscDa3lEqYuz1pDOEP5KvX94I9ey3vsqjJcLVFVU+3QA==", + "dev": true, + "requires": { + "hasown": "^2.0.0" + } + }, + "is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "requires": { + "has-bigints": "^1.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmmirror.com/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmmirror.com/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true + }, + "is-ci": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/is-ci/-/is-ci-1.2.1.tgz", + "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", + "dev": true, + "requires": { + "ci-info": "^1.5.0" + } + }, + "is-color-stop": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/is-color-stop/-/is-color-stop-1.1.0.tgz", + "integrity": "sha512-H1U8Vz0cfXNujrJzEcvvwMDW9Ra+biSYA3ThdQvAnMLJkEHQXn6bWzLkxHtVYJ+Sdbx0b6finn3jZiaVe7MAHA==", + "dev": true, + "requires": { + "css-color-names": "^0.0.4", + "hex-color-regex": "^1.1.0", + "hsl-regex": "^1.0.0", + "hsla-regex": "^1.0.0", + "rgb-regex": "^1.0.1", + "rgba-regex": "^1.0.0" + } + }, + "is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "requires": { + "hasown": "^2.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/is-data-descriptor/-/is-data-descriptor-1.0.1.tgz", + "integrity": "sha512-bc4NlCDiCr28U4aEsQ3Qs2491gVq4V8G7MQyws968ImqjKuYtTJXrl7Vq7jsN7Ly/C3xj5KWFrY7sHNeDkAzXw==", + "dev": true, + "requires": { + "hasown": "^2.0.0" + } + }, + "is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "requires": { + "is-typed-array": "^1.1.13" + } + }, + "is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-descriptor": { + "version": "0.1.7", + "resolved": "https://registry.npmmirror.com/is-descriptor/-/is-descriptor-0.1.7.tgz", + "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmmirror.com/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==", + "dev": true + }, + "is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmmirror.com/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmmirror.com/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmmirror.com/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmmirror.com/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true + }, + "is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true + }, + "is-path-in-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", + "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", + "dev": true, + "requires": { + "is-path-inside": "^2.1.0" + } + }, + "is-path-inside": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/is-path-inside/-/is-path-inside-2.1.0.tgz", + "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", + "dev": true, + "requires": { + "path-is-inside": "^1.0.2" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmmirror.com/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" + }, + "is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", + "dev": true + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, + "requires": { + "call-bind": "^1.0.7" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "dev": true + }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmmirror.com/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmmirror.com/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, + "requires": { + "which-typed-array": "^1.1.14" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true + }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmmirror.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true + }, + "is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmmirror.com/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "dev": true + }, + "javascript-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/javascript-stringify/-/javascript-stringify-2.1.0.tgz", + "integrity": "sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==", + "dev": true + }, + "jest-worker": { + "version": "25.5.0", + "resolved": "https://registry.npmmirror.com/jest-worker/-/jest-worker-25.5.0.tgz", + "integrity": "sha512-/dsSmUkIy5EBGfv/IjjqmFxrNAUpBERfGs1oHROyD7yxjG/w+t0GOJDX8O1k32ySmd7+a5IhnJU2qQFcJ4n1vw==", + "dev": true, + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "js-base64": { + "version": "2.6.4", + "resolved": "https://registry.npmmirror.com/js-base64/-/js-base64-2.6.4.tgz", + "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==", + "dev": true + }, + "js-beautify": { + "version": "1.13.0", + "resolved": "https://registry.npmmirror.com/js-beautify/-/js-beautify-1.13.0.tgz", + "integrity": "sha512-/Tbp1OVzZjbwzwJQFIlYLm9eWQ+3aYbBXLSaqb1mEJzhcQAfrqMMQYtjb6io+U6KpD0ID4F+Id3/xcjH3l/sqA==", + "requires": { + "config-chain": "^1.1.12", + "editorconfig": "^0.15.3", + "glob": "^7.1.3", + "mkdirp": "^1.0.4", + "nopt": "^5.0.0" + } + }, + "js-cookie": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/js-cookie/-/js-cookie-3.0.1.tgz", + "integrity": "sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw==" + }, + "js-message": { + "version": "1.0.7", + "resolved": "https://registry.npmmirror.com/js-message/-/js-message-1.0.7.tgz", + "integrity": "sha512-efJLHhLjIyKRewNS9EGZ4UpI8NguuL6fKkhRxVuMmrGV2xN/0APGdQYwLFky5w9naebSZ0OwAGp0G6/2Cg90rA==", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmmirror.com/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true + }, + "jsencrypt": { + "version": "3.0.0-rc.1", + "resolved": "https://registry.npmmirror.com/jsencrypt/-/jsencrypt-3.0.0-rc.1.tgz", + "integrity": "sha512-gcvGaqerlUJy1Kq6tNgPYteVEoWNemu+9hBe2CdsCIz4rVcwjoTQ72iD1W76/PRMlnkzG0yVh7nwOOMOOUfKmg==" + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmmirror.com/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true + }, + "json5": { + "version": "2.2.3", + "resolved": "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmmirror.com/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + } + }, + "keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "requires": { + "json-buffer": "3.0.1" + } + }, + "killable": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/killable/-/killable-1.0.1.tgz", + "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==", + "dev": true + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmmirror.com/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "klona": { + "version": "2.0.6", + "resolved": "https://registry.npmmirror.com/klona/-/klona-2.0.6.tgz", + "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", + "dev": true + }, + "launch-editor": { + "version": "2.6.1", + "resolved": "https://registry.npmmirror.com/launch-editor/-/launch-editor-2.6.1.tgz", + "integrity": "sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==", + "dev": true, + "requires": { + "picocolors": "^1.0.0", + "shell-quote": "^1.8.1" + } + }, + "launch-editor-middleware": { + "version": "2.6.1", + "resolved": "https://registry.npmmirror.com/launch-editor-middleware/-/launch-editor-middleware-2.6.1.tgz", + "integrity": "sha512-Fg/xYhf7ARmRp40n18wIfJyuAMEjXo67Yull7uF7d0OJ3qA4EYJISt1XfPPn69IIJ5jKgQwzcg6DqHYo95LL/g==", + "dev": true, + "requires": { + "launch-editor": "^2.6.1" + } + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "lint-staged": { + "version": "10.5.3", + "resolved": "https://registry.npmmirror.com/lint-staged/-/lint-staged-10.5.3.tgz", + "integrity": "sha512-TanwFfuqUBLufxCc3RUtFEkFraSPNR3WzWcGF39R3f2J7S9+iF9W0KTVLfSy09lYGmZS5NDCxjNvhGMSJyFCWg==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "cli-truncate": "^2.1.0", + "commander": "^6.2.0", + "cosmiconfig": "^7.0.0", + "debug": "^4.2.0", + "dedent": "^0.7.0", + "enquirer": "^2.3.6", + "execa": "^4.1.0", + "listr2": "^3.2.2", + "log-symbols": "^4.0.0", + "micromatch": "^4.0.2", + "normalize-path": "^3.0.0", + "please-upgrade-node": "^3.2.0", + "string-argv": "0.3.1", + "stringify-object": "^3.3.0" + }, + "dependencies": { + "braces": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "requires": { + "fill-range": "^7.1.1" + } + }, + "commander": { + "version": "6.2.1", + "resolved": "https://registry.npmmirror.com/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true + }, + "cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmmirror.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dev": true, + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "execa": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + } + }, + "fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, + "log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + } + }, + "micromatch": { + "version": "4.0.7", + "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "dev": true, + "requires": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "listr2": { + "version": "3.14.0", + "resolved": "https://registry.npmmirror.com/listr2/-/listr2-3.14.0.tgz", + "integrity": "sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==", + "dev": true, + "requires": { + "cli-truncate": "^2.1.0", + "colorette": "^2.0.16", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.5.1", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmmirror.com/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "requires": { + "tslib": "^2.1.0" + } + } + } + }, + "loader-fs-cache": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/loader-fs-cache/-/loader-fs-cache-1.0.3.tgz", + "integrity": "sha512-ldcgZpjNJj71n+2Mf6yetz+c9bM4xpKtNds4LbqXzU/PTdeAX0g3ytnU1AJMEcTk2Lex4Smpe3Q/eCTsvUBxbA==", + "dev": true, + "requires": { + "find-cache-dir": "^0.1.1", + "mkdirp": "^0.5.1" + }, + "dependencies": { + "find-cache-dir": { + "version": "0.1.1", + "resolved": "https://registry.npmmirror.com/find-cache-dir/-/find-cache-dir-0.1.1.tgz", + "integrity": "sha512-Z9XSBoNE7xQiV6MSgPuCfyMokH2K7JdpRkOYE1+mu3d4BFJtx3GW+f6Bo4q8IX6rlf5MYbLBKW0pjl2cWdkm2A==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "mkdirp": "^0.5.1", + "pkg-dir": "^1.0.0" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "pkg-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/pkg-dir/-/pkg-dir-1.0.0.tgz", + "integrity": "sha512-c6pv3OE78mcZ92ckebVDqg0aWSoKhOTbwCV6qbCWMk546mAL9pZln0+QsN/yQ7fkucd4+yJPLrCBXNt8Ruk+Eg==", + "dev": true, + "requires": { + "find-up": "^1.0.0" + } + } + } + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmmirror.com/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true + }, + "loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmmirror.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, + "lodash.defaultsdeep": { + "version": "4.6.1", + "resolved": "https://registry.npmmirror.com/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz", + "integrity": "sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==", + "dev": true + }, + "lodash.kebabcase": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", + "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", + "dev": true + }, + "lodash.mapvalues": { + "version": "4.6.0", + "resolved": "https://registry.npmmirror.com/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", + "integrity": "sha512-JPFqXFeZQ7BfS00H58kClY7SPVeHertPE0lNuCyZ26/XlN8TvakYD7b9bGyNmXbT/D3BbtPAAmq90gPWqLkxlQ==", + "dev": true + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmmirror.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "lodash.padend": { + "version": "4.6.1", + "resolved": "https://registry.npmmirror.com/lodash.padend/-/lodash.padend-4.6.1.tgz", + "integrity": "sha512-sOQs2aqGpbl27tmCS1QNZA09Uqp01ZzWfDUoD+xzTii0E7dSQfRKcRetFwa+uXaxaqL+TKm7CgD2JdKP7aZBSw==", + "dev": true + }, + "lodash.transform": { + "version": "4.6.0", + "resolved": "https://registry.npmmirror.com/lodash.transform/-/lodash.transform-4.6.0.tgz", + "integrity": "sha512-LO37ZnhmBVx0GvOU/caQuipEh4GN82TcWv3yHlebGDgOxbxiwwzW5Pcx2AcvpIv2WmvmSMoC492yQFNhy/l/UQ==", + "dev": true + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmmirror.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", + "dev": true + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "requires": { + "chalk": "^2.0.1" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } + } + }, + "log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dev": true, + "requires": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } + } + }, + "loglevel": { + "version": "1.9.1", + "resolved": "https://registry.npmmirror.com/loglevel/-/loglevel-1.9.1.tgz", + "integrity": "sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg==", + "dev": true + }, + "lower-case": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/lower-case/-/lower-case-1.1.4.tgz", + "integrity": "sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==", + "dev": true + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "magic-string": { + "version": "0.30.10", + "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.10.tgz", + "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", + "dev": true, + "requires": { + "@jridgewell/sourcemap-codec": "^1.4.15" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmmirror.com/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "material-colors": { + "version": "1.2.6", + "resolved": "https://registry.npmmirror.com/material-colors/-/material-colors-1.2.6.tgz", + "integrity": "sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==" + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmmirror.com/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "mdn-data": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==", + "dev": true + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmmirror.com/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha512-cda4JKCxReDXFXRqOHPQscuIYg1PvxbE2S2GP45rnwfEK+vZaXC8C1OFvdHIbgw0DLzowXGVoxLaAmlgRy14GQ==", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "dev": true + }, + "merge-options": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/merge-options/-/merge-options-1.0.1.tgz", + "integrity": "sha512-iuPV41VWKWBIOpBsjoxjDZw8/GbSfZ2mk7N1453bwMrfzdrIk7EzBd+8UVR6rkw67th7xnk9Dytl3J+lHPdxvg==", + "dev": true, + "requires": { + "is-plain-obj": "^1.1" + } + }, + "merge-source-map": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/merge-source-map/-/merge-source-map-1.1.0.tgz", + "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", + "dev": true, + "requires": { + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true + }, + "microargs": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/microargs/-/microargs-1.1.2.tgz", + "integrity": "sha512-fUrX9ozzzUX6JlDoNXmUM5i4B0uBF5xPznZ0Y/izM9wOtAaTf44V2vUCRgGBLUq/SeGIcDgfnEZDVoT92HId0g==", + "dev": true + }, + "microcli": { + "version": "1.3.3", + "resolved": "https://registry.npmmirror.com/microcli/-/microcli-1.3.3.tgz", + "integrity": "sha512-1isRaEBpfRC8vJMJymKknAH8CdPFABuWPVc18rlRWHOCcHLYEkJxcoH7FNkX7AuTGrB4Uf1ve6B0s/FfwzGWKg==", + "dev": true, + "requires": { + "lodash": "4.17.11", + "microargs": "1.1.2" + }, + "dependencies": { + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + } + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmmirror.com/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "mime": { + "version": "2.6.0", + "resolved": "https://registry.npmmirror.com/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "requires": { + "mime-db": "1.52.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "mini-css-extract-plugin": { + "version": "0.9.0", + "resolved": "https://registry.npmmirror.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz", + "integrity": "sha512-lp3GeY7ygcgAmVIcRPBVhIkf8Us7FZjA+ILpal44qLdSu11wmjKQ3d9k15lfD7pO4esu9eUIAW7qiYIBppv40A==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "normalize-url": "1.9.1", + "schema-utils": "^1.0.0", + "webpack-sources": "^1.1.0" + }, + "dependencies": { + "json5": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.2", + "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-1.4.2.tgz", + "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "normalize-url": { + "version": "1.9.1", + "resolved": "https://registry.npmmirror.com/normalize-url/-/normalize-url-1.9.1.tgz", + "integrity": "sha512-A48My/mtCklowHBlI8Fq2jFWK4tX4lJ5E6ytFsSOq1fzpvT0SQSgKhSg7lN5c2uYFOrUAOQp6zhhJnpp1eMloQ==", + "dev": true, + "requires": { + "object-assign": "^4.0.1", + "prepend-http": "^1.0.0", + "query-string": "^4.1.0", + "sort-keys": "^1.0.0" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "dev": true + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true + }, + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + }, + "dependencies": { + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "mitt": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/mitt/-/mitt-1.1.2.tgz", + "integrity": "sha512-3btxP0O9iGADGWAkteQ8mzDtEspZqu4I32y4GZYCV5BrwtzdcRpF4dQgNdJadCrbBx7Lu6Sq9AVrerMHR0Hkmw==", + "dev": true + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmmirror.com/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha512-hdrFxZOycD/g6A6SoI2bB5NA/5NEqD0569+S47WZhPvm46sD50ZHdYaFmnua5lndde9rCHGjmfK7Z8BuCt/PcQ==", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + } + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmmirror.com/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "dev": true, + "requires": { + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" + } + }, + "multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha512-cnAsSVxIDsYt0v7HmC0hWZFwwXSh+E6PgCrREDuN/EsjgLwA5XRmlMHhSiDPrt6HxY1gTivEa/Zh7GtODoLevQ==", + "dev": true + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmmirror.com/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "mz": { + "version": "2.7.0", + "resolved": "https://registry.npmmirror.com/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "requires": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmmirror.com/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmmirror.com/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "no-case": { + "version": "2.3.2", + "resolved": "https://registry.npmmirror.com/no-case/-/no-case-2.3.2.tgz", + "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "dev": true, + "requires": { + "lower-case": "^1.1.1" + } + }, + "node-forge": { + "version": "0.10.0", + "resolved": "https://registry.npmmirror.com/node-forge/-/node-forge-0.10.0.tgz", + "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", + "dev": true + }, + "node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmmirror.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "dev": true, + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmmirror.com/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true + } + } + }, + "node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "requires": { + "abbrev": "1" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmmirror.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmmirror.com/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true + }, + "normalize-url": { + "version": "3.3.0", + "resolved": "https://registry.npmmirror.com/normalize-url/-/normalize-url-3.3.0.tgz", + "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==", + "dev": true + }, + "normalize-wheel": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/normalize-wheel/-/normalize-wheel-1.0.1.tgz", + "integrity": "sha512-1OnlAPZ3zgrk8B91HyRj+eVv+kS5u+Z0SCsak6Xil/kmgEia50ga7zfkumayonZrImffAxPU/5WcyGhzetHNPA==" + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==" + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dev": true, + "requires": { + "boolbase": "~1.0.0" + } + }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmmirror.com/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha512-Y1wZESM7VUThYY+4W+X4ySH2maqcA+p7UR+w8VWNWVAd6lwuXXWz/w/Cz43J/dI2I+PS6wD5N+bJUF+gjWvIqg==", + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmmirror.com/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmmirror.com/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmmirror.com/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmmirror.com/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-hash": { + "version": "1.3.1", + "resolved": "https://registry.npmmirror.com/object-hash/-/object-hash-1.3.1.tgz", + "integrity": "sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA==", + "dev": true + }, + "object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "dev": true + }, + "object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmmirror.com/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmmirror.com/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + } + }, + "object.getownpropertydescriptors": { + "version": "2.1.8", + "resolved": "https://registry.npmmirror.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.8.tgz", + "integrity": "sha512-qkHIGe4q0lSYMv0XI4SsBTJz3WaURhLvd0lKSgtVuOsJ2krg4SgMw3PIRQFMp07yi++UR3se2mkcLqsBNpBb/A==", + "dev": true, + "requires": { + "array.prototype.reduce": "^1.0.6", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "gopd": "^1.0.1", + "safe-array-concat": "^1.1.2" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + } + }, + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "omelette": { + "version": "0.4.5", + "resolved": "https://registry.npmmirror.com/omelette/-/omelette-0.4.5.tgz", + "integrity": "sha512-b0k9uqwF60u15KmVkneVw96VYRtZu2QCbXUQ26SgdyVUgMBzctzIfhNPKAWl4oqJEKpe52CzBYSS+HIKtiK8sw==", + "dev": true + }, + "on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmmirror.com/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "open": { + "version": "6.4.0", + "resolved": "https://registry.npmmirror.com/open/-/open-6.4.0.tgz", + "integrity": "sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==", + "dev": true, + "requires": { + "is-wsl": "^1.1.0" + } + }, + "opener": { + "version": "1.5.2", + "resolved": "https://registry.npmmirror.com/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "dev": true + }, + "opn": { + "version": "5.5.0", + "resolved": "https://registry.npmmirror.com/opn/-/opn-5.5.0.tgz", + "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", + "dev": true, + "requires": { + "is-wsl": "^1.1.0" + } + }, + "optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmmirror.com/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + } + }, + "ora": { + "version": "3.4.0", + "resolved": "https://registry.npmmirror.com/ora/-/ora-3.4.0.tgz", + "integrity": "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-spinners": "^2.0.0", + "log-symbols": "^2.2.0", + "strip-ansi": "^5.2.0", + "wcwidth": "^1.0.1" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmmirror.com/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "dev": true + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "p-retry": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/p-retry/-/p-retry-3.0.1.tgz", + "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", + "dev": true, + "requires": { + "retry": "^0.12.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmmirror.com/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "dev": true, + "requires": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "param-case": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/param-case/-/param-case-2.1.1.tgz", + "integrity": "sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==", + "dev": true, + "requires": { + "no-case": "^2.2.0" + } + }, + "parchment": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/parchment/-/parchment-1.1.4.tgz", + "integrity": "sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg==" + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + }, + "dependencies": { + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + } + } + }, + "parse-asn1": { + "version": "5.1.7", + "resolved": "https://registry.npmmirror.com/parse-asn1/-/parse-asn1-5.1.7.tgz", + "integrity": "sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg==", + "dev": true, + "requires": { + "asn1.js": "^4.10.1", + "browserify-aes": "^1.2.0", + "evp_bytestokey": "^1.0.3", + "hash-base": "~3.0", + "pbkdf2": "^3.1.2", + "safe-buffer": "^5.2.1" + }, + "dependencies": { + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha512-EeeoJKjTyt868liAlVmcv2ZsUfGHlE3Q+BICOXcZiwN3osr5Q/zFGYmTJpoIzuaSTAwndFy+GqhEwlU4L3j4Ow==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + } + } + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmmirror.com/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", + "dev": true + }, + "parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "dev": true, + "requires": { + "parse5": "^6.0.1" + }, + "dependencies": { + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + } + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmmirror.com/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==", + "dev": true + }, + "path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmmirror.com/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmmirror.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true + } + } + }, + "pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "dev": true + }, + "picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "dev": true, + "requires": { + "semver-compare": "^1.0.0" + } + }, + "pnp-webpack-plugin": { + "version": "1.7.0", + "resolved": "https://registry.npmmirror.com/pnp-webpack-plugin/-/pnp-webpack-plugin-1.7.0.tgz", + "integrity": "sha512-2Rb3vm+EXble/sMXNSu6eoBx8e79gKqhNq9F5ZWW6ERNCTE/Q0wQNne5541tE5vKjfM8hpNCYL+LGc1YTfI0dg==", + "dev": true, + "requires": { + "ts-pnp": "^1.1.6" + } + }, + "portfinder": { + "version": "1.0.32", + "resolved": "https://registry.npmmirror.com/portfinder/-/portfinder-1.0.32.tgz", + "integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==", + "dev": true, + "requires": { + "async": "^2.6.4", + "debug": "^3.2.7", + "mkdirp": "^0.5.6" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmmirror.com/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + } + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmmirror.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==", + "dev": true + }, + "possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true + }, + "postcss": { + "version": "8.4.38", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "dev": true, + "requires": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.2.0" + } + }, + "postcss-calc": { + "version": "7.0.5", + "resolved": "https://registry.npmmirror.com/postcss-calc/-/postcss-calc-7.0.5.tgz", + "integrity": "sha512-1tKHutbGtLtEZF6PT4JSihCHfIVldU72mZ8SdZHIYriIZ9fh9k9aWSppaT8rHsyI3dX+KSR+W+Ix9BMY3AODrg==", + "dev": true, + "requires": { + "postcss": "^7.0.27", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-colormin": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/postcss-colormin/-/postcss-colormin-4.0.3.tgz", + "integrity": "sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "color": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-convert-values": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz", + "integrity": "sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ==", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-discard-comments": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz", + "integrity": "sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-discard-duplicates": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz", + "integrity": "sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-discard-empty": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz", + "integrity": "sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-discard-overridden": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz", + "integrity": "sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-load-config": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/postcss-load-config/-/postcss-load-config-2.1.2.tgz", + "integrity": "sha512-/rDeGV6vMUo3mwJZmeHfEDvwnTKKqQ0S7OHUi/kJvvtx3aWtyWG2/0ZWnzCt2keEclwN6Tf0DST2v9kITdOKYw==", + "dev": true, + "requires": { + "cosmiconfig": "^5.0.0", + "import-cwd": "^2.0.0" + } + }, + "postcss-loader": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/postcss-loader/-/postcss-loader-3.0.0.tgz", + "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "postcss": "^7.0.0", + "postcss-load-config": "^2.0.0", + "schema-utils": "^1.0.0" + }, + "dependencies": { + "json5": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.2", + "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-1.4.2.tgz", + "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-merge-longhand": { + "version": "4.0.11", + "resolved": "https://registry.npmmirror.com/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz", + "integrity": "sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw==", + "dev": true, + "requires": { + "css-color-names": "0.0.4", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "stylehacks": "^4.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-merge-rules": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz", + "integrity": "sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "cssnano-util-same-parent": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0", + "vendors": "^1.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-minify-font-values": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz", + "integrity": "sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg==", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-minify-gradients": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz", + "integrity": "sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "is-color-stop": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-minify-params": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz", + "integrity": "sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "browserslist": "^4.0.0", + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "uniqs": "^2.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-minify-selectors": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz", + "integrity": "sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-modules-extract-imports": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", + "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", + "dev": true, + "requires": { + "postcss": "^7.0.5" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-modules-local-by-default": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz", + "integrity": "sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw==", + "dev": true, + "requires": { + "icss-utils": "^4.1.1", + "postcss": "^7.0.32", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-modules-scope": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz", + "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==", + "dev": true, + "requires": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-modules-values": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", + "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", + "dev": true, + "requires": { + "icss-utils": "^4.0.0", + "postcss": "^7.0.6" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-normalize-charset": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz", + "integrity": "sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-normalize-display-values": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz", + "integrity": "sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ==", + "dev": true, + "requires": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-normalize-positions": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz", + "integrity": "sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-normalize-repeat-style": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz", + "integrity": "sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-normalize-string": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz", + "integrity": "sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA==", + "dev": true, + "requires": { + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-normalize-timing-functions": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz", + "integrity": "sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A==", + "dev": true, + "requires": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-normalize-unicode": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz", + "integrity": "sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-normalize-url": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz", + "integrity": "sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA==", + "dev": true, + "requires": { + "is-absolute-url": "^2.0.0", + "normalize-url": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-normalize-whitespace": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz", + "integrity": "sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA==", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-ordered-values": { + "version": "4.1.2", + "resolved": "https://registry.npmmirror.com/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz", + "integrity": "sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-prefix-selector": { + "version": "1.16.1", + "resolved": "https://registry.npmmirror.com/postcss-prefix-selector/-/postcss-prefix-selector-1.16.1.tgz", + "integrity": "sha512-Umxu+FvKMwlY6TyDzGFoSUnzW+NOfMBLyC1tAkIjgX+Z/qGspJeRjVC903D7mx7TuBpJlwti2ibXtWuA7fKMeQ==", + "dev": true + }, + "postcss-reduce-initial": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz", + "integrity": "sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-reduce-transforms": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz", + "integrity": "sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg==", + "dev": true, + "requires": { + "cssnano-util-get-match": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-selector-parser": { + "version": "6.1.0", + "resolved": "https://registry.npmmirror.com/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz", + "integrity": "sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + } + }, + "postcss-svgo": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/postcss-svgo/-/postcss-svgo-4.0.3.tgz", + "integrity": "sha512-NoRbrcMWTtUghzuKSoIm6XV+sJdvZ7GZSc3wdBN0W19FTtp2ko8NqLsgoh/m9CzNhU3KLPvQmjIwtaNFkaFTvw==", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "svgo": "^1.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-unique-selectors": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz", + "integrity": "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "postcss": "^7.0.0", + "uniqs": "^2.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "posthtml": { + "version": "0.9.2", + "resolved": "https://registry.npmmirror.com/posthtml/-/posthtml-0.9.2.tgz", + "integrity": "sha512-spBB5sgC4cv2YcW03f/IAUN1pgDJWNWD8FzkyY4mArLUMJW+KlQhlmUdKAHQuPfb00Jl5xIfImeOsf6YL8QK7Q==", + "dev": true, + "requires": { + "posthtml-parser": "^0.2.0", + "posthtml-render": "^1.0.5" + } + }, + "posthtml-parser": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/posthtml-parser/-/posthtml-parser-0.2.1.tgz", + "integrity": "sha512-nPC53YMqJnc/+1x4fRYFfm81KV2V+G9NZY+hTohpYg64Ay7NemWWcV4UWuy/SgMupqQ3kJ88M/iRfZmSnxT+pw==", + "dev": true, + "requires": { + "htmlparser2": "^3.8.3", + "isobject": "^2.1.0" + }, + "dependencies": { + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmmirror.com/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "dev": true, + "requires": { + "domelementtype": "1" + } + }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", + "dev": true + }, + "htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmmirror.com/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "dev": true, + "requires": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + } + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "posthtml-rename-id": { + "version": "1.0.12", + "resolved": "https://registry.npmmirror.com/posthtml-rename-id/-/posthtml-rename-id-1.0.12.tgz", + "integrity": "sha512-UKXf9OF/no8WZo9edRzvuMenb6AD5hDLzIepJW+a4oJT+T/Lx7vfMYWT4aWlGNQh0WMhnUx1ipN9OkZ9q+ddEw==", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5" + } + }, + "posthtml-render": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/posthtml-render/-/posthtml-render-1.4.0.tgz", + "integrity": "sha512-W1779iVHGfq0Fvh2PROhCe2QhB8mEErgqzo1wpIt36tCgChafP+hbXIhLDOM8ePJrZcFs0vkNEtdibEWVqChqw==", + "dev": true + }, + "posthtml-svg-mode": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/posthtml-svg-mode/-/posthtml-svg-mode-1.0.3.tgz", + "integrity": "sha512-hEqw9NHZ9YgJ2/0G7CECOeuLQKZi8HjWLkBaSVtOWjygQ9ZD8P7tqeowYs7WrFdKsWEKG7o+IlsPY8jrr0CJpQ==", + "dev": true, + "requires": { + "merge-options": "1.0.1", + "posthtml": "^0.9.2", + "posthtml-parser": "^0.2.1", + "posthtml-render": "^1.0.6" + } + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha512-PhmXi5XmoyKw1Un4E+opM2KcsJInDvKyuOumcjjw3waw86ZNjHwVUOOWLc4bCzLdcKNaWBH9e99sbWzDQsVaYg==", + "dev": true + }, + "prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmmirror.com/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "optional": true + }, + "pretty-error": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/pretty-error/-/pretty-error-2.1.2.tgz", + "integrity": "sha512-EY5oDzmsX5wvuynAByrmY0P0hcp+QpnAKbJng2A2MPjVKXCxrDSUkzghVJ4ZGPIv+JC4gX8fPUWscC0RtjsWGw==", + "dev": true, + "requires": { + "lodash": "^4.17.20", + "renderkid": "^2.0.4" + } + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmmirror.com/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "dev": true + }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==" + }, + "proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmmirror.com/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" + }, + "psl": { + "version": "1.9.0", + "resolved": "https://registry.npmmirror.com/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmmirror.com/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmmirror.com/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmmirror.com/q/-/q-1.5.1.tgz", + "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", + "dev": true + }, + "qs": { + "version": "6.5.3", + "resolved": "https://registry.npmmirror.com/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "dev": true + }, + "query-string": { + "version": "4.3.4", + "resolved": "https://registry.npmmirror.com/query-string/-/query-string-4.3.4.tgz", + "integrity": "sha512-O2XLNDBIg1DnTOa+2XrIwSiXEV8h2KImXUnjhhn2+UsvZ+Es2uyd5CCRTNQlDGbzUQOW3aYCBx9rVA6dzsiY7Q==", + "dev": true, + "requires": { + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==", + "dev": true + }, + "querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true + }, + "quill": { + "version": "1.3.7", + "resolved": "https://registry.npmmirror.com/quill/-/quill-1.3.7.tgz", + "integrity": "sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g==", + "requires": { + "clone": "^2.1.1", + "deep-equal": "^1.0.1", + "eventemitter3": "^2.0.3", + "extend": "^3.0.2", + "parchment": "^1.1.4", + "quill-delta": "^3.6.2" + } + }, + "quill-delta": { + "version": "3.6.3", + "resolved": "https://registry.npmmirror.com/quill-delta/-/quill-delta-3.6.3.tgz", + "integrity": "sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg==", + "requires": { + "deep-equal": "^1.0.1", + "extend": "^3.0.2", + "fast-diff": "1.1.2" + } + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true + }, + "raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmmirror.com/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dev": true, + "requires": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + } + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmmirror.com/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmmirror.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "dev": true, + "requires": { + "regenerate": "^1.4.2" + } + }, + "regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, + "regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmmirror.com/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.8.4" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmmirror.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "requires": { + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" + } + }, + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true + }, + "regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmmirror.com/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dev": true, + "requires": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + } + }, + "regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmmirror.com/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmmirror.com/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true + } + } + }, + "relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmmirror.com/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "dev": true + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", + "dev": true + }, + "renderkid": { + "version": "2.0.7", + "resolved": "https://registry.npmmirror.com/renderkid/-/renderkid-2.0.7.tgz", + "integrity": "sha512-oCcFyxaMrKsKcTY59qnCAtmDVSLfPbrv6A3tVbPdFMMrv5jaK10V6m40cKsoPNhAqN6rmHW9sswW4o3ruSrwUQ==", + "dev": true, + "requires": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true + }, + "css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + } + }, + "css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmmirror.com/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true + }, + "dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmmirror.com/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + } + }, + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true + }, + "domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmmirror.com/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true + }, + "nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "requires": { + "boolbase": "^1.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "repeat-element": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/repeat-element/-/repeat-element-1.1.4.tgz", + "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmmirror.com/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "dev": true + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmmirror.com/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true + }, + "resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmmirror.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==" + }, + "resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "requires": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha512-ccu8zQTrzVr954472aUVPLEcB3YpKSYR3cg/3lo1okzobPBM+1INXBbBZlDbnI/hbEocnf8j0QVo43hQKrbchg==", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmmirror.com/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmmirror.com/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true + }, + "rfdc": { + "version": "1.3.1", + "resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.3.1.tgz", + "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==", + "dev": true + }, + "rgb-regex": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/rgb-regex/-/rgb-regex-1.0.1.tgz", + "integrity": "sha512-gDK5mkALDFER2YLqH6imYvK6g02gpNGM4ILDZ472EwWfXZnC2ZEpoB2ECXTyOVUKuk/bPJZMzwQPBYICzP+D3w==", + "dev": true + }, + "rgba-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/rgba-regex/-/rgba-regex-1.0.0.tgz", + "integrity": "sha512-zgn5OjNQXLUTdq8m17KdaicF6w89TZs8ZU8y0AYENIU6wG8GG6LLm0yLSiPY8DmaYmHdgRW8rnApjoT0fQRfMg==", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmmirror.com/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha512-ntymy489o0/QQplUDnpYAYUsO50K9SBrIVaKCWDOJzYJts0f9WH9RFJkyagebkw5+y1oi00R7ynNW/d12GBumg==", + "dev": true, + "requires": { + "aproba": "^1.1.1" + } + }, + "runjs": { + "version": "4.4.2", + "resolved": "https://registry.npmmirror.com/runjs/-/runjs-4.4.2.tgz", + "integrity": "sha512-/DB54HRJnxfGA/a9QLZMyAn8H84SMt8oVGF7Vz+OS4BMCve312DXNRpy6Z8yohLuoMctoalXQtvmpd2ChQYD4Q==", + "dev": true, + "requires": { + "chalk": "2.3.0", + "lodash.padend": "4.6.1", + "microcli": "1.3.3", + "omelette": "0.4.5" + }, + "dependencies": { + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.1.0", + "escape-string-regexp": "^1.0.5", + "supports-color": "^4.0.0" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha512-P+1n3MnwjR/Epg9BBo1KT8qbye2g2Ou4sFumihwt6I4tsUX7jnLcX4BTOSKg/B1ZrIYMN9FcEnG4x5a7NB8Eng==", + "dev": true + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha512-ycQR/UbvI9xIlEdQT1TQqwoXtEldExbCEAJgRo5YXlmSKjv6ThHnP9/vwGa1gr19Gfw+LkFd7KqYMhzrRC5JYw==", + "dev": true, + "requires": { + "has-flag": "^2.0.0" + } + } + } + }, + "rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmmirror.com/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmmirror.com/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmmirror.com/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + } + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, + "requires": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "sass": { + "version": "1.32.13", + "resolved": "https://registry.npmmirror.com/sass/-/sass-1.32.13.tgz", + "integrity": "sha512-dEgI9nShraqP7cXQH+lEXVf73WOPCse0QlFzSD8k+1TcOxCMwVXfQlr0jtoluZysQOyJGnfr21dLvYKDJq8HkA==", + "dev": true, + "requires": { + "chokidar": ">=3.0.0 <4.0.0" + } + }, + "sass-loader": { + "version": "10.1.1", + "resolved": "https://registry.npmmirror.com/sass-loader/-/sass-loader-10.1.1.tgz", + "integrity": "sha512-W6gVDXAd5hR/WHsPicvZdjAWHBcEJ44UahgxcIE196fW2ong0ZHMPO1kZuI5q0VlvMQZh32gpv69PLWQm70qrw==", + "dev": true, + "requires": { + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "neo-async": "^2.6.2", + "schema-utils": "^3.0.0", + "semver": "^7.3.2" + }, + "dependencies": { + "schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "semver": { + "version": "7.6.2", + "resolved": "https://registry.npmmirror.com/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true + } + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmmirror.com/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + } + }, + "screenfull": { + "version": "5.0.2", + "resolved": "https://registry.npmmirror.com/screenfull/-/screenfull-5.0.2.tgz", + "integrity": "sha512-cCF2b+L/mnEiORLN5xSAz6H3t18i2oHh9BA8+CQlAh5DRw2+NFAGQJOSYbcGw8B2k04g/lVvFcfZ83b3ysH5UQ==" + }, + "script-ext-html-webpack-plugin": { + "version": "2.1.5", + "resolved": "https://registry.npmmirror.com/script-ext-html-webpack-plugin/-/script-ext-html-webpack-plugin-2.1.5.tgz", + "integrity": "sha512-nMjd5dtsnoB8dS+pVM9ZL4mC9O1uVtTxrDS99OGZsZxFbkZE6pw0HCMued/cncDrKivIShO9vwoyOTvsGqQHEQ==", + "dev": true, + "requires": { + "debug": "^4.2.0" + } + }, + "select": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/select/-/select-1.1.2.tgz", + "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==" + }, + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "dev": true + }, + "selfsigned": { + "version": "1.10.14", + "resolved": "https://registry.npmmirror.com/selfsigned/-/selfsigned-1.10.14.tgz", + "integrity": "sha512-lkjaiAye+wBZDCBsu5BGi0XiLRxeUlsGod5ZP924CRSEoGuZAw/f7y9RKu28rwTfiHVhdavhB0qH0INV6P1lEA==", + "dev": true, + "requires": { + "node-forge": "^0.10.0" + } + }, + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmmirror.com/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" + }, + "semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "dev": true + }, + "send": { + "version": "0.18.0", + "resolved": "https://registry.npmmirror.com/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + } + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmmirror.com/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmmirror.com/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmmirror.com/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true + } + } + }, + "serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmmirror.com/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true + }, + "set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmmirror.com/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "requires": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + } + }, + "set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "requires": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + } + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmmirror.com/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true + }, + "shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmmirror.com/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true + }, + "side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + } + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha512-fCvEXfh6NWpm+YSuY2bpXb/VIihqWA6hLsgboC+0nl71Q7N7o2eaCW8mJa/NLvQhs6jpd3VZV4UiUQlV6+lc8g==" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmmirror.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "dev": true, + "requires": { + "is-arrayish": "^0.3.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmmirror.com/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "dev": true + } + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true + } + } + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmmirror.com/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmmirror.com/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-descriptor": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/is-descriptor/-/is-descriptor-1.0.3.tgz", + "integrity": "sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmmirror.com/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmmirror.com/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dev": true, + "requires": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + }, + "dependencies": { + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmmirror.com/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true + } + } + }, + "sockjs-client": { + "version": "1.6.1", + "resolved": "https://registry.npmmirror.com/sockjs-client/-/sockjs-client-1.6.1.tgz", + "integrity": "sha512-2g0tjOR+fRs0amxENLi/q5TiJTqY+WXFOzb5UwXndlK6TO3U/mirZznpx6w34HVMoc3g7cY24yC/ZMIYnDlfkw==", + "dev": true, + "requires": { + "debug": "^3.2.7", + "eventsource": "^2.0.2", + "faye-websocket": "^0.11.4", + "inherits": "^2.0.4", + "url-parse": "^1.5.10" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmmirror.com/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==", + "dev": true, + "requires": { + "is-plain-obj": "^1.0.0" + } + }, + "sortablejs": { + "version": "1.10.2", + "resolved": "https://registry.npmmirror.com/sortablejs/-/sortablejs-1.10.2.tgz", + "integrity": "sha512-YkPGufevysvfwn5rfdlGyrGjt7/CRHwvRPogD/lC+TnvcN29jDpCifKP+rBqf+LRldfXSTh+0CGLcSg0VIxq3A==" + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "dev": true + }, + "source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmmirror.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "source-map-url": { + "version": "0.4.1", + "resolved": "https://registry.npmmirror.com/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", + "dev": true + }, + "spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmmirror.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.18", + "resolved": "https://registry.npmmirror.com/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz", + "integrity": "sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==", + "dev": true + }, + "spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + } + }, + "spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "sshpk": { + "version": "1.18.0", + "resolved": "https://registry.npmmirror.com/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "ssri": { + "version": "6.0.2", + "resolved": "https://registry.npmmirror.com/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npmmirror.com/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "dev": true + }, + "stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmmirror.com/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmmirror.com/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmmirror.com/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true + }, + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmmirror.com/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmmirror.com/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dev": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "stream-shift": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/stream-shift/-/stream-shift-1.0.3.tgz", + "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", + "dev": true + }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==", + "dev": true + }, + "string-argv": { + "version": "0.3.1", + "resolved": "https://registry.npmmirror.com/string-argv/-/string-argv-0.3.1.tgz", + "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmmirror.com/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + } + }, + "string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmmirror.com/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + } + }, + "string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmmirror.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmmirror.com/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "dev": true, + "requires": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + }, + "dependencies": { + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", + "dev": true + } + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + } + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", + "dev": true + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, + "strip-indent": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/strip-indent/-/strip-indent-2.0.0.tgz", + "integrity": "sha512-RsSNPLpq6YUL7QYy44RnPVTn/lcVZtb48Uof3X5JLbF4zD/Gs7ZFDv2HWol+leoQN2mT86LAzSshGfkTlSOpsA==", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "stylehacks": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/stylehacks/-/stylehacks-4.0.3.tgz", + "integrity": "sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "svg-baker": { + "version": "1.7.0", + "resolved": "https://registry.npmmirror.com/svg-baker/-/svg-baker-1.7.0.tgz", + "integrity": "sha512-nibslMbkXOIkqKVrfcncwha45f97fGuAOn1G99YwnwTj8kF9YiM6XexPcUso97NxOm6GsP0SIvYVIosBis1xLg==", + "dev": true, + "requires": { + "bluebird": "^3.5.0", + "clone": "^2.1.1", + "he": "^1.1.1", + "image-size": "^0.5.1", + "loader-utils": "^1.1.0", + "merge-options": "1.0.1", + "micromatch": "3.1.0", + "postcss": "^5.2.17", + "postcss-prefix-selector": "^1.6.0", + "posthtml-rename-id": "^1.0", + "posthtml-svg-mode": "^1.0.3", + "query-string": "^4.3.2", + "traverse": "^0.6.6" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "dev": true + } + } + }, + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==", + "dev": true + }, + "is-descriptor": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/is-descriptor/-/is-descriptor-1.0.3.tgz", + "integrity": "sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.1", + "is-data-descriptor": "^1.0.1" + } + }, + "json5": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmmirror.com/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + }, + "loader-utils": { + "version": "1.4.2", + "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-1.4.2.tgz", + "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "micromatch": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-3.1.0.tgz", + "integrity": "sha512-3StSelAE+hnRvMs8IdVW7Uhk8CVed5tp+kLLGlBP6WiRAXS21GPGu/Nat4WNPXj2Eoc24B02SaeoyozPMfj0/g==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.2.2", + "define-property": "^1.0.0", + "extend-shallow": "^2.0.1", + "extglob": "^2.0.2", + "fragment-cache": "^0.2.1", + "kind-of": "^5.0.2", + "nanomatch": "^1.2.1", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==", + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } + } + } + }, + "svg-baker-runtime": { + "version": "1.4.7", + "resolved": "https://registry.npmmirror.com/svg-baker-runtime/-/svg-baker-runtime-1.4.7.tgz", + "integrity": "sha512-Zorfwwj5+lWjk/oxwSMsRdS2sPQQdTmmsvaSpzU+i9ZWi3zugHLt6VckWfnswphQP0LmOel3nggpF5nETbt6xw==", + "dev": true, + "requires": { + "deepmerge": "1.3.2", + "mitt": "1.1.2", + "svg-baker": "^1.7.0" + }, + "dependencies": { + "deepmerge": { + "version": "1.3.2", + "resolved": "https://registry.npmmirror.com/deepmerge/-/deepmerge-1.3.2.tgz", + "integrity": "sha512-qjMjTrk+RKv/sp4RPDpV5CnKhxjFI9p+GkLBOls5A8EEElldYWCWA9zceAkmfd0xIo2aU1nxiaLFoiya2sb6Cg==", + "dev": true + } + } + }, + "svg-sprite-loader": { + "version": "5.1.1", + "resolved": "https://registry.npmmirror.com/svg-sprite-loader/-/svg-sprite-loader-5.1.1.tgz", + "integrity": "sha512-oRjDBw3AtZOb+XTx7XE3HcVju9RdnfdXttT3ZJB/vmWGJ+SM+xfXzh3yuVPIpySO8FjGhH5BtU63lGMI9WgYzA==", + "dev": true, + "requires": { + "bluebird": "^3.5.0", + "deepmerge": "1.3.2", + "domready": "1.0.8", + "escape-string-regexp": "1.0.5", + "html-webpack-plugin": "^3.2.0", + "loader-utils": "^1.1.0", + "svg-baker": "^1.5.0", + "svg-baker-runtime": "^1.4.7", + "url-slug": "2.0.0" + }, + "dependencies": { + "deepmerge": { + "version": "1.3.2", + "resolved": "https://registry.npmmirror.com/deepmerge/-/deepmerge-1.3.2.tgz", + "integrity": "sha512-qjMjTrk+RKv/sp4RPDpV5CnKhxjFI9p+GkLBOls5A8EEElldYWCWA9zceAkmfd0xIo2aU1nxiaLFoiya2sb6Cg==", + "dev": true + }, + "json5": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.2", + "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-1.4.2.tgz", + "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + } + } + }, + "svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", + "dev": true + }, + "svgo": { + "version": "1.3.2", + "resolved": "https://registry.npmmirror.com/svgo/-/svgo-1.3.2.tgz", + "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "coa": "^2.0.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "^0.1.1", + "css-tree": "1.0.0-alpha.37", + "csso": "^4.0.2", + "js-yaml": "^3.13.1", + "mkdirp": "~0.5.1", + "object.values": "^1.1.0", + "sax": "~1.2.4", + "stable": "^0.1.8", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + } + } + }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmmirror.com/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmmirror.com/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true + }, + "tar": { + "version": "6.2.1", + "resolved": "https://registry.npmmirror.com/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dev": true, + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "dependencies": { + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true + }, + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "terser": { + "version": "4.8.1", + "resolved": "https://registry.npmmirror.com/terser/-/terser-4.8.1.tgz", + "integrity": "sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmmirror.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dev": true, + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "dependencies": { + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmmirror.com/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmmirror.com/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "requires": { + "any-promise": "^1.0.0" + } + }, + "thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmmirror.com/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "requires": { + "thenify": ">= 3.1.0 < 4" + } + }, + "thread-loader": { + "version": "2.1.3", + "resolved": "https://registry.npmmirror.com/thread-loader/-/thread-loader-2.1.3.tgz", + "integrity": "sha512-wNrVKH2Lcf8ZrWxDF/khdlLlsTMczdcwPA9VEK4c2exlEPynYWxi9op3nPTo5lAnDIkE0rQEB3VBP+4Zncc9Hg==", + "dev": true, + "requires": { + "loader-runner": "^2.3.1", + "loader-utils": "^1.1.0", + "neo-async": "^2.6.0" + }, + "dependencies": { + "json5": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.2", + "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-1.4.2.tgz", + "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + } + } + }, + "throttle-debounce": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/throttle-debounce/-/throttle-debounce-1.1.0.tgz", + "integrity": "sha512-XH8UiPCQcWNuk2LYePibW/4qL97+ZQ1AN3FNXwZRBNPPowo/NRU5fAlDCSNBJIYCKbioZfuYtMhG4quqoJhVzg==" + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmmirror.com/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmmirror.com/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true + }, + "timers-browserify": { + "version": "2.0.12", + "resolved": "https://registry.npmmirror.com/timers-browserify/-/timers-browserify-2.0.12.tgz", + "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "dev": true, + "requires": { + "setimmediate": "^1.0.4" + } + }, + "timsort": { + "version": "0.3.0", + "resolved": "https://registry.npmmirror.com/timsort/-/timsort-0.3.0.tgz", + "integrity": "sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A==", + "dev": true + }, + "tiny-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz", + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmmirror.com/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmmirror.com/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmmirror.com/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true + }, + "toposort": { + "version": "1.0.7", + "resolved": "https://registry.npmmirror.com/toposort/-/toposort-1.0.7.tgz", + "integrity": "sha512-FclLrw8b9bMWf4QlCJuHBEVhSRsqDj6u3nIjAzPeJvgl//1hBlffdlk0MALceL14+koWEdU4ofRAXofbODxQzg==", + "dev": true + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmmirror.com/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "traverse": { + "version": "0.6.9", + "resolved": "https://registry.npmmirror.com/traverse/-/traverse-0.6.9.tgz", + "integrity": "sha512-7bBrcF+/LQzSgFmT0X5YclVqQxtv7TDJ1f8Wj7ibBu/U6BMLeOpUxuZjV7rMc44UtKxlnMFigdhFAIszSX1DMg==", + "dev": true, + "requires": { + "gopd": "^1.0.1", + "typedarray.prototype.slice": "^1.0.3", + "which-typed-array": "^1.1.15" + } + }, + "tryer": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/tryer/-/tryer-1.0.1.tgz", + "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==", + "dev": true + }, + "ts-pnp": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/ts-pnp/-/ts-pnp-1.2.0.tgz", + "integrity": "sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==", + "dev": true + }, + "tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==" + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmmirror.com/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw==", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmmirror.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmmirror.com/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "dev": true + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmmirror.com/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + } + }, + "typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + } + }, + "typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + } + }, + "typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmmirror.com/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmmirror.com/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "dev": true + }, + "typedarray.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/typedarray.prototype.slice/-/typedarray.prototype.slice-1.0.3.tgz", + "integrity": "sha512-8WbVAQAUlENo1q3c3zZYuy5k9VzBQvp8AX9WOtbvyWlLM1v5JaSRmjubLjzHF4JFtptjH/5c/i95yaElvcjC0A==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-errors": "^1.3.0", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-offset": "^1.0.2" + } + }, + "uglify-js": { + "version": "3.4.10", + "resolved": "https://registry.npmmirror.com/uglify-js/-/uglify-js-3.4.10.tgz", + "integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==", + "dev": true, + "requires": { + "commander": "~2.19.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "commander": { + "version": "2.19.0", + "resolved": "https://registry.npmmirror.com/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + } + }, + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "dev": true + }, + "unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true + }, + "unidecode": { + "version": "0.1.8", + "resolved": "https://registry.npmmirror.com/unidecode/-/unidecode-0.1.8.tgz", + "integrity": "sha512-SdoZNxCWpN2tXTCrGkPF/0rL2HEq+i2gwRG1ReBvx8/0yTzC3enHfugOf8A9JBShVwwrRIkLX0YcDUGbzjbVCA==", + "dev": true + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA==", + "dev": true + }, + "uniqs": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/uniqs/-/uniqs-2.0.0.tgz", + "integrity": "sha512-mZdDpf3vBV5Efh29kMw5tXoup/buMgxLzOt/XKFKcVmi+15ManNQWr6HfZ2aiZTYlYixbdNJ0KFmIZIv52tHSQ==", + "dev": true + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmmirror.com/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true + }, + "unquote": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/unquote/-/unquote-1.1.1.tgz", + "integrity": "sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg==", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmmirror.com/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmmirror.com/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==", + "dev": true + } + } + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true + }, + "update-browserslist-db": { + "version": "1.0.16", + "resolved": "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", + "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", + "dev": true, + "requires": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + } + }, + "upper-case": { + "version": "1.1.3", + "resolved": "https://registry.npmmirror.com/upper-case/-/upper-case-1.1.3.tgz", + "integrity": "sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==", + "dev": true + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmmirror.com/urix/-/urix-0.1.0.tgz", + "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==", + "dev": true + }, + "url": { + "version": "0.11.3", + "resolved": "https://registry.npmmirror.com/url/-/url-0.11.3.tgz", + "integrity": "sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==", + "dev": true, + "requires": { + "punycode": "^1.4.1", + "qs": "^6.11.2" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmmirror.com/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true + }, + "qs": { + "version": "6.12.1", + "resolved": "https://registry.npmmirror.com/qs/-/qs-6.12.1.tgz", + "integrity": "sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==", + "dev": true, + "requires": { + "side-channel": "^1.0.6" + } + } + } + }, + "url-loader": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/url-loader/-/url-loader-2.3.0.tgz", + "integrity": "sha512-goSdg8VY+7nPZKUEChZSEtW5gjbS66USIGCeSJ1OVOJ7Yfuh/36YxCwMi5HVEJh6mqUYOoy3NJ0vlOMrWsSHog==", + "dev": true, + "requires": { + "loader-utils": "^1.2.3", + "mime": "^2.4.4", + "schema-utils": "^2.5.0" + }, + "dependencies": { + "json5": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.2", + "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-1.4.2.tgz", + "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + } + } + }, + "url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmmirror.com/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dev": true, + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "url-slug": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/url-slug/-/url-slug-2.0.0.tgz", + "integrity": "sha512-aiNmSsVgrjCiJ2+KWPferjT46YFKoE8i0YX04BlMVDue022Xwhg/zYlnZ6V9/mP3p8Wj7LEp0myiTkC/p6sxew==", + "dev": true, + "requires": { + "unidecode": "0.1.8" + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmmirror.com/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "requires": { + "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + } + }, + "utila": { + "version": "0.4.0", + "resolved": "https://registry.npmmirror.com/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", + "dev": true + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmmirror.com/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + }, + "v8-compile-cache": { + "version": "2.4.0", + "resolved": "https://registry.npmmirror.com/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz", + "integrity": "sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true + }, + "vendors": { + "version": "1.0.4", + "resolved": "https://registry.npmmirror.com/vendors/-/vendors-1.0.4.tgz", + "integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmmirror.com/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmmirror.com/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true + }, + "vue": { + "version": "2.6.12", + "resolved": "https://registry.npmmirror.com/vue/-/vue-2.6.12.tgz", + "integrity": "sha512-uhmLFETqPPNyuLLbsKz6ioJ4q7AZHzD8ZVFNATNyICSZouqP2Sz0rotWQC8UNBF6VGSCs5abnKJoStA6JbCbfg==" + }, + "vue-count-to": { + "version": "1.0.13", + "resolved": "https://registry.npmmirror.com/vue-count-to/-/vue-count-to-1.0.13.tgz", + "integrity": "sha512-6R4OVBVNtQTlcbXu6SJ8ENR35M2/CdWt3Jmv57jOUM+1ojiFmjVGvZPH8DfHpMDSA+ITs+EW5V6qthADxeyYOQ==" + }, + "vue-cropper": { + "version": "0.5.5", + "resolved": "https://registry.npmmirror.com/vue-cropper/-/vue-cropper-0.5.5.tgz", + "integrity": "sha512-5mGaBlS1EwLxUFwHHX2Q8zOZSiVfBUjOfolR+ZNKwu7Rh3u+GhwHYOyFkgZHhhoQBBNdyVB28O6W+MpMimhCbA==" + }, + "vue-eslint-parser": { + "version": "7.11.0", + "resolved": "https://registry.npmmirror.com/vue-eslint-parser/-/vue-eslint-parser-7.11.0.tgz", + "integrity": "sha512-qh3VhDLeh773wjgNTl7ss0VejY9bMMa0GoDG2fQVyDzRFdiU3L7fw74tWZDHNQXdZqxO3EveQroa9ct39D2nqg==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "eslint-scope": "^5.1.1", + "eslint-visitor-keys": "^1.1.0", + "espree": "^6.2.1", + "esquery": "^1.4.0", + "lodash": "^4.17.21", + "semver": "^6.3.0" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmmirror.com/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "espree": { + "version": "6.2.1", + "resolved": "https://registry.npmmirror.com/espree/-/espree-6.2.1.tgz", + "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", + "dev": true, + "requires": { + "acorn": "^7.1.1", + "acorn-jsx": "^5.2.0", + "eslint-visitor-keys": "^1.1.0" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "vue-hot-reload-api": { + "version": "2.3.4", + "resolved": "https://registry.npmmirror.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz", + "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==", + "dev": true + }, + "vue-loader": { + "version": "15.11.1", + "resolved": "https://registry.npmmirror.com/vue-loader/-/vue-loader-15.11.1.tgz", + "integrity": "sha512-0iw4VchYLePqJfJu9s62ACWUXeSqM30SQqlIftbYWM3C+jpPcEHKSPUZBLjSF9au4HTHQ/naF6OGnO3Q/qGR3Q==", + "dev": true, + "requires": { + "@vue/component-compiler-utils": "^3.1.0", + "hash-sum": "^1.0.2", + "loader-utils": "^1.1.0", + "vue-hot-reload-api": "^2.3.0", + "vue-style-loader": "^4.1.0" + }, + "dependencies": { + "hash-sum": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/hash-sum/-/hash-sum-1.0.2.tgz", + "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==", + "dev": true + }, + "json5": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.2", + "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-1.4.2.tgz", + "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + } + } + }, + "vue-meta": { + "version": "2.4.0", + "resolved": "https://registry.npmmirror.com/vue-meta/-/vue-meta-2.4.0.tgz", + "integrity": "sha512-XEeZUmlVeODclAjCNpWDnjgw+t3WA6gdzs6ENoIAgwO1J1d5p1tezDhtteLUFwcaQaTtayRrsx7GL6oXp/m2Jw==", + "requires": { + "deepmerge": "^4.2.2" + }, + "dependencies": { + "deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmmirror.com/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==" + } + } + }, + "vue-router": { + "version": "3.4.9", + "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-3.4.9.tgz", + "integrity": "sha512-CGAKWN44RqXW06oC+u4mPgHLQQi2t6vLD/JbGRDAXm0YpMv0bgpKuU5bBd7AvMgfTz9kXVRIWKHqRwGEb8xFkA==" + }, + "vue-style-loader": { + "version": "4.1.3", + "resolved": "https://registry.npmmirror.com/vue-style-loader/-/vue-style-loader-4.1.3.tgz", + "integrity": "sha512-sFuh0xfbtpRlKfm39ss/ikqs9AbKCoXZBpHeVZ8Tx650o0k0q/YCM7FRvigtxpACezfq6af+a7JeqVTWvncqDg==", + "dev": true, + "requires": { + "hash-sum": "^1.0.2", + "loader-utils": "^1.0.2" + }, + "dependencies": { + "hash-sum": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/hash-sum/-/hash-sum-1.0.2.tgz", + "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==", + "dev": true + }, + "json5": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.2", + "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-1.4.2.tgz", + "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + } + } + }, + "vue-template-compiler": { + "version": "2.6.12", + "resolved": "https://registry.npmmirror.com/vue-template-compiler/-/vue-template-compiler-2.6.12.tgz", + "integrity": "sha512-OzzZ52zS41YUbkCBfdXShQTe69j1gQDZ9HIX8miuC9C3rBCk9wIRjLiZZLrmX9V+Ftq/YEyv1JaVr5Y/hNtByg==", + "dev": true, + "requires": { + "de-indent": "^1.0.2", + "he": "^1.1.0" + } + }, + "vue-template-es2015-compiler": { + "version": "1.9.1", + "resolved": "https://registry.npmmirror.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz", + "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==", + "dev": true + }, + "vuedraggable": { + "version": "2.24.3", + "resolved": "https://registry.npmmirror.com/vuedraggable/-/vuedraggable-2.24.3.tgz", + "integrity": "sha512-6/HDXi92GzB+Hcs9fC6PAAozK1RLt1ewPTLjK0anTYguXLAeySDmcnqE8IC0xa7shvSzRjQXq3/+dsZ7ETGF3g==", + "requires": { + "sortablejs": "1.10.2" + } + }, + "vuex": { + "version": "3.6.0", + "resolved": "https://registry.npmmirror.com/vuex/-/vuex-3.6.0.tgz", + "integrity": "sha512-W74OO2vCJPs9/YjNjW8lLbj+jzT24waTo2KShI8jLvJW8OaIkgb3wuAMA7D+ZiUxDOx3ubwSZTaJBip9G8a3aQ==" + }, + "watch-size": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/watch-size/-/watch-size-2.0.0.tgz", + "integrity": "sha512-M92R89dNoTPWyCD+HuUEDdhaDnh9jxPGOwlDc0u51jAgmjUvzqaEMynXSr3BaWs+QdHYk4KzibPy1TFtjLmOZQ==" + }, + "watchpack": { + "version": "1.7.5", + "resolved": "https://registry.npmmirror.com/watchpack/-/watchpack-1.7.5.tgz", + "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", + "dev": true, + "requires": { + "chokidar": "^3.4.1", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.1" + } + }, + "watchpack-chokidar2": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz", + "integrity": "sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==", + "dev": true, + "optional": true, + "requires": { + "chokidar": "^2.1.8" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "optional": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "optional": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "optional": true + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "optional": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "dev": true, + "optional": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "optional": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==", + "dev": true, + "optional": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "optional": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + } + } + }, + "wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmmirror.com/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "requires": { + "minimalistic-assert": "^1.0.0" + } + }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "requires": { + "defaults": "^1.0.3" + } + }, + "webpack": { + "version": "4.47.0", + "resolved": "https://registry.npmmirror.com/webpack/-/webpack-4.47.0.tgz", + "integrity": "sha512-td7fYwgLSrky3fI1EuU5cneU4+pbH6GgOfuKNS1tNPcfdGinGELAqsb/BP4nnvZyKSG2i/xFGU7+n2PvZA8HJQ==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.5.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "json5": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.2", + "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-1.4.2.tgz", + "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "webpack-bundle-analyzer": { + "version": "3.9.0", + "resolved": "https://registry.npmmirror.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.9.0.tgz", + "integrity": "sha512-Ob8amZfCm3rMB1ScjQVlbYYUEJyEjdEtQ92jqiFUYt5VkEeO2v5UMbv49P/gnmCZm3A6yaFQzCBvpZqN4MUsdA==", + "dev": true, + "requires": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1", + "bfj": "^6.1.1", + "chalk": "^2.4.1", + "commander": "^2.18.0", + "ejs": "^2.6.1", + "express": "^4.16.3", + "filesize": "^3.6.1", + "gzip-size": "^5.0.0", + "lodash": "^4.17.19", + "mkdirp": "^0.5.1", + "opener": "^1.5.1", + "ws": "^6.0.0" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmmirror.com/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + } + } + }, + "webpack-chain": { + "version": "6.5.1", + "resolved": "https://registry.npmmirror.com/webpack-chain/-/webpack-chain-6.5.1.tgz", + "integrity": "sha512-7doO/SRtLu8q5WM0s7vPKPWX580qhi0/yBHkOxNkv50f6qB76Zy9o2wRTrrPULqYTvQlVHuvbA8v+G5ayuUDsA==", + "dev": true, + "requires": { + "deepmerge": "^1.5.2", + "javascript-stringify": "^2.0.1" + } + }, + "webpack-dev-middleware": { + "version": "3.7.3", + "resolved": "https://registry.npmmirror.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz", + "integrity": "sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ==", + "dev": true, + "requires": { + "memory-fs": "^0.4.1", + "mime": "^2.4.4", + "mkdirp": "^0.5.1", + "range-parser": "^1.2.1", + "webpack-log": "^2.0.0" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + } + } + }, + "webpack-dev-server": { + "version": "3.11.3", + "resolved": "https://registry.npmmirror.com/webpack-dev-server/-/webpack-dev-server-3.11.3.tgz", + "integrity": "sha512-3x31rjbEQWKMNzacUZRE6wXvUFuGpH7vr0lIEbYpMAG9BOxi0928QU1BBswOAP3kg3H1O4hiS+sq4YyAn6ANnA==", + "dev": true, + "requires": { + "ansi-html-community": "0.0.8", + "bonjour": "^3.5.0", + "chokidar": "^2.1.8", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", + "debug": "^4.1.1", + "del": "^4.1.1", + "express": "^4.17.1", + "html-entities": "^1.3.1", + "http-proxy-middleware": "0.19.1", + "import-local": "^2.0.0", + "internal-ip": "^4.3.0", + "ip": "^1.1.5", + "is-absolute-url": "^3.0.3", + "killable": "^1.0.1", + "loglevel": "^1.6.8", + "opn": "^5.5.0", + "p-retry": "^3.0.1", + "portfinder": "^1.0.26", + "schema-utils": "^1.0.0", + "selfsigned": "^1.10.8", + "semver": "^6.3.0", + "serve-index": "^1.9.1", + "sockjs": "^0.3.21", + "sockjs-client": "^1.5.0", + "spdy": "^4.0.2", + "strip-ansi": "^3.0.1", + "supports-color": "^6.1.0", + "url": "^0.11.0", + "webpack-dev-middleware": "^3.7.2", + "webpack-log": "^2.0.0", + "ws": "^6.2.1", + "yargs": "^13.3.2" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmmirror.com/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-absolute-url": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz", + "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmmirror.com/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "dev": true, + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + } + }, + "webpack-merge": { + "version": "4.2.2", + "resolved": "https://registry.npmmirror.com/webpack-merge/-/webpack-merge-4.2.2.tgz", + "integrity": "sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==", + "dev": true, + "requires": { + "lodash": "^4.17.15" + } + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmmirror.com/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmmirror.com/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "requires": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmmirror.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmmirror.com/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, + "which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "dev": true + }, + "which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmmirror.com/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + } + }, + "word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true + }, + "worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmmirror.com/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "dev": true, + "requires": { + "errno": "~0.1.7" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "ws": { + "version": "6.2.2", + "resolved": "https://registry.npmmirror.com/ws/-/ws-6.2.2.tgz", + "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmmirror.com/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==" + }, + "yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmmirror.com/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmmirror.com/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "dependencies": { + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmmirror.com/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + } + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true + }, + "yorkie": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/yorkie/-/yorkie-2.0.0.tgz", + "integrity": "sha512-jcKpkthap6x63MB4TxwCyuIGkV0oYP/YRyuQU5UO0Yz/E/ZAu+653/uov+phdmO54n6BcvFRyyt0RRrWdN2mpw==", + "dev": true, + "requires": { + "execa": "^0.8.0", + "is-ci": "^1.0.10", + "normalize-path": "^1.0.0", + "strip-indent": "^2.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "0.8.0", + "resolved": "https://registry.npmmirror.com/execa/-/execa-0.8.0.tgz", + "integrity": "sha512-zDWS+Rb1E8BlqqhALSt9kUhss8Qq4nN3iof3gsOdyINksElaPyNBtKUMTR62qhvgVWR0CqCX7sdnKe4MnUbFEA==", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", + "dev": true + }, + "normalize-path": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-1.0.0.tgz", + "integrity": "sha512-7WyT0w8jhpDStXRq5836AMmihQwq2nrUVQrgjvUo/p/NZf9uy/MeJ246lBJVmWuYXMlJuG9BNZHF0hWjfTbQUA==", + "dev": true + } + } + }, + "zrender": { + "version": "5.4.0", + "resolved": "https://registry.npmmirror.com/zrender/-/zrender-5.4.0.tgz", + "integrity": "sha512-rOS09Z2HSVGFs2dn/TuYk5BlCaZcVe8UDLLjj1ySYF828LATKKdxuakSZMvrDz54yiKPDYVfjdKqcX8Jky3BIA==", + "requires": { + "tslib": "2.3.0" + } + } + } +} diff --git a/custom-ui/package.json b/custom-ui/package.json new file mode 100644 index 0000000..e4d2180 --- /dev/null +++ b/custom-ui/package.json @@ -0,0 +1,90 @@ +{ + "name": "ruoyi", + "version": "3.8.5", + "description": "后台管理系统", + "author": "若依", + "license": "MIT", + "scripts": { + "dev": "vue-cli-service serve", + "build:prod": "vue-cli-service build", + "build:stage": "vue-cli-service build --mode staging", + "preview": "node build/index.js --preview", + "lint": "eslint --ext .js,.vue src" + }, + "husky": { + "hooks": { + "pre-commit": "lint-staged" + } + }, + "lint-staged": { + "src/**/*.{js,vue}": [ + "eslint --fix", + "git add" + ] + }, + "keywords": [ + "vue", + "admin", + "dashboard", + "element-ui", + "boilerplate", + "admin-template", + "management-system" + ], + "repository": { + "type": "git", + "url": "https://gitee.com/y_project/RuoYi-Vue.git" + }, + "dependencies": { + "@riophae/vue-treeselect": "0.4.0", + "axios": "0.24.0", + "clipboard": "2.0.8", + "core-js": "3.25.3", + "echarts": "5.4.0", + "element-ui": "2.15.12", + "file-saver": "2.0.5", + "fuse.js": "6.4.3", + "highlight.js": "9.18.5", + "js-beautify": "1.13.0", + "js-cookie": "3.0.1", + "jsencrypt": "3.0.0-rc.1", + "nprogress": "0.2.0", + "quill": "1.3.7", + "screenfull": "5.0.2", + "sortablejs": "1.10.2", + "vue": "2.6.12", + "vue-count-to": "1.0.13", + "vue-cropper": "0.5.5", + "vue-meta": "2.4.0", + "vue-router": "3.4.9", + "vuedraggable": "2.24.3", + "vuex": "3.6.0" + }, + "devDependencies": { + "@vue/cli-plugin-babel": "4.4.6", + "@vue/cli-plugin-eslint": "4.4.6", + "@vue/cli-service": "4.4.6", + "babel-eslint": "10.1.0", + "babel-plugin-dynamic-import-node": "2.3.3", + "chalk": "4.1.0", + "compression-webpack-plugin": "5.0.2", + "connect": "3.6.6", + "eslint": "7.15.0", + "eslint-plugin-vue": "7.2.0", + "lint-staged": "10.5.3", + "runjs": "4.4.2", + "sass": "1.32.13", + "sass-loader": "10.1.1", + "script-ext-html-webpack-plugin": "2.1.5", + "svg-sprite-loader": "5.1.1", + "vue-template-compiler": "2.6.12" + }, + "engines": { + "node": ">=8.9", + "npm": ">= 3.0.0" + }, + "browserslist": [ + "> 1%", + "last 2 versions" + ] +} diff --git a/custom-ui/public/favicon.ico b/custom-ui/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..e26376026420542212ed58d90d0ed34f554fa4ae GIT binary patch literal 5663 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 + + + + 请升级您的浏览器 + + + + + + +

请升级您的浏览器,以便我们更好的为您提供服务!

+

您正在使用 Internet Explorer 的早期版本(IE11以下版本或使用该内核的浏览器)。这意味着在升级浏览器前,您将无法访问此网站。

+
+

请注意:微软公司对Windows XP 及 Internet Explorer 早期版本的支持已经结束

+

自 2016 年 1 月 12 日起,Microsoft 不再为 IE 11 以下版本提供相应支持和更新。没有关键的浏览器安全更新,您的电脑可能易受有害病毒、间谍软件和其他恶意软件的攻击,它们可以窃取或损害您的业务数据和信息。请参阅 微软对 Internet Explorer 早期版本的支持将于 2016 年 1 月 12 日结束的说明

+
+

您可以选择更先进的浏览器

+

推荐使用以下浏览器的最新版本。如果您的电脑已有以下浏览器的最新版本则直接使用该浏览器访问即可。

+ +
+ + \ No newline at end of file diff --git a/custom-ui/public/index.html b/custom-ui/public/index.html new file mode 100644 index 0000000..925455c --- /dev/null +++ b/custom-ui/public/index.html @@ -0,0 +1,208 @@ + + + + + + + + + <%= webpackConfig.name %> + + + + +
+
+
+
+
+
正在加载系统资源,请耐心等待
+
+
+ + diff --git a/custom-ui/public/robots.txt b/custom-ui/public/robots.txt new file mode 100644 index 0000000..77470cb --- /dev/null +++ b/custom-ui/public/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: / \ No newline at end of file diff --git a/custom-ui/src/App.vue b/custom-ui/src/App.vue new file mode 100644 index 0000000..29de49f --- /dev/null +++ b/custom-ui/src/App.vue @@ -0,0 +1,28 @@ + + + + diff --git a/custom-ui/src/api/business/survey.js b/custom-ui/src/api/business/survey.js new file mode 100644 index 0000000..bf50234 --- /dev/null +++ b/custom-ui/src/api/business/survey.js @@ -0,0 +1,53 @@ +import request from '@/utils/request' + +// 查询模版属性列表 +export function listBySurveyId(surveyId) { + return request({ + url: '/business/survey/listBySurveyId?surveyId=' + surveyId, + method: 'get', + }) +} + + +// 查询调查问卷管理列表 +export function listSurvey(query) { + return request({ + url: '/business/survey/list', + method: 'get', + params: query + }) +} + +// 查询调查问卷管理详细 +export function getSurvey(id) { + return request({ + url: '/business/survey/' + id, + method: 'get' + }) +} + +// 新增调查问卷管理 +export function addSurvey(data) { + return request({ + url: '/business/survey', + method: 'post', + data: data + }) +} + +// 修改调查问卷管理 +export function updateSurvey(data) { + return request({ + url: '/business/survey', + method: 'put', + data: data + }) +} + +// 删除调查问卷管理 +export function delSurvey(id) { + return request({ + url: '/business/survey/' + id, + method: 'delete' + }) +} diff --git a/custom-ui/src/api/business/template.js b/custom-ui/src/api/business/template.js new file mode 100644 index 0000000..4f7b0c1 --- /dev/null +++ b/custom-ui/src/api/business/template.js @@ -0,0 +1,54 @@ +import request from '@/utils/request' + +// 查询模版管理列表 +export function listTemplate(query) { + return request({ + url: '/business/template/list', + method: 'get', + params: query + }) +} + + +// 查询模版管理列表 +export function listAll(query) { + return request({ + url: '/business/template/listAll', + method: 'get', + params: query + }) +} + +// 查询模版管理详细 +export function getTemplate(id) { + return request({ + url: '/business/template/' + id, + method: 'get' + }) +} + +// 新增模版管理 +export function addTemplate(data) { + return request({ + url: '/business/template', + method: 'post', + data: data + }) +} + +// 修改模版管理 +export function updateTemplate(data) { + return request({ + url: '/business/template', + method: 'put', + data: data + }) +} + +// 删除模版管理 +export function delTemplate(id) { + return request({ + url: '/business/template/' + id, + method: 'delete' + }) +} diff --git a/custom-ui/src/api/business/templateProp.js b/custom-ui/src/api/business/templateProp.js new file mode 100644 index 0000000..6b237bf --- /dev/null +++ b/custom-ui/src/api/business/templateProp.js @@ -0,0 +1,45 @@ +import request from '@/utils/request' + + +// 查询模版管理列表 +export function listTemplateProp(query) { + return request({ + url: '/business/templateProp/list', + method: 'get', + params: query + }) +} + +// 查询模版属性详细 +export function getTemplateProp(id) { + return request({ + url: '/business/templateProp/' + id, + method: 'get' + }) +} + +// 新增模版属性 +export function addTemplateProp(data) { + return request({ + url: '/business/templateProp', + method: 'post', + data: data + }) +} + +// 修改模版属性 +export function updateTemplateProp(data) { + return request({ + url: '/business/templateProp', + method: 'put', + data: data + }) +} + +// 删除模版属性 +export function delTemplateProp(id) { + return request({ + url: '/business/templateProp/' + id, + method: 'delete' + }) +} diff --git a/custom-ui/src/api/business/templatePropValue.js b/custom-ui/src/api/business/templatePropValue.js new file mode 100644 index 0000000..bb6eda9 --- /dev/null +++ b/custom-ui/src/api/business/templatePropValue.js @@ -0,0 +1,61 @@ +import request from '@/utils/request' + +// 统计数据 +export function countGroup(surveyId) { + return request({ + url: '/business/templatePropValue/countGroup?surveyId=' + surveyId, + method: 'get', + }) +} + +// 查询模版属性值列表 +export function listTemplatePropValue(query) { + return request({ + url: '/business/templatePropValue/list', + method: 'get', + params: query + }) +} + +// 查询模版属性值详细 +export function getTemplatePropValue(id) { + return request({ + url: '/business/templatePropValue/' + id, + method: 'get' + }) +} + +// 新增模版属性值 +export function addTemplatePropValue(data) { + return request({ + url: '/business/templatePropValue', + method: 'post', + data: data + }) +} + +// 新增模版属性值 +export function addList(data) { + return request({ + url: '/business/templatePropValue/addList', + method: 'post', + data: data + }) +} + +// 修改模版属性值 +export function updateTemplatePropValue(data) { + return request({ + url: '/business/templatePropValue', + method: 'put', + data: data + }) +} + +// 删除模版属性值 +export function delTemplatePropValue(id) { + return request({ + url: '/business/templatePropValue/' + id, + method: 'delete' + }) +} diff --git a/custom-ui/src/api/login.js b/custom-ui/src/api/login.js new file mode 100644 index 0000000..4578559 --- /dev/null +++ b/custom-ui/src/api/login.js @@ -0,0 +1,70 @@ +import request from '@/utils/request' + +// 登录方法 +export function login(username, password, code, uuid) { + const data = { + username, + password, + code, + uuid + } + return request({ + url: '/login', + headers: { + isToken: false + }, + method: 'post', + data: data + }) +} + +// 注册方法 +export function register(data) { + return request({ + url: '/register', + headers: { + isToken: false + }, + method: 'post', + data: data + }) +} + +// 获取用户详细信息 +export function getInfo() { + return request({ + url: '/getInfo', + method: 'get' + }) +} + +// 退出方法 +export function logout() { + return request({ + url: '/logout', + method: 'post' + }) +} + +// 获取验证码 +export function getCodeImg() { + return request({ + url: '/captchaImage', + headers: { + isToken: false + }, + method: 'get', + timeout: 20000 + }) +} + +// 查询是否允许注册 +export function getConfigKey(configKey) { + return request({ + url: '/system/config/configKey/' + configKey, + headers: { + isToken: false + }, + method: 'get' + }) +} \ No newline at end of file diff --git a/custom-ui/src/api/menu.js b/custom-ui/src/api/menu.js new file mode 100644 index 0000000..faef101 --- /dev/null +++ b/custom-ui/src/api/menu.js @@ -0,0 +1,9 @@ +import request from '@/utils/request' + +// 获取路由 +export const getRouters = () => { + return request({ + url: '/getRouters', + method: 'get' + }) +} \ No newline at end of file diff --git a/custom-ui/src/api/monitor/cache.js b/custom-ui/src/api/monitor/cache.js new file mode 100644 index 0000000..72c5f6a --- /dev/null +++ b/custom-ui/src/api/monitor/cache.js @@ -0,0 +1,57 @@ +import request from '@/utils/request' + +// 查询缓存详细 +export function getCache() { + return request({ + url: '/monitor/cache', + method: 'get' + }) +} + +// 查询缓存名称列表 +export function listCacheName() { + return request({ + url: '/monitor/cache/getNames', + method: 'get' + }) +} + +// 查询缓存键名列表 +export function listCacheKey(cacheName) { + return request({ + url: '/monitor/cache/getKeys/' + cacheName, + method: 'get' + }) +} + +// 查询缓存内容 +export function getCacheValue(cacheName, cacheKey) { + return request({ + url: '/monitor/cache/getValue/' + cacheName + '/' + cacheKey, + method: 'get' + }) +} + +// 清理指定名称缓存 +export function clearCacheName(cacheName) { + return request({ + url: '/monitor/cache/clearCacheName/' + cacheName, + method: 'delete' + }) +} + +// 清理指定键名缓存 +export function clearCacheKey(cacheKey) { + return request({ + url: '/monitor/cache/clearCacheKey/' + cacheKey, + method: 'delete' + }) +} + +// 清理全部缓存 +export function clearCacheAll() { + return request({ + url: '/monitor/cache/clearCacheAll', + method: 'delete' + }) +} diff --git a/custom-ui/src/api/monitor/job.js b/custom-ui/src/api/monitor/job.js new file mode 100644 index 0000000..3815569 --- /dev/null +++ b/custom-ui/src/api/monitor/job.js @@ -0,0 +1,71 @@ +import request from '@/utils/request' + +// 查询定时任务调度列表 +export function listJob(query) { + return request({ + url: '/monitor/job/list', + method: 'get', + params: query + }) +} + +// 查询定时任务调度详细 +export function getJob(jobId) { + return request({ + url: '/monitor/job/' + jobId, + method: 'get' + }) +} + +// 新增定时任务调度 +export function addJob(data) { + return request({ + url: '/monitor/job', + method: 'post', + data: data + }) +} + +// 修改定时任务调度 +export function updateJob(data) { + return request({ + url: '/monitor/job', + method: 'put', + data: data + }) +} + +// 删除定时任务调度 +export function delJob(jobId) { + return request({ + url: '/monitor/job/' + jobId, + method: 'delete' + }) +} + +// 任务状态修改 +export function changeJobStatus(jobId, status) { + const data = { + jobId, + status + } + return request({ + url: '/monitor/job/changeStatus', + method: 'put', + data: data + }) +} + + +// 定时任务立即执行一次 +export function runJob(jobId, jobGroup) { + const data = { + jobId, + jobGroup + } + return request({ + url: '/monitor/job/run', + method: 'put', + data: data + }) +} \ No newline at end of file diff --git a/custom-ui/src/api/monitor/jobLog.js b/custom-ui/src/api/monitor/jobLog.js new file mode 100644 index 0000000..6e0be61 --- /dev/null +++ b/custom-ui/src/api/monitor/jobLog.js @@ -0,0 +1,26 @@ +import request from '@/utils/request' + +// 查询调度日志列表 +export function listJobLog(query) { + return request({ + url: '/monitor/jobLog/list', + method: 'get', + params: query + }) +} + +// 删除调度日志 +export function delJobLog(jobLogId) { + return request({ + url: '/monitor/jobLog/' + jobLogId, + method: 'delete' + }) +} + +// 清空调度日志 +export function cleanJobLog() { + return request({ + url: '/monitor/jobLog/clean', + method: 'delete' + }) +} diff --git a/custom-ui/src/api/monitor/logininfor.js b/custom-ui/src/api/monitor/logininfor.js new file mode 100644 index 0000000..4d112b7 --- /dev/null +++ b/custom-ui/src/api/monitor/logininfor.js @@ -0,0 +1,34 @@ +import request from '@/utils/request' + +// 查询登录日志列表 +export function list(query) { + return request({ + url: '/monitor/logininfor/list', + method: 'get', + params: query + }) +} + +// 删除登录日志 +export function delLogininfor(infoId) { + return request({ + url: '/monitor/logininfor/' + infoId, + method: 'delete' + }) +} + +// 解锁用户登录状态 +export function unlockLogininfor(userName) { + return request({ + url: '/monitor/logininfor/unlock/' + userName, + method: 'get' + }) +} + +// 清空登录日志 +export function cleanLogininfor() { + return request({ + url: '/monitor/logininfor/clean', + method: 'delete' + }) +} diff --git a/custom-ui/src/api/monitor/online.js b/custom-ui/src/api/monitor/online.js new file mode 100644 index 0000000..bd22137 --- /dev/null +++ b/custom-ui/src/api/monitor/online.js @@ -0,0 +1,18 @@ +import request from '@/utils/request' + +// 查询在线用户列表 +export function list(query) { + return request({ + url: '/monitor/online/list', + method: 'get', + params: query + }) +} + +// 强退用户 +export function forceLogout(tokenId) { + return request({ + url: '/monitor/online/' + tokenId, + method: 'delete' + }) +} diff --git a/custom-ui/src/api/monitor/operlog.js b/custom-ui/src/api/monitor/operlog.js new file mode 100644 index 0000000..a04bca8 --- /dev/null +++ b/custom-ui/src/api/monitor/operlog.js @@ -0,0 +1,26 @@ +import request from '@/utils/request' + +// 查询操作日志列表 +export function list(query) { + return request({ + url: '/monitor/operlog/list', + method: 'get', + params: query + }) +} + +// 删除操作日志 +export function delOperlog(operId) { + return request({ + url: '/monitor/operlog/' + operId, + method: 'delete' + }) +} + +// 清空操作日志 +export function cleanOperlog() { + return request({ + url: '/monitor/operlog/clean', + method: 'delete' + }) +} diff --git a/custom-ui/src/api/monitor/server.js b/custom-ui/src/api/monitor/server.js new file mode 100644 index 0000000..e1f9ca2 --- /dev/null +++ b/custom-ui/src/api/monitor/server.js @@ -0,0 +1,9 @@ +import request from '@/utils/request' + +// 获取服务信息 +export function getServer() { + return request({ + url: '/monitor/server', + method: 'get' + }) +} \ No newline at end of file diff --git a/custom-ui/src/api/system/config.js b/custom-ui/src/api/system/config.js new file mode 100644 index 0000000..a404d82 --- /dev/null +++ b/custom-ui/src/api/system/config.js @@ -0,0 +1,60 @@ +import request from '@/utils/request' + +// 查询参数列表 +export function listConfig(query) { + return request({ + url: '/system/config/list', + method: 'get', + params: query + }) +} + +// 查询参数详细 +export function getConfig(configId) { + return request({ + url: '/system/config/' + configId, + method: 'get' + }) +} + +// 根据参数键名查询参数值 +export function getConfigKey(configKey) { + return request({ + url: '/system/config/configKey/' + configKey, + method: 'get' + }) +} + +// 新增参数配置 +export function addConfig(data) { + return request({ + url: '/system/config', + method: 'post', + data: data + }) +} + +// 修改参数配置 +export function updateConfig(data) { + return request({ + url: '/system/config', + method: 'put', + data: data + }) +} + +// 删除参数配置 +export function delConfig(configId) { + return request({ + url: '/system/config/' + configId, + method: 'delete' + }) +} + +// 刷新参数缓存 +export function refreshCache() { + return request({ + url: '/system/config/refreshCache', + method: 'delete' + }) +} diff --git a/custom-ui/src/api/system/dept.js b/custom-ui/src/api/system/dept.js new file mode 100644 index 0000000..fc943cd --- /dev/null +++ b/custom-ui/src/api/system/dept.js @@ -0,0 +1,52 @@ +import request from '@/utils/request' + +// 查询部门列表 +export function listDept(query) { + return request({ + url: '/system/dept/list', + method: 'get', + params: query + }) +} + +// 查询部门列表(排除节点) +export function listDeptExcludeChild(deptId) { + return request({ + url: '/system/dept/list/exclude/' + deptId, + method: 'get' + }) +} + +// 查询部门详细 +export function getDept(deptId) { + return request({ + url: '/system/dept/' + deptId, + method: 'get' + }) +} + +// 新增部门 +export function addDept(data) { + return request({ + url: '/system/dept', + method: 'post', + data: data + }) +} + +// 修改部门 +export function updateDept(data) { + return request({ + url: '/system/dept', + method: 'put', + data: data + }) +} + +// 删除部门 +export function delDept(deptId) { + return request({ + url: '/system/dept/' + deptId, + method: 'delete' + }) +} \ No newline at end of file diff --git a/custom-ui/src/api/system/dict/data.js b/custom-ui/src/api/system/dict/data.js new file mode 100644 index 0000000..6c9eb79 --- /dev/null +++ b/custom-ui/src/api/system/dict/data.js @@ -0,0 +1,52 @@ +import request from '@/utils/request' + +// 查询字典数据列表 +export function listData(query) { + return request({ + url: '/system/dict/data/list', + method: 'get', + params: query + }) +} + +// 查询字典数据详细 +export function getData(dictCode) { + return request({ + url: '/system/dict/data/' + dictCode, + method: 'get' + }) +} + +// 根据字典类型查询字典数据信息 +export function getDicts(dictType) { + return request({ + url: '/system/dict/data/type/' + dictType, + method: 'get' + }) +} + +// 新增字典数据 +export function addData(data) { + return request({ + url: '/system/dict/data', + method: 'post', + data: data + }) +} + +// 修改字典数据 +export function updateData(data) { + return request({ + url: '/system/dict/data', + method: 'put', + data: data + }) +} + +// 删除字典数据 +export function delData(dictCode) { + return request({ + url: '/system/dict/data/' + dictCode, + method: 'delete' + }) +} diff --git a/custom-ui/src/api/system/dict/type.js b/custom-ui/src/api/system/dict/type.js new file mode 100644 index 0000000..a7a6e01 --- /dev/null +++ b/custom-ui/src/api/system/dict/type.js @@ -0,0 +1,60 @@ +import request from '@/utils/request' + +// 查询字典类型列表 +export function listType(query) { + return request({ + url: '/system/dict/type/list', + method: 'get', + params: query + }) +} + +// 查询字典类型详细 +export function getType(dictId) { + return request({ + url: '/system/dict/type/' + dictId, + method: 'get' + }) +} + +// 新增字典类型 +export function addType(data) { + return request({ + url: '/system/dict/type', + method: 'post', + data: data + }) +} + +// 修改字典类型 +export function updateType(data) { + return request({ + url: '/system/dict/type', + method: 'put', + data: data + }) +} + +// 删除字典类型 +export function delType(dictId) { + return request({ + url: '/system/dict/type/' + dictId, + method: 'delete' + }) +} + +// 刷新字典缓存 +export function refreshCache() { + return request({ + url: '/system/dict/type/refreshCache', + method: 'delete' + }) +} + +// 获取字典选择框列表 +export function optionselect() { + return request({ + url: '/system/dict/type/optionselect', + method: 'get' + }) +} \ No newline at end of file diff --git a/custom-ui/src/api/system/menu.js b/custom-ui/src/api/system/menu.js new file mode 100644 index 0000000..f6415c6 --- /dev/null +++ b/custom-ui/src/api/system/menu.js @@ -0,0 +1,60 @@ +import request from '@/utils/request' + +// 查询菜单列表 +export function listMenu(query) { + return request({ + url: '/system/menu/list', + method: 'get', + params: query + }) +} + +// 查询菜单详细 +export function getMenu(menuId) { + return request({ + url: '/system/menu/' + menuId, + method: 'get' + }) +} + +// 查询菜单下拉树结构 +export function treeselect() { + return request({ + url: '/system/menu/treeselect', + method: 'get' + }) +} + +// 根据角色ID查询菜单下拉树结构 +export function roleMenuTreeselect(roleId) { + return request({ + url: '/system/menu/roleMenuTreeselect/' + roleId, + method: 'get' + }) +} + +// 新增菜单 +export function addMenu(data) { + return request({ + url: '/system/menu', + method: 'post', + data: data + }) +} + +// 修改菜单 +export function updateMenu(data) { + return request({ + url: '/system/menu', + method: 'put', + data: data + }) +} + +// 删除菜单 +export function delMenu(menuId) { + return request({ + url: '/system/menu/' + menuId, + method: 'delete' + }) +} \ No newline at end of file diff --git a/custom-ui/src/api/system/notice.js b/custom-ui/src/api/system/notice.js new file mode 100644 index 0000000..c274ea5 --- /dev/null +++ b/custom-ui/src/api/system/notice.js @@ -0,0 +1,44 @@ +import request from '@/utils/request' + +// 查询公告列表 +export function listNotice(query) { + return request({ + url: '/system/notice/list', + method: 'get', + params: query + }) +} + +// 查询公告详细 +export function getNotice(noticeId) { + return request({ + url: '/system/notice/' + noticeId, + method: 'get' + }) +} + +// 新增公告 +export function addNotice(data) { + return request({ + url: '/system/notice', + method: 'post', + data: data + }) +} + +// 修改公告 +export function updateNotice(data) { + return request({ + url: '/system/notice', + method: 'put', + data: data + }) +} + +// 删除公告 +export function delNotice(noticeId) { + return request({ + url: '/system/notice/' + noticeId, + method: 'delete' + }) +} \ No newline at end of file diff --git a/custom-ui/src/api/system/post.js b/custom-ui/src/api/system/post.js new file mode 100644 index 0000000..1a8e9ca --- /dev/null +++ b/custom-ui/src/api/system/post.js @@ -0,0 +1,44 @@ +import request from '@/utils/request' + +// 查询岗位列表 +export function listPost(query) { + return request({ + url: '/system/post/list', + method: 'get', + params: query + }) +} + +// 查询岗位详细 +export function getPost(postId) { + return request({ + url: '/system/post/' + postId, + method: 'get' + }) +} + +// 新增岗位 +export function addPost(data) { + return request({ + url: '/system/post', + method: 'post', + data: data + }) +} + +// 修改岗位 +export function updatePost(data) { + return request({ + url: '/system/post', + method: 'put', + data: data + }) +} + +// 删除岗位 +export function delPost(postId) { + return request({ + url: '/system/post/' + postId, + method: 'delete' + }) +} diff --git a/custom-ui/src/api/system/role.js b/custom-ui/src/api/system/role.js new file mode 100644 index 0000000..f13e6f4 --- /dev/null +++ b/custom-ui/src/api/system/role.js @@ -0,0 +1,119 @@ +import request from '@/utils/request' + +// 查询角色列表 +export function listRole(query) { + return request({ + url: '/system/role/list', + method: 'get', + params: query + }) +} + +// 查询角色详细 +export function getRole(roleId) { + return request({ + url: '/system/role/' + roleId, + method: 'get' + }) +} + +// 新增角色 +export function addRole(data) { + return request({ + url: '/system/role', + method: 'post', + data: data + }) +} + +// 修改角色 +export function updateRole(data) { + return request({ + url: '/system/role', + method: 'put', + data: data + }) +} + +// 角色数据权限 +export function dataScope(data) { + return request({ + url: '/system/role/dataScope', + method: 'put', + data: data + }) +} + +// 角色状态修改 +export function changeRoleStatus(roleId, status) { + const data = { + roleId, + status + } + return request({ + url: '/system/role/changeStatus', + method: 'put', + data: data + }) +} + +// 删除角色 +export function delRole(roleId) { + return request({ + url: '/system/role/' + roleId, + method: 'delete' + }) +} + +// 查询角色已授权用户列表 +export function allocatedUserList(query) { + return request({ + url: '/system/role/authUser/allocatedList', + method: 'get', + params: query + }) +} + +// 查询角色未授权用户列表 +export function unallocatedUserList(query) { + return request({ + url: '/system/role/authUser/unallocatedList', + method: 'get', + params: query + }) +} + +// 取消用户授权角色 +export function authUserCancel(data) { + return request({ + url: '/system/role/authUser/cancel', + method: 'put', + data: data + }) +} + +// 批量取消用户授权角色 +export function authUserCancelAll(data) { + return request({ + url: '/system/role/authUser/cancelAll', + method: 'put', + params: data + }) +} + +// 授权用户选择 +export function authUserSelectAll(data) { + return request({ + url: '/system/role/authUser/selectAll', + method: 'put', + params: data + }) +} + +// 根据角色ID查询部门树结构 +export function deptTreeSelect(roleId) { + return request({ + url: '/system/role/deptTree/' + roleId, + method: 'get' + }) +} diff --git a/custom-ui/src/api/system/user.js b/custom-ui/src/api/system/user.js new file mode 100644 index 0000000..f2f76ef --- /dev/null +++ b/custom-ui/src/api/system/user.js @@ -0,0 +1,135 @@ +import request from '@/utils/request' +import { parseStrEmpty } from "@/utils/ruoyi"; + +// 查询用户列表 +export function listUser(query) { + return request({ + url: '/system/user/list', + method: 'get', + params: query + }) +} + +// 查询用户详细 +export function getUser(userId) { + return request({ + url: '/system/user/' + parseStrEmpty(userId), + method: 'get' + }) +} + +// 新增用户 +export function addUser(data) { + return request({ + url: '/system/user', + method: 'post', + data: data + }) +} + +// 修改用户 +export function updateUser(data) { + return request({ + url: '/system/user', + method: 'put', + data: data + }) +} + +// 删除用户 +export function delUser(userId) { + return request({ + url: '/system/user/' + userId, + method: 'delete' + }) +} + +// 用户密码重置 +export function resetUserPwd(userId, password) { + const data = { + userId, + password + } + return request({ + url: '/system/user/resetPwd', + method: 'put', + data: data + }) +} + +// 用户状态修改 +export function changeUserStatus(userId, status) { + const data = { + userId, + status + } + return request({ + url: '/system/user/changeStatus', + method: 'put', + data: data + }) +} + +// 查询用户个人信息 +export function getUserProfile() { + return request({ + url: '/system/user/profile', + method: 'get' + }) +} + +// 修改用户个人信息 +export function updateUserProfile(data) { + return request({ + url: '/system/user/profile', + method: 'put', + data: data + }) +} + +// 用户密码重置 +export function updateUserPwd(oldPassword, newPassword) { + const data = { + oldPassword, + newPassword + } + return request({ + url: '/system/user/profile/updatePwd', + method: 'put', + params: data + }) +} + +// 用户头像上传 +export function uploadAvatar(data) { + return request({ + url: '/system/user/profile/avatar', + method: 'post', + data: data + }) +} + +// 查询授权角色 +export function getAuthRole(userId) { + return request({ + url: '/system/user/authRole/' + userId, + method: 'get' + }) +} + +// 保存授权角色 +export function updateAuthRole(data) { + return request({ + url: '/system/user/authRole', + method: 'put', + params: data + }) +} + +// 查询部门下拉树结构 +export function deptTreeSelect() { + return request({ + url: '/system/user/deptTree', + method: 'get' + }) +} diff --git a/custom-ui/src/api/tool/gen.js b/custom-ui/src/api/tool/gen.js new file mode 100644 index 0000000..4506927 --- /dev/null +++ b/custom-ui/src/api/tool/gen.js @@ -0,0 +1,76 @@ +import request from '@/utils/request' + +// 查询生成表数据 +export function listTable(query) { + return request({ + url: '/tool/gen/list', + method: 'get', + params: query + }) +} +// 查询db数据库列表 +export function listDbTable(query) { + return request({ + url: '/tool/gen/db/list', + method: 'get', + params: query + }) +} + +// 查询表详细信息 +export function getGenTable(tableId) { + return request({ + url: '/tool/gen/' + tableId, + method: 'get' + }) +} + +// 修改代码生成信息 +export function updateGenTable(data) { + return request({ + url: '/tool/gen', + method: 'put', + data: data + }) +} + +// 导入表 +export function importTable(data) { + return request({ + url: '/tool/gen/importTable', + method: 'post', + params: data + }) +} + +// 预览生成代码 +export function previewTable(tableId) { + return request({ + url: '/tool/gen/preview/' + tableId, + method: 'get' + }) +} + +// 删除表数据 +export function delTable(tableId) { + return request({ + url: '/tool/gen/' + tableId, + method: 'delete' + }) +} + +// 生成代码(自定义路径) +export function genCode(tableName) { + return request({ + url: '/tool/gen/genCode/' + tableName, + method: 'get' + }) +} + +// 同步数据库 +export function synchDb(tableName) { + return request({ + url: '/tool/gen/synchDb/' + tableName, + method: 'get' + }) +} diff --git a/custom-ui/src/assets/401_images/401.gif b/custom-ui/src/assets/401_images/401.gif new file mode 100644 index 0000000000000000000000000000000000000000..cd6e0d9433421b3f29d0ec0c40f755e354728000 GIT binary patch literal 164227 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⋘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 GY5fOuZZib{ literal 0 HcmV?d00001 diff --git a/custom-ui/src/assets/404_images/404.png b/custom-ui/src/assets/404_images/404.png new file mode 100644 index 0000000000000000000000000000000000000000..3d8e2305cc973ad2121403aee4bf08728f76c461 GIT binary patch literal 98071 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 literal 0 HcmV?d00001 diff --git a/custom-ui/src/assets/404_images/404_cloud.png b/custom-ui/src/assets/404_images/404_cloud.png new file mode 100644 index 0000000000000000000000000000000000000000..c6281d09013e0a2c5f8e699a0a6038d9480291e5 GIT binary patch literal 4766 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 literal 0 HcmV?d00001 diff --git a/custom-ui/src/assets/icons/index.js b/custom-ui/src/assets/icons/index.js new file mode 100644 index 0000000..2c6b309 --- /dev/null +++ b/custom-ui/src/assets/icons/index.js @@ -0,0 +1,9 @@ +import Vue from 'vue' +import SvgIcon from '@/components/SvgIcon'// svg component + +// register globally +Vue.component('svg-icon', SvgIcon) + +const req = require.context('./svg', false, /\.svg$/) +const requireAll = requireContext => requireContext.keys().map(requireContext) +requireAll(req) diff --git a/custom-ui/src/assets/icons/svg/404.svg b/custom-ui/src/assets/icons/svg/404.svg new file mode 100644 index 0000000..6df5019 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/404.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/bug.svg b/custom-ui/src/assets/icons/svg/bug.svg new file mode 100644 index 0000000..05a150d --- /dev/null +++ b/custom-ui/src/assets/icons/svg/bug.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/build.svg b/custom-ui/src/assets/icons/svg/build.svg new file mode 100644 index 0000000..97c4688 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/build.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/button.svg b/custom-ui/src/assets/icons/svg/button.svg new file mode 100644 index 0000000..904fddc --- /dev/null +++ b/custom-ui/src/assets/icons/svg/button.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/cascader.svg b/custom-ui/src/assets/icons/svg/cascader.svg new file mode 100644 index 0000000..e256024 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/cascader.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/chart.svg b/custom-ui/src/assets/icons/svg/chart.svg new file mode 100644 index 0000000..27728fb --- /dev/null +++ b/custom-ui/src/assets/icons/svg/chart.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/checkbox.svg b/custom-ui/src/assets/icons/svg/checkbox.svg new file mode 100644 index 0000000..013fd3a --- /dev/null +++ b/custom-ui/src/assets/icons/svg/checkbox.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/clipboard.svg b/custom-ui/src/assets/icons/svg/clipboard.svg new file mode 100644 index 0000000..90923ff --- /dev/null +++ b/custom-ui/src/assets/icons/svg/clipboard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/code.svg b/custom-ui/src/assets/icons/svg/code.svg new file mode 100644 index 0000000..5f9c5ab --- /dev/null +++ b/custom-ui/src/assets/icons/svg/code.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/color.svg b/custom-ui/src/assets/icons/svg/color.svg new file mode 100644 index 0000000..44a81aa --- /dev/null +++ b/custom-ui/src/assets/icons/svg/color.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/component.svg b/custom-ui/src/assets/icons/svg/component.svg new file mode 100644 index 0000000..29c3458 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/component.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/dashboard.svg b/custom-ui/src/assets/icons/svg/dashboard.svg new file mode 100644 index 0000000..5317d37 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/dashboard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/date-range.svg b/custom-ui/src/assets/icons/svg/date-range.svg new file mode 100644 index 0000000..fda571e --- /dev/null +++ b/custom-ui/src/assets/icons/svg/date-range.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/date.svg b/custom-ui/src/assets/icons/svg/date.svg new file mode 100644 index 0000000..52dc73e --- /dev/null +++ b/custom-ui/src/assets/icons/svg/date.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/dict.svg b/custom-ui/src/assets/icons/svg/dict.svg new file mode 100644 index 0000000..4849377 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/dict.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/documentation.svg b/custom-ui/src/assets/icons/svg/documentation.svg new file mode 100644 index 0000000..7043122 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/documentation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/download.svg b/custom-ui/src/assets/icons/svg/download.svg new file mode 100644 index 0000000..c896951 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/download.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/drag.svg b/custom-ui/src/assets/icons/svg/drag.svg new file mode 100644 index 0000000..4185d3c --- /dev/null +++ b/custom-ui/src/assets/icons/svg/drag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/druid.svg b/custom-ui/src/assets/icons/svg/druid.svg new file mode 100644 index 0000000..a2b4b4e --- /dev/null +++ b/custom-ui/src/assets/icons/svg/druid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/edit.svg b/custom-ui/src/assets/icons/svg/edit.svg new file mode 100644 index 0000000..d26101f --- /dev/null +++ b/custom-ui/src/assets/icons/svg/edit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/education.svg b/custom-ui/src/assets/icons/svg/education.svg new file mode 100644 index 0000000..7bfb01d --- /dev/null +++ b/custom-ui/src/assets/icons/svg/education.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/email.svg b/custom-ui/src/assets/icons/svg/email.svg new file mode 100644 index 0000000..74d25e2 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/email.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/example.svg b/custom-ui/src/assets/icons/svg/example.svg new file mode 100644 index 0000000..46f42b5 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/example.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/excel.svg b/custom-ui/src/assets/icons/svg/excel.svg new file mode 100644 index 0000000..74d97b8 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/excel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/exit-fullscreen.svg b/custom-ui/src/assets/icons/svg/exit-fullscreen.svg new file mode 100644 index 0000000..485c128 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/exit-fullscreen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/eye-open.svg b/custom-ui/src/assets/icons/svg/eye-open.svg new file mode 100644 index 0000000..88dcc98 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/eye-open.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/eye.svg b/custom-ui/src/assets/icons/svg/eye.svg new file mode 100644 index 0000000..16ed2d8 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/eye.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/form.svg b/custom-ui/src/assets/icons/svg/form.svg new file mode 100644 index 0000000..dcbaa18 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/form.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/fullscreen.svg b/custom-ui/src/assets/icons/svg/fullscreen.svg new file mode 100644 index 0000000..0e86b6f --- /dev/null +++ b/custom-ui/src/assets/icons/svg/fullscreen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/github.svg b/custom-ui/src/assets/icons/svg/github.svg new file mode 100644 index 0000000..db0a0d4 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/github.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/guide.svg b/custom-ui/src/assets/icons/svg/guide.svg new file mode 100644 index 0000000..b271001 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/guide.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/icon.svg b/custom-ui/src/assets/icons/svg/icon.svg new file mode 100644 index 0000000..82be8ee --- /dev/null +++ b/custom-ui/src/assets/icons/svg/icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/input.svg b/custom-ui/src/assets/icons/svg/input.svg new file mode 100644 index 0000000..ab91381 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/input.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/international.svg b/custom-ui/src/assets/icons/svg/international.svg new file mode 100644 index 0000000..e9b56ee --- /dev/null +++ b/custom-ui/src/assets/icons/svg/international.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/job.svg b/custom-ui/src/assets/icons/svg/job.svg new file mode 100644 index 0000000..2a93a25 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/job.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/language.svg b/custom-ui/src/assets/icons/svg/language.svg new file mode 100644 index 0000000..0082b57 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/language.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/link.svg b/custom-ui/src/assets/icons/svg/link.svg new file mode 100644 index 0000000..48197ba --- /dev/null +++ b/custom-ui/src/assets/icons/svg/link.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/list.svg b/custom-ui/src/assets/icons/svg/list.svg new file mode 100644 index 0000000..20259ed --- /dev/null +++ b/custom-ui/src/assets/icons/svg/list.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/lock.svg b/custom-ui/src/assets/icons/svg/lock.svg new file mode 100644 index 0000000..74fee54 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/lock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/log.svg b/custom-ui/src/assets/icons/svg/log.svg new file mode 100644 index 0000000..d879d33 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/log.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/logininfor.svg b/custom-ui/src/assets/icons/svg/logininfor.svg new file mode 100644 index 0000000..267f844 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/logininfor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/message.svg b/custom-ui/src/assets/icons/svg/message.svg new file mode 100644 index 0000000..14ca817 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/message.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/money.svg b/custom-ui/src/assets/icons/svg/money.svg new file mode 100644 index 0000000..c1580de --- /dev/null +++ b/custom-ui/src/assets/icons/svg/money.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/monitor.svg b/custom-ui/src/assets/icons/svg/monitor.svg new file mode 100644 index 0000000..bc308cb --- /dev/null +++ b/custom-ui/src/assets/icons/svg/monitor.svg @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/nested.svg b/custom-ui/src/assets/icons/svg/nested.svg new file mode 100644 index 0000000..06713a8 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/nested.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/number.svg b/custom-ui/src/assets/icons/svg/number.svg new file mode 100644 index 0000000..ad5ce9a --- /dev/null +++ b/custom-ui/src/assets/icons/svg/number.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/online.svg b/custom-ui/src/assets/icons/svg/online.svg new file mode 100644 index 0000000..330a202 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/online.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/password.svg b/custom-ui/src/assets/icons/svg/password.svg new file mode 100644 index 0000000..6c64def --- /dev/null +++ b/custom-ui/src/assets/icons/svg/password.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/pdf.svg b/custom-ui/src/assets/icons/svg/pdf.svg new file mode 100644 index 0000000..957aa0c --- /dev/null +++ b/custom-ui/src/assets/icons/svg/pdf.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/people.svg b/custom-ui/src/assets/icons/svg/people.svg new file mode 100644 index 0000000..2bd54ae --- /dev/null +++ b/custom-ui/src/assets/icons/svg/people.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/peoples.svg b/custom-ui/src/assets/icons/svg/peoples.svg new file mode 100644 index 0000000..aab852e --- /dev/null +++ b/custom-ui/src/assets/icons/svg/peoples.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/phone.svg b/custom-ui/src/assets/icons/svg/phone.svg new file mode 100644 index 0000000..ab8e8c4 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/phone.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/post.svg b/custom-ui/src/assets/icons/svg/post.svg new file mode 100644 index 0000000..2922c61 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/post.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/qq.svg b/custom-ui/src/assets/icons/svg/qq.svg new file mode 100644 index 0000000..ee13d4e --- /dev/null +++ b/custom-ui/src/assets/icons/svg/qq.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/question.svg b/custom-ui/src/assets/icons/svg/question.svg new file mode 100644 index 0000000..cf75bd4 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/question.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/radio.svg b/custom-ui/src/assets/icons/svg/radio.svg new file mode 100644 index 0000000..0cde345 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/radio.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/rate.svg b/custom-ui/src/assets/icons/svg/rate.svg new file mode 100644 index 0000000..aa3b14d --- /dev/null +++ b/custom-ui/src/assets/icons/svg/rate.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/redis-list.svg b/custom-ui/src/assets/icons/svg/redis-list.svg new file mode 100644 index 0000000..98a15b2 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/redis-list.svg @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/redis.svg b/custom-ui/src/assets/icons/svg/redis.svg new file mode 100644 index 0000000..2f1d62d --- /dev/null +++ b/custom-ui/src/assets/icons/svg/redis.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/row.svg b/custom-ui/src/assets/icons/svg/row.svg new file mode 100644 index 0000000..0780992 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/row.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/search.svg b/custom-ui/src/assets/icons/svg/search.svg new file mode 100644 index 0000000..84233dd --- /dev/null +++ b/custom-ui/src/assets/icons/svg/search.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/select.svg b/custom-ui/src/assets/icons/svg/select.svg new file mode 100644 index 0000000..d628382 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/select.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/server.svg b/custom-ui/src/assets/icons/svg/server.svg new file mode 100644 index 0000000..eb287e3 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/server.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/shopping.svg b/custom-ui/src/assets/icons/svg/shopping.svg new file mode 100644 index 0000000..87513e7 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/shopping.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/size.svg b/custom-ui/src/assets/icons/svg/size.svg new file mode 100644 index 0000000..ddb25b8 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/size.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/skill.svg b/custom-ui/src/assets/icons/svg/skill.svg new file mode 100644 index 0000000..a3b7312 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/skill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/slider.svg b/custom-ui/src/assets/icons/svg/slider.svg new file mode 100644 index 0000000..fbe4f39 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/slider.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/star.svg b/custom-ui/src/assets/icons/svg/star.svg new file mode 100644 index 0000000..6cf86e6 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/star.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/swagger.svg b/custom-ui/src/assets/icons/svg/swagger.svg new file mode 100644 index 0000000..05d4e7b --- /dev/null +++ b/custom-ui/src/assets/icons/svg/swagger.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/switch.svg b/custom-ui/src/assets/icons/svg/switch.svg new file mode 100644 index 0000000..0ba61e3 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/switch.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/system.svg b/custom-ui/src/assets/icons/svg/system.svg new file mode 100644 index 0000000..5992593 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/system.svg @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/tab.svg b/custom-ui/src/assets/icons/svg/tab.svg new file mode 100644 index 0000000..b4b48e4 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/tab.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/table.svg b/custom-ui/src/assets/icons/svg/table.svg new file mode 100644 index 0000000..0e3dc9d --- /dev/null +++ b/custom-ui/src/assets/icons/svg/table.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/textarea.svg b/custom-ui/src/assets/icons/svg/textarea.svg new file mode 100644 index 0000000..2709f29 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/textarea.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/theme.svg b/custom-ui/src/assets/icons/svg/theme.svg new file mode 100644 index 0000000..5982a2f --- /dev/null +++ b/custom-ui/src/assets/icons/svg/theme.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/time-range.svg b/custom-ui/src/assets/icons/svg/time-range.svg new file mode 100644 index 0000000..13c1202 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/time-range.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/time.svg b/custom-ui/src/assets/icons/svg/time.svg new file mode 100644 index 0000000..b376e32 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/time.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/tool.svg b/custom-ui/src/assets/icons/svg/tool.svg new file mode 100644 index 0000000..48e0e35 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/tool.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/tree-table.svg b/custom-ui/src/assets/icons/svg/tree-table.svg new file mode 100644 index 0000000..8aafdb8 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/tree-table.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/tree.svg b/custom-ui/src/assets/icons/svg/tree.svg new file mode 100644 index 0000000..dd4b7dd --- /dev/null +++ b/custom-ui/src/assets/icons/svg/tree.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/upload.svg b/custom-ui/src/assets/icons/svg/upload.svg new file mode 100644 index 0000000..bae49c0 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/upload.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/user.svg b/custom-ui/src/assets/icons/svg/user.svg new file mode 100644 index 0000000..0ba0716 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/user.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/validCode.svg b/custom-ui/src/assets/icons/svg/validCode.svg new file mode 100644 index 0000000..cfb1021 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/validCode.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/wechat.svg b/custom-ui/src/assets/icons/svg/wechat.svg new file mode 100644 index 0000000..c586e55 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/wechat.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svg/zip.svg b/custom-ui/src/assets/icons/svg/zip.svg new file mode 100644 index 0000000..f806fc4 --- /dev/null +++ b/custom-ui/src/assets/icons/svg/zip.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/custom-ui/src/assets/icons/svgo.yml b/custom-ui/src/assets/icons/svgo.yml new file mode 100644 index 0000000..d11906a --- /dev/null +++ b/custom-ui/src/assets/icons/svgo.yml @@ -0,0 +1,22 @@ +# replace default config + +# multipass: true +# full: true + +plugins: + + # - name + # + # or: + # - name: false + # - name: true + # + # or: + # - name: + # param1: 1 + # param2: 2 + +- removeAttrs: + attrs: + - 'fill' + - 'fill-rule' diff --git a/custom-ui/src/assets/images/dark.svg b/custom-ui/src/assets/images/dark.svg new file mode 100644 index 0000000..f646bd7 --- /dev/null +++ b/custom-ui/src/assets/images/dark.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/custom-ui/src/assets/images/light.svg b/custom-ui/src/assets/images/light.svg new file mode 100644 index 0000000..ab7cc08 --- /dev/null +++ b/custom-ui/src/assets/images/light.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/custom-ui/src/assets/images/login-background.jpg b/custom-ui/src/assets/images/login-background.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8a89eb8291d5cb7d9f37ec4f275deab911c9e28e GIT binary patch literal 521275 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¥}>uauIoY!`8n(7niSl_m2d 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

LZs5vs<4*dn)6_orH;Y;`bzi*q=#N#x6 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

8A%Us3k< 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𝔫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

&!CIz1Ns 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⩛TtXwH2N8q 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

Wf@+FD?DGvA4he?g#aN51zy(O$Xy! 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

Acrih5KDW9ugPSk3y-@mXy^-HnY=Jp77llly?k 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 z≺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 literal 0 HcmV?d00001 diff --git a/custom-ui/src/assets/logo/logo.png b/custom-ui/src/assets/logo/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e26376026420542212ed58d90d0ed34f554fa4ae GIT binary patch literal 5663 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 div + > .el-submenu + > .el-submenu__title + .el-submenu__icon-arrow { + display: none; +} \ No newline at end of file diff --git a/custom-ui/src/assets/styles/element-variables.scss b/custom-ui/src/assets/styles/element-variables.scss new file mode 100644 index 0000000..1615ff2 --- /dev/null +++ b/custom-ui/src/assets/styles/element-variables.scss @@ -0,0 +1,31 @@ +/** +* I think element-ui's default theme color is too light for long-term use. +* So I modified the default color and you can modify it to your liking. +**/ + +/* theme color */ +$--color-primary: #1890ff; +$--color-success: #13ce66; +$--color-warning: #ffba00; +$--color-danger: #ff4949; +// $--color-info: #1E1E1E; + +$--button-font-weight: 400; + +// $--color-text-regular: #1f2d3d; + +$--border-color-light: #dfe4ed; +$--border-color-lighter: #e6ebf5; + +$--table-border: 1px solid #dfe6ec; + +/* icon font path, required */ +$--font-path: '~element-ui/lib/theme-chalk/fonts'; + +@import "~element-ui/packages/theme-chalk/src/index"; + +// the :export directive is the magic sauce for webpack +// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass +:export { + theme: $--color-primary; +} diff --git a/custom-ui/src/assets/styles/index.scss b/custom-ui/src/assets/styles/index.scss new file mode 100644 index 0000000..96095ef --- /dev/null +++ b/custom-ui/src/assets/styles/index.scss @@ -0,0 +1,191 @@ +@import './variables.scss'; +@import './mixin.scss'; +@import './transition.scss'; +@import './element-ui.scss'; +@import './sidebar.scss'; +@import './btn.scss'; + +body { + height: 100%; + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + text-rendering: optimizeLegibility; + font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif; +} + +label { + font-weight: 700; +} + +html { + height: 100%; + box-sizing: border-box; +} + +#app { + height: 100%; +} + +*, +*:before, +*:after { + box-sizing: inherit; +} + +.no-padding { + padding: 0px !important; +} + +.padding-content { + padding: 4px 0; +} + +a:focus, +a:active { + outline: none; +} + +a, +a:focus, +a:hover { + cursor: pointer; + color: inherit; + text-decoration: none; +} + +div:focus { + outline: none; +} + +.fr { + float: right; +} + +.fl { + float: left; +} + +.pr-5 { + padding-right: 5px; +} + +.pl-5 { + padding-left: 5px; +} + +.block { + display: block; +} + +.pointer { + cursor: pointer; +} + +.inlineBlock { + display: block; +} + +.clearfix { + &:after { + visibility: hidden; + display: block; + font-size: 0; + content: " "; + clear: both; + height: 0; + } +} + +aside { + background: #eef1f6; + padding: 8px 24px; + margin-bottom: 20px; + border-radius: 2px; + display: block; + line-height: 32px; + font-size: 16px; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; + color: #2c3e50; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + + a { + color: #337ab7; + cursor: pointer; + + &:hover { + color: rgb(32, 160, 255); + } + } +} + +//main-container全局样式 +.app-container { + padding: 20px; +} + +.components-container { + margin: 30px 50px; + position: relative; +} + +.pagination-container { + margin-top: 30px; +} + +.text-center { + text-align: center +} + +.sub-navbar { + height: 50px; + line-height: 50px; + position: relative; + width: 100%; + text-align: right; + padding-right: 20px; + transition: 600ms ease position; + background: linear-gradient(90deg, rgba(32, 182, 249, 1) 0%, rgba(32, 182, 249, 1) 0%, rgba(33, 120, 241, 1) 100%, rgba(33, 120, 241, 1) 100%); + + .subtitle { + font-size: 20px; + color: #fff; + } + + &.draft { + background: #d0d0d0; + } + + &.deleted { + background: #d0d0d0; + } +} + +.link-type, +.link-type:focus { + color: #337ab7; + cursor: pointer; + + &:hover { + color: rgb(32, 160, 255); + } +} + +.filter-container { + padding-bottom: 10px; + + .filter-item { + display: inline-block; + vertical-align: middle; + margin-bottom: 10px; + } +} + +//refine vue-multiselect plugin +.multiselect { + line-height: 16px; +} + +.multiselect--active { + z-index: 1000 !important; +} diff --git a/custom-ui/src/assets/styles/mixin.scss b/custom-ui/src/assets/styles/mixin.scss new file mode 100644 index 0000000..06fa061 --- /dev/null +++ b/custom-ui/src/assets/styles/mixin.scss @@ -0,0 +1,66 @@ +@mixin clearfix { + &:after { + content: ""; + display: table; + clear: both; + } +} + +@mixin scrollBar { + &::-webkit-scrollbar-track-piece { + background: #d3dce6; + } + + &::-webkit-scrollbar { + width: 6px; + } + + &::-webkit-scrollbar-thumb { + background: #99a9bf; + border-radius: 20px; + } +} + +@mixin relative { + position: relative; + width: 100%; + height: 100%; +} + +@mixin pct($pct) { + width: #{$pct}; + position: relative; + margin: 0 auto; +} + +@mixin triangle($width, $height, $color, $direction) { + $width: $width/2; + $color-border-style: $height solid $color; + $transparent-border-style: $width solid transparent; + height: 0; + width: 0; + + @if $direction==up { + border-bottom: $color-border-style; + border-left: $transparent-border-style; + border-right: $transparent-border-style; + } + + @else if $direction==right { + border-left: $color-border-style; + border-top: $transparent-border-style; + border-bottom: $transparent-border-style; + } + + @else if $direction==down { + border-top: $color-border-style; + border-left: $transparent-border-style; + border-right: $transparent-border-style; + } + + @else if $direction==left { + border-right: $color-border-style; + border-top: $transparent-border-style; + border-bottom: $transparent-border-style; + } +} diff --git a/custom-ui/src/assets/styles/ruoyi.scss b/custom-ui/src/assets/styles/ruoyi.scss new file mode 100644 index 0000000..db8c29b --- /dev/null +++ b/custom-ui/src/assets/styles/ruoyi.scss @@ -0,0 +1,277 @@ + /** + * 通用css样式布局处理 + * Copyright (c) 2019 ruoyi + */ + + /** 基础通用 **/ +.pt5 { + padding-top: 5px; +} +.pr5 { + padding-right: 5px; +} +.pb5 { + padding-bottom: 5px; +} +.mt5 { + margin-top: 5px; +} +.mr5 { + margin-right: 5px; +} +.mb5 { + margin-bottom: 5px; +} +.mb8 { + margin-bottom: 8px; +} +.ml5 { + margin-left: 5px; +} +.mt10 { + margin-top: 10px; +} +.mr10 { + margin-right: 10px; +} +.mb10 { + margin-bottom: 10px; +} +.ml10 { + margin-left: 10px; +} +.mt20 { + margin-top: 20px; +} +.mr20 { + margin-right: 20px; +} +.mb20 { + margin-bottom: 20px; +} +.ml20 { + margin-left: 20px; +} + +.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 { + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit; +} + +.el-message-box__status + .el-message-box__message{ + word-break: break-word; +} + +.el-dialog:not(.is-fullscreen) { + margin-top: 6vh !important; +} + +.el-dialog__wrapper.scrollbar .el-dialog .el-dialog__body { + overflow: auto; + overflow-x: hidden; + max-height: 70vh; + padding: 10px 20px 0; +} + +.el-table { + .el-table__header-wrapper, .el-table__fixed-header-wrapper { + th { + word-break: break-word; + background-color: #f8f8f9; + color: #515a6e; + height: 40px; + font-size: 13px; + } + } + .el-table__body-wrapper { + .el-button [class*="el-icon-"] + span { + margin-left: 1px; + } + } +} + +/** 表单布局 **/ +.form-header { + font-size:15px; + color:#6379bb; + border-bottom:1px solid #ddd; + margin:8px 10px 25px 10px; + padding-bottom:5px +} + +/** 表格布局 **/ +.pagination-container { + position: relative; + height: 25px; + margin-bottom: 10px; + margin-top: 15px; + padding: 10px 20px !important; +} + +/* tree border */ +.tree-border { + margin-top: 5px; + border: 1px solid #e5e6e7; + background: #FFFFFF none; + border-radius:4px; +} + +.pagination-container .el-pagination { + right: 0; + position: absolute; +} + +@media ( max-width : 768px) { + .pagination-container .el-pagination > .el-pagination__jump { + display: none !important; + } + .pagination-container .el-pagination > .el-pagination__sizes { + display: none !important; + } +} + +.el-table .fixed-width .el-button--mini { + padding-left: 0; + padding-right: 0; + width: inherit; +} + +/** 表格更多操作下拉样式 */ +.el-table .el-dropdown-link,.el-table .el-dropdown-selfdefine { + cursor: pointer; + margin-left: 5px; +} + +.el-table .el-dropdown, .el-icon-arrow-down { + font-size: 12px; +} + +.el-tree-node__content > .el-checkbox { + margin-right: 8px; +} + +.list-group-striped > .list-group-item { + border-left: 0; + border-right: 0; + border-radius: 0; + padding-left: 0; + padding-right: 0; +} + +.list-group { + padding-left: 0px; + list-style: none; +} + +.list-group-item { + border-bottom: 1px solid #e7eaec; + border-top: 1px solid #e7eaec; + margin-bottom: -1px; + padding: 11px 0px; + font-size: 13px; +} + +.pull-right { + float: right !important; +} + +.el-card__header { + padding: 14px 15px 7px; + min-height: 40px; +} + +.el-card__body { + padding: 15px 20px 20px 20px; +} + +.card-box { + padding-right: 15px; + padding-left: 15px; + margin-bottom: 10px; +} + +/* button color */ +.el-button--cyan.is-active, +.el-button--cyan:active { + background: #20B2AA; + border-color: #20B2AA; + color: #FFFFFF; +} + +.el-button--cyan:focus, +.el-button--cyan:hover { + background: #48D1CC; + border-color: #48D1CC; + color: #FFFFFF; +} + +.el-button--cyan { + background-color: #20B2AA; + border-color: #20B2AA; + color: #FFFFFF; +} + +/* text color */ +.text-navy { + color: #1ab394; +} + +.text-primary { + color: inherit; +} + +.text-success { + color: #1c84c6; +} + +.text-info { + color: #23c6c8; +} + +.text-warning { + color: #f8ac59; +} + +.text-danger { + color: #ed5565; +} + +.text-muted { + color: #888888; +} + +/* image */ +.img-circle { + border-radius: 50%; +} + +.img-lg { + width: 120px; + height: 120px; +} + +.avatar-upload-preview { + position: relative; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 200px; + height: 200px; + border-radius: 50%; + box-shadow: 0 0 4px #ccc; + overflow: hidden; +} + +/* 拖拽列样式 */ +.sortable-ghost{ + opacity: .8; + color: #fff!important; + background: #42b983!important; +} + +.top-right-btn { + position: relative; + float: right; +} diff --git a/custom-ui/src/assets/styles/sidebar.scss b/custom-ui/src/assets/styles/sidebar.scss new file mode 100644 index 0000000..ed308b8 --- /dev/null +++ b/custom-ui/src/assets/styles/sidebar.scss @@ -0,0 +1,227 @@ +#app { + + .main-container { + min-height: 100%; + transition: margin-left .28s; + margin-left: $base-sidebar-width; + position: relative; + } + + .sidebarHide { + margin-left: 0!important; + } + + .sidebar-container { + -webkit-transition: width .28s; + transition: width 0.28s; + width: $base-sidebar-width !important; + background-color: $base-menu-background; + height: 100%; + position: fixed; + font-size: 0px; + top: 0; + bottom: 0; + left: 0; + z-index: 1001; + overflow: hidden; + -webkit-box-shadow: 2px 0 6px rgba(0,21,41,.35); + box-shadow: 2px 0 6px rgba(0,21,41,.35); + + // reset element-ui css + .horizontal-collapse-transition { + transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out; + } + + .scrollbar-wrapper { + overflow-x: hidden !important; + } + + .el-scrollbar__bar.is-vertical { + right: 0px; + } + + .el-scrollbar { + height: 100%; + } + + &.has-logo { + .el-scrollbar { + height: calc(100% - 50px); + } + } + + .is-horizontal { + display: none; + } + + a { + display: inline-block; + width: 100%; + overflow: hidden; + } + + .svg-icon { + margin-right: 16px; + } + + .el-menu { + border: none; + height: 100%; + width: 100% !important; + } + + .el-menu-item, .el-submenu__title { + overflow: hidden !important; + text-overflow: ellipsis !important; + white-space: nowrap !important; + } + + // menu hover + .submenu-title-noDropdown, + .el-submenu__title { + &:hover { + background-color: rgba(0, 0, 0, 0.06) !important; + } + } + + & .theme-dark .is-active > .el-submenu__title { + color: $base-menu-color-active !important; + } + + & .nest-menu .el-submenu>.el-submenu__title, + & .el-submenu .el-menu-item { + min-width: $base-sidebar-width !important; + + &:hover { + background-color: rgba(0, 0, 0, 0.06) !important; + } + } + + & .theme-dark .nest-menu .el-submenu>.el-submenu__title, + & .theme-dark .el-submenu .el-menu-item { + background-color: $base-sub-menu-background !important; + + &:hover { + background-color: $base-sub-menu-hover !important; + } + } + } + + .hideSidebar { + .sidebar-container { + width: 54px !important; + } + + .main-container { + margin-left: 54px; + } + + .submenu-title-noDropdown { + padding: 0 !important; + position: relative; + + .el-tooltip { + padding: 0 !important; + + .svg-icon { + margin-left: 20px; + } + } + } + + .el-submenu { + overflow: hidden; + + &>.el-submenu__title { + padding: 0 !important; + + .svg-icon { + margin-left: 20px; + } + + } + } + + .el-menu--collapse { + .el-submenu { + &>.el-submenu__title { + &>span { + height: 0; + width: 0; + overflow: hidden; + visibility: hidden; + display: inline-block; + } + } + } + } + } + + .el-menu--collapse .el-menu .el-submenu { + min-width: $base-sidebar-width !important; + } + + // mobile responsive + .mobile { + .main-container { + margin-left: 0px; + } + + .sidebar-container { + transition: transform .28s; + width: $base-sidebar-width !important; + } + + &.hideSidebar { + .sidebar-container { + pointer-events: none; + transition-duration: 0.3s; + transform: translate3d(-$base-sidebar-width, 0, 0); + } + } + } + + .withoutAnimation { + + .main-container, + .sidebar-container { + transition: none; + } + } +} + +// when menu collapsed +.el-menu--vertical { + &>.el-menu { + .svg-icon { + margin-right: 16px; + } + } + + .nest-menu .el-submenu>.el-submenu__title, + .el-menu-item { + &:hover { + // you can use $subMenuHover + background-color: rgba(0, 0, 0, 0.06) !important; + } + } + + // the scroll bar appears when the subMenu is too long + >.el-menu--popup { + max-height: 100vh; + overflow-y: auto; + + &::-webkit-scrollbar-track-piece { + background: #d3dce6; + } + + &::-webkit-scrollbar { + width: 6px; + } + + &::-webkit-scrollbar-thumb { + background: #99a9bf; + border-radius: 20px; + } + } +} diff --git a/custom-ui/src/assets/styles/transition.scss b/custom-ui/src/assets/styles/transition.scss new file mode 100644 index 0000000..eb49895 --- /dev/null +++ b/custom-ui/src/assets/styles/transition.scss @@ -0,0 +1,53 @@ +// global transition css + +/* fade */ +.fade-enter-active, +.fade-leave-active { + transition: opacity 0.28s; +} + +.fade-enter, +.fade-leave-active { + opacity: 0; +} + +/* fade-transform */ +.fade-transform--move, +.fade-transform-leave-active, +.fade-transform-enter-active { + transition: all .5s; +} + +.fade-transform-leave-active { + position: absolute; +} + +.fade-transform-enter { + opacity: 0; + transform: translateX(-30px); +} + +.fade-transform-leave-to { + opacity: 0; + transform: translateX(30px); +} + +/* breadcrumb transition */ +.breadcrumb-enter-active, +.breadcrumb-leave-active { + transition: all .5s; +} + +.breadcrumb-enter, +.breadcrumb-leave-active { + opacity: 0; + transform: translateX(20px); +} + +.breadcrumb-move { + transition: all .5s; +} + +.breadcrumb-leave-active { + position: absolute; +} diff --git a/custom-ui/src/assets/styles/variables.scss b/custom-ui/src/assets/styles/variables.scss new file mode 100644 index 0000000..34484d4 --- /dev/null +++ b/custom-ui/src/assets/styles/variables.scss @@ -0,0 +1,54 @@ +// base color +$blue:#324157; +$light-blue:#3A71A8; +$red:#C03639; +$pink: #E65D6E; +$green: #30B08F; +$tiffany: #4AB7BD; +$yellow:#FEC171; +$panGreen: #30B08F; + +// 默认菜单主题风格 +$base-menu-color:#bfcbd9; +$base-menu-color-active:#f4f4f5; +$base-menu-background:#304156; +$base-logo-title-color: #ffffff; + +$base-menu-light-color:rgba(0,0,0,.70); +$base-menu-light-background:#ffffff; +$base-logo-light-title-color: #001529; + +$base-sub-menu-background:#1f2d3d; +$base-sub-menu-hover:#001528; + +// 自定义暗色菜单风格 +/** +$base-menu-color:hsla(0,0%,100%,.65); +$base-menu-color-active:#fff; +$base-menu-background:#001529; +$base-logo-title-color: #ffffff; + +$base-menu-light-color:rgba(0,0,0,.70); +$base-menu-light-background:#ffffff; +$base-logo-light-title-color: #001529; + +$base-sub-menu-background:#000c17; +$base-sub-menu-hover:#001528; +*/ + +$base-sidebar-width: 200px; + +// the :export directive is the magic sauce for webpack +// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass +:export { + menuColor: $base-menu-color; + menuLightColor: $base-menu-light-color; + menuColorActive: $base-menu-color-active; + menuBackground: $base-menu-background; + menuLightBackground: $base-menu-light-background; + subMenuBackground: $base-sub-menu-background; + subMenuHover: $base-sub-menu-hover; + sideBarWidth: $base-sidebar-width; + logoTitleColor: $base-logo-title-color; + logoLightTitleColor: $base-logo-light-title-color +} diff --git a/custom-ui/src/components/Breadcrumb/index.vue b/custom-ui/src/components/Breadcrumb/index.vue new file mode 100644 index 0000000..1696f54 --- /dev/null +++ b/custom-ui/src/components/Breadcrumb/index.vue @@ -0,0 +1,74 @@ + + + + + diff --git a/custom-ui/src/components/Crontab/day.vue b/custom-ui/src/components/Crontab/day.vue new file mode 100644 index 0000000..fe3eaf0 --- /dev/null +++ b/custom-ui/src/components/Crontab/day.vue @@ -0,0 +1,161 @@ + + + diff --git a/custom-ui/src/components/Crontab/hour.vue b/custom-ui/src/components/Crontab/hour.vue new file mode 100644 index 0000000..4b1f1fc --- /dev/null +++ b/custom-ui/src/components/Crontab/hour.vue @@ -0,0 +1,114 @@ + + + diff --git a/custom-ui/src/components/Crontab/index.vue b/custom-ui/src/components/Crontab/index.vue new file mode 100644 index 0000000..3963df2 --- /dev/null +++ b/custom-ui/src/components/Crontab/index.vue @@ -0,0 +1,430 @@ + + + + diff --git a/custom-ui/src/components/Crontab/min.vue b/custom-ui/src/components/Crontab/min.vue new file mode 100644 index 0000000..43cab90 --- /dev/null +++ b/custom-ui/src/components/Crontab/min.vue @@ -0,0 +1,116 @@ + + + \ No newline at end of file diff --git a/custom-ui/src/components/Crontab/month.vue b/custom-ui/src/components/Crontab/month.vue new file mode 100644 index 0000000..fd0ac38 --- /dev/null +++ b/custom-ui/src/components/Crontab/month.vue @@ -0,0 +1,114 @@ + + + diff --git a/custom-ui/src/components/Crontab/result.vue b/custom-ui/src/components/Crontab/result.vue new file mode 100644 index 0000000..aea6e0e --- /dev/null +++ b/custom-ui/src/components/Crontab/result.vue @@ -0,0 +1,559 @@ + + + diff --git a/custom-ui/src/components/Crontab/second.vue b/custom-ui/src/components/Crontab/second.vue new file mode 100644 index 0000000..e7b7761 --- /dev/null +++ b/custom-ui/src/components/Crontab/second.vue @@ -0,0 +1,117 @@ + + + diff --git a/custom-ui/src/components/Crontab/week.vue b/custom-ui/src/components/Crontab/week.vue new file mode 100644 index 0000000..1cec700 --- /dev/null +++ b/custom-ui/src/components/Crontab/week.vue @@ -0,0 +1,202 @@ + + + diff --git a/custom-ui/src/components/Crontab/year.vue b/custom-ui/src/components/Crontab/year.vue new file mode 100644 index 0000000..5487a6c --- /dev/null +++ b/custom-ui/src/components/Crontab/year.vue @@ -0,0 +1,131 @@ + + + diff --git a/custom-ui/src/components/DictData/index.js b/custom-ui/src/components/DictData/index.js new file mode 100644 index 0000000..7b85d4a --- /dev/null +++ b/custom-ui/src/components/DictData/index.js @@ -0,0 +1,49 @@ +import Vue from 'vue' +import store from '@/store' +import DataDict from '@/utils/dict' +import { getDicts as getDicts } from '@/api/system/dict/data' + +function searchDictByKey(dict, key) { + if (key == null && key == "") { + return null + } + try { + for (let i = 0; i < dict.length; i++) { + if (dict[i].key == key) { + return dict[i].value + } + } + } catch (e) { + return null + } +} + +function install() { + Vue.use(DataDict, { + metas: { + '*': { + labelField: 'dictLabel', + valueField: 'dictValue', + request(dictMeta) { + const storeDict = searchDictByKey(store.getters.dict, dictMeta.type) + if (storeDict) { + return new Promise(resolve => { resolve(storeDict) }) + } else { + return new Promise((resolve, reject) => { + getDicts(dictMeta.type).then(res => { + store.dispatch('dict/setDict', { key: dictMeta.type, value: res.data }) + resolve(res.data) + }).catch(error => { + reject(error) + }) + }) + } + }, + }, + }, + }) +} + +export default { + install, +} \ No newline at end of file diff --git a/custom-ui/src/components/DictTag/index.vue b/custom-ui/src/components/DictTag/index.vue new file mode 100644 index 0000000..4c196c4 --- /dev/null +++ b/custom-ui/src/components/DictTag/index.vue @@ -0,0 +1,52 @@ + + + + \ No newline at end of file diff --git a/custom-ui/src/components/Editor/index.vue b/custom-ui/src/components/Editor/index.vue new file mode 100644 index 0000000..6bb5a18 --- /dev/null +++ b/custom-ui/src/components/Editor/index.vue @@ -0,0 +1,272 @@ + + + + + diff --git a/custom-ui/src/components/FileUpload/index.vue b/custom-ui/src/components/FileUpload/index.vue new file mode 100644 index 0000000..6c583cf --- /dev/null +++ b/custom-ui/src/components/FileUpload/index.vue @@ -0,0 +1,215 @@ + + + + + diff --git a/custom-ui/src/components/Hamburger/index.vue b/custom-ui/src/components/Hamburger/index.vue new file mode 100644 index 0000000..368b002 --- /dev/null +++ b/custom-ui/src/components/Hamburger/index.vue @@ -0,0 +1,44 @@ + + + + + diff --git a/custom-ui/src/components/HeaderSearch/index.vue b/custom-ui/src/components/HeaderSearch/index.vue new file mode 100644 index 0000000..c4d76bb --- /dev/null +++ b/custom-ui/src/components/HeaderSearch/index.vue @@ -0,0 +1,189 @@ + + + + + diff --git a/custom-ui/src/components/IconSelect/index.vue b/custom-ui/src/components/IconSelect/index.vue new file mode 100644 index 0000000..b0ec9fa --- /dev/null +++ b/custom-ui/src/components/IconSelect/index.vue @@ -0,0 +1,68 @@ + + + + + + diff --git a/custom-ui/src/components/IconSelect/requireIcons.js b/custom-ui/src/components/IconSelect/requireIcons.js new file mode 100644 index 0000000..99e5c54 --- /dev/null +++ b/custom-ui/src/components/IconSelect/requireIcons.js @@ -0,0 +1,11 @@ + +const req = require.context('../../assets/icons/svg', false, /\.svg$/) +const requireAll = requireContext => requireContext.keys() + +const re = /\.\/(.*)\.svg/ + +const icons = requireAll(req).map(i => { + return i.match(re)[1] +}) + +export default icons diff --git a/custom-ui/src/components/ImagePreview/index.vue b/custom-ui/src/components/ImagePreview/index.vue new file mode 100644 index 0000000..3c770c7 --- /dev/null +++ b/custom-ui/src/components/ImagePreview/index.vue @@ -0,0 +1,90 @@ + + + + + diff --git a/custom-ui/src/components/ImageUpload/index.vue b/custom-ui/src/components/ImageUpload/index.vue new file mode 100644 index 0000000..b57a15e --- /dev/null +++ b/custom-ui/src/components/ImageUpload/index.vue @@ -0,0 +1,226 @@ + + + + + diff --git a/custom-ui/src/components/Pagination/index.vue b/custom-ui/src/components/Pagination/index.vue new file mode 100644 index 0000000..56f5a6b --- /dev/null +++ b/custom-ui/src/components/Pagination/index.vue @@ -0,0 +1,114 @@ + + + + + diff --git a/custom-ui/src/components/PanThumb/index.vue b/custom-ui/src/components/PanThumb/index.vue new file mode 100644 index 0000000..1bcf417 --- /dev/null +++ b/custom-ui/src/components/PanThumb/index.vue @@ -0,0 +1,142 @@ + + + + + diff --git a/custom-ui/src/components/ParentView/index.vue b/custom-ui/src/components/ParentView/index.vue new file mode 100644 index 0000000..7bf6148 --- /dev/null +++ b/custom-ui/src/components/ParentView/index.vue @@ -0,0 +1,3 @@ + diff --git a/custom-ui/src/components/RightPanel/index.vue b/custom-ui/src/components/RightPanel/index.vue new file mode 100644 index 0000000..5abeecb --- /dev/null +++ b/custom-ui/src/components/RightPanel/index.vue @@ -0,0 +1,106 @@ + + + + + diff --git a/custom-ui/src/components/RightToolbar/index.vue b/custom-ui/src/components/RightToolbar/index.vue new file mode 100644 index 0000000..527e07c --- /dev/null +++ b/custom-ui/src/components/RightToolbar/index.vue @@ -0,0 +1,104 @@ + + + diff --git a/custom-ui/src/components/RuoYi/Doc/index.vue b/custom-ui/src/components/RuoYi/Doc/index.vue new file mode 100644 index 0000000..75fa864 --- /dev/null +++ b/custom-ui/src/components/RuoYi/Doc/index.vue @@ -0,0 +1,21 @@ + + + \ No newline at end of file diff --git a/custom-ui/src/components/RuoYi/Git/index.vue b/custom-ui/src/components/RuoYi/Git/index.vue new file mode 100644 index 0000000..bdafbae --- /dev/null +++ b/custom-ui/src/components/RuoYi/Git/index.vue @@ -0,0 +1,21 @@ + + + \ No newline at end of file diff --git a/custom-ui/src/components/Screenfull/index.vue b/custom-ui/src/components/Screenfull/index.vue new file mode 100644 index 0000000..d4e539c --- /dev/null +++ b/custom-ui/src/components/Screenfull/index.vue @@ -0,0 +1,57 @@ + + + + + diff --git a/custom-ui/src/components/SizeSelect/index.vue b/custom-ui/src/components/SizeSelect/index.vue new file mode 100644 index 0000000..069b5de --- /dev/null +++ b/custom-ui/src/components/SizeSelect/index.vue @@ -0,0 +1,56 @@ + + + diff --git a/custom-ui/src/components/SvgIcon/index.vue b/custom-ui/src/components/SvgIcon/index.vue new file mode 100644 index 0000000..e4bf5ad --- /dev/null +++ b/custom-ui/src/components/SvgIcon/index.vue @@ -0,0 +1,61 @@ + + + + + diff --git a/custom-ui/src/components/ThemePicker/index.vue b/custom-ui/src/components/ThemePicker/index.vue new file mode 100644 index 0000000..1714e1f --- /dev/null +++ b/custom-ui/src/components/ThemePicker/index.vue @@ -0,0 +1,173 @@ + + + + + diff --git a/custom-ui/src/components/TopNav/index.vue b/custom-ui/src/components/TopNav/index.vue new file mode 100644 index 0000000..5f0edbe --- /dev/null +++ b/custom-ui/src/components/TopNav/index.vue @@ -0,0 +1,185 @@ + + + + + diff --git a/custom-ui/src/components/iFrame/index.vue b/custom-ui/src/components/iFrame/index.vue new file mode 100644 index 0000000..426857f --- /dev/null +++ b/custom-ui/src/components/iFrame/index.vue @@ -0,0 +1,36 @@ + + + diff --git a/custom-ui/src/layout/components/Navbar.vue b/custom-ui/src/layout/components/Navbar.vue new file mode 100644 index 0000000..34095fd --- /dev/null +++ b/custom-ui/src/layout/components/Navbar.vue @@ -0,0 +1,192 @@ + + + + + diff --git a/custom-ui/src/layout/components/Settings/index.vue b/custom-ui/src/layout/components/Settings/index.vue new file mode 100644 index 0000000..8b49842 --- /dev/null +++ b/custom-ui/src/layout/components/Settings/index.vue @@ -0,0 +1,260 @@ + + + + + diff --git a/custom-ui/src/layout/components/Sidebar/FixiOSBug.js b/custom-ui/src/layout/components/Sidebar/FixiOSBug.js new file mode 100644 index 0000000..6823726 --- /dev/null +++ b/custom-ui/src/layout/components/Sidebar/FixiOSBug.js @@ -0,0 +1,25 @@ +export default { + computed: { + device() { + return this.$store.state.app.device + } + }, + mounted() { + // In order to fix the click on menu on the ios device will trigger the mouseleave bug + this.fixBugIniOS() + }, + methods: { + fixBugIniOS() { + const $subMenu = this.$refs.subMenu + if ($subMenu) { + const handleMouseleave = $subMenu.handleMouseleave + $subMenu.handleMouseleave = (e) => { + if (this.device === 'mobile') { + return + } + handleMouseleave(e) + } + } + } + } +} diff --git a/custom-ui/src/layout/components/Sidebar/Item.vue b/custom-ui/src/layout/components/Sidebar/Item.vue new file mode 100644 index 0000000..be3285d --- /dev/null +++ b/custom-ui/src/layout/components/Sidebar/Item.vue @@ -0,0 +1,33 @@ + diff --git a/custom-ui/src/layout/components/Sidebar/Link.vue b/custom-ui/src/layout/components/Sidebar/Link.vue new file mode 100644 index 0000000..8b0bc93 --- /dev/null +++ b/custom-ui/src/layout/components/Sidebar/Link.vue @@ -0,0 +1,43 @@ + + + diff --git a/custom-ui/src/layout/components/Sidebar/Logo.vue b/custom-ui/src/layout/components/Sidebar/Logo.vue new file mode 100644 index 0000000..b1e8482 --- /dev/null +++ b/custom-ui/src/layout/components/Sidebar/Logo.vue @@ -0,0 +1,93 @@ + + + + + diff --git a/custom-ui/src/layout/components/Sidebar/SidebarItem.vue b/custom-ui/src/layout/components/Sidebar/SidebarItem.vue new file mode 100644 index 0000000..4853fbb --- /dev/null +++ b/custom-ui/src/layout/components/Sidebar/SidebarItem.vue @@ -0,0 +1,100 @@ + + + diff --git a/custom-ui/src/layout/components/Sidebar/index.vue b/custom-ui/src/layout/components/Sidebar/index.vue new file mode 100644 index 0000000..51d0839 --- /dev/null +++ b/custom-ui/src/layout/components/Sidebar/index.vue @@ -0,0 +1,57 @@ + + + diff --git a/custom-ui/src/layout/components/TagsView/ScrollPane.vue b/custom-ui/src/layout/components/TagsView/ScrollPane.vue new file mode 100644 index 0000000..bb753a1 --- /dev/null +++ b/custom-ui/src/layout/components/TagsView/ScrollPane.vue @@ -0,0 +1,94 @@ + + + + + diff --git a/custom-ui/src/layout/components/TagsView/index.vue b/custom-ui/src/layout/components/TagsView/index.vue new file mode 100644 index 0000000..cc98071 --- /dev/null +++ b/custom-ui/src/layout/components/TagsView/index.vue @@ -0,0 +1,332 @@ + + + + + + + diff --git a/custom-ui/src/layout/components/index.js b/custom-ui/src/layout/components/index.js new file mode 100644 index 0000000..104bd3a --- /dev/null +++ b/custom-ui/src/layout/components/index.js @@ -0,0 +1,5 @@ +export { default as AppMain } from './AppMain' +export { default as Navbar } from './Navbar' +export { default as Settings } from './Settings' +export { default as Sidebar } from './Sidebar/index.vue' +export { default as TagsView } from './TagsView/index.vue' diff --git a/custom-ui/src/layout/index.vue b/custom-ui/src/layout/index.vue new file mode 100644 index 0000000..f048657 --- /dev/null +++ b/custom-ui/src/layout/index.vue @@ -0,0 +1,111 @@ + + + + + diff --git a/custom-ui/src/layout/mixin/ResizeHandler.js b/custom-ui/src/layout/mixin/ResizeHandler.js new file mode 100644 index 0000000..e8d0df8 --- /dev/null +++ b/custom-ui/src/layout/mixin/ResizeHandler.js @@ -0,0 +1,45 @@ +import store from '@/store' + +const { body } = document +const WIDTH = 992 // refer to Bootstrap's responsive design + +export default { + watch: { + $route(route) { + if (this.device === 'mobile' && this.sidebar.opened) { + store.dispatch('app/closeSideBar', { withoutAnimation: false }) + } + } + }, + beforeMount() { + window.addEventListener('resize', this.$_resizeHandler) + }, + beforeDestroy() { + window.removeEventListener('resize', this.$_resizeHandler) + }, + mounted() { + const isMobile = this.$_isMobile() + if (isMobile) { + store.dispatch('app/toggleDevice', 'mobile') + store.dispatch('app/closeSideBar', { withoutAnimation: true }) + } + }, + methods: { + // use $_ for mixins properties + // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential + $_isMobile() { + const rect = body.getBoundingClientRect() + return rect.width - 1 < WIDTH + }, + $_resizeHandler() { + if (!document.hidden) { + const isMobile = this.$_isMobile() + store.dispatch('app/toggleDevice', isMobile ? 'mobile' : 'desktop') + + if (isMobile) { + store.dispatch('app/closeSideBar', { withoutAnimation: true }) + } + } + } + } +} diff --git a/custom-ui/src/main.js b/custom-ui/src/main.js new file mode 100644 index 0000000..13c6cf2 --- /dev/null +++ b/custom-ui/src/main.js @@ -0,0 +1,86 @@ +import Vue from 'vue' + +import Cookies from 'js-cookie' + +import Element from 'element-ui' +import './assets/styles/element-variables.scss' + +import '@/assets/styles/index.scss' // global css +import '@/assets/styles/ruoyi.scss' // ruoyi css +import App from './App' +import store from './store' +import router from './router' +import directive from './directive' // directive +import plugins from './plugins' // plugins +import { download } from '@/utils/request' + +import './assets/icons' // icon +import './permission' // permission control +import { getDicts } from "@/api/system/dict/data"; +import { getConfigKey } from "@/api/system/config"; +import { parseTime, resetForm, addDateRange, selectDictLabel, selectDictLabels, handleTree } from "@/utils/ruoyi"; +// 分页组件 +import Pagination from "@/components/Pagination"; +// 自定义表格工具组件 +import RightToolbar from "@/components/RightToolbar" +// 富文本组件 +import Editor from "@/components/Editor" +// 文件上传组件 +import FileUpload from "@/components/FileUpload" +// 图片上传组件 +import ImageUpload from "@/components/ImageUpload" +// 图片预览组件 +import ImagePreview from "@/components/ImagePreview" +// 字典标签组件 +import DictTag from '@/components/DictTag' +// 头部标签组件 +import VueMeta from 'vue-meta' +// 字典数据组件 +import DictData from '@/components/DictData' + +// 全局方法挂载 +Vue.prototype.getDicts = getDicts +Vue.prototype.getConfigKey = getConfigKey +Vue.prototype.parseTime = parseTime +Vue.prototype.resetForm = resetForm +Vue.prototype.addDateRange = addDateRange +Vue.prototype.selectDictLabel = selectDictLabel +Vue.prototype.selectDictLabels = selectDictLabels +Vue.prototype.download = download +Vue.prototype.handleTree = handleTree + +// 全局组件挂载 +Vue.component('DictTag', DictTag) +Vue.component('Pagination', Pagination) +Vue.component('RightToolbar', RightToolbar) +Vue.component('Editor', Editor) +Vue.component('FileUpload', FileUpload) +Vue.component('ImageUpload', ImageUpload) +Vue.component('ImagePreview', ImagePreview) + +Vue.use(directive) +Vue.use(plugins) +Vue.use(VueMeta) +DictData.install() + +/** + * If you don't want to use mock-server + * you want to use MockJs for mock api + * you can execute: mockXHR() + * + * Currently MockJs will be used in the production environment, + * please remove it before going online! ! ! + */ + +Vue.use(Element, { + size: Cookies.get('size') || 'medium' // set element-ui default size +}) + +Vue.config.productionTip = false + +new Vue({ + el: '#app', + router, + store, + render: h => h(App) +}) diff --git a/custom-ui/src/permission.js b/custom-ui/src/permission.js new file mode 100644 index 0000000..6bb0a1f --- /dev/null +++ b/custom-ui/src/permission.js @@ -0,0 +1,56 @@ +import router from './router' +import store from './store' +import { Message } from 'element-ui' +import NProgress from 'nprogress' +import 'nprogress/nprogress.css' +import { getToken } from '@/utils/auth' +import { isRelogin } from '@/utils/request' + +NProgress.configure({ showSpinner: false }) + +const whiteList = ['/login', '/auth-redirect', '/bind', '/register'] + +router.beforeEach((to, from, next) => { + NProgress.start() + if (getToken()) { + to.meta.title && store.dispatch('settings/setTitle', to.meta.title) + /* has token*/ + if (to.path === '/login') { + next({ path: '/' }) + NProgress.done() + } else { + if (store.getters.roles.length === 0) { + isRelogin.show = true + // 判断当前用户是否已拉取完user_info信息 + store.dispatch('GetInfo').then(() => { + isRelogin.show = false + store.dispatch('GenerateRoutes').then(accessRoutes => { + // 根据roles权限生成可访问的路由表 + router.addRoutes(accessRoutes) // 动态添加可访问路由表 + next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 + }) + }).catch(err => { + store.dispatch('LogOut').then(() => { + Message.error(err) + next({ path: '/' }) + }) + }) + } else { + next() + } + } + } else { + // 没有token + if (whiteList.indexOf(to.path) !== -1) { + // 在免登录白名单,直接进入 + next() + } else { + next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页 + NProgress.done() + } + } +}) + +router.afterEach(() => { + NProgress.done() +}) diff --git a/custom-ui/src/plugins/auth.js b/custom-ui/src/plugins/auth.js new file mode 100644 index 0000000..6c6bc24 --- /dev/null +++ b/custom-ui/src/plugins/auth.js @@ -0,0 +1,60 @@ +import store from '@/store' + +function authPermission(permission) { + const all_permission = "*:*:*"; + const permissions = store.getters && store.getters.permissions + if (permission && permission.length > 0) { + return permissions.some(v => { + return all_permission === v || v === permission + }) + } else { + return false + } +} + +function authRole(role) { + const super_admin = "admin"; + const roles = store.getters && store.getters.roles + if (role && role.length > 0) { + return roles.some(v => { + return super_admin === v || v === role + }) + } else { + return false + } +} + +export default { + // 验证用户是否具备某权限 + hasPermi(permission) { + return authPermission(permission); + }, + // 验证用户是否含有指定权限,只需包含其中一个 + hasPermiOr(permissions) { + return permissions.some(item => { + return authPermission(item) + }) + }, + // 验证用户是否含有指定权限,必须全部拥有 + hasPermiAnd(permissions) { + return permissions.every(item => { + return authPermission(item) + }) + }, + // 验证用户是否具备某角色 + hasRole(role) { + return authRole(role); + }, + // 验证用户是否含有指定角色,只需包含其中一个 + hasRoleOr(roles) { + return roles.some(item => { + return authRole(item) + }) + }, + // 验证用户是否含有指定角色,必须全部拥有 + hasRoleAnd(roles) { + return roles.every(item => { + return authRole(item) + }) + } +} diff --git a/custom-ui/src/plugins/cache.js b/custom-ui/src/plugins/cache.js new file mode 100644 index 0000000..6b5c00b --- /dev/null +++ b/custom-ui/src/plugins/cache.js @@ -0,0 +1,77 @@ +const sessionCache = { + set (key, value) { + if (!sessionStorage) { + return + } + if (key != null && value != null) { + sessionStorage.setItem(key, value) + } + }, + get (key) { + if (!sessionStorage) { + return null + } + if (key == null) { + return null + } + return sessionStorage.getItem(key) + }, + setJSON (key, jsonValue) { + if (jsonValue != null) { + this.set(key, JSON.stringify(jsonValue)) + } + }, + getJSON (key) { + const value = this.get(key) + if (value != null) { + return JSON.parse(value) + } + }, + remove (key) { + sessionStorage.removeItem(key); + } +} +const localCache = { + set (key, value) { + if (!localStorage) { + return + } + if (key != null && value != null) { + localStorage.setItem(key, value) + } + }, + get (key) { + if (!localStorage) { + return null + } + if (key == null) { + return null + } + return localStorage.getItem(key) + }, + setJSON (key, jsonValue) { + if (jsonValue != null) { + this.set(key, JSON.stringify(jsonValue)) + } + }, + getJSON (key) { + const value = this.get(key) + if (value != null) { + return JSON.parse(value) + } + }, + remove (key) { + localStorage.removeItem(key); + } +} + +export default { + /** + * 会话级缓存 + */ + session: sessionCache, + /** + * 本地缓存 + */ + local: localCache +} diff --git a/custom-ui/src/plugins/download.js b/custom-ui/src/plugins/download.js new file mode 100644 index 0000000..a3bb8c4 --- /dev/null +++ b/custom-ui/src/plugins/download.js @@ -0,0 +1,72 @@ +import axios from 'axios' +import { Message } from 'element-ui' +import { saveAs } from 'file-saver' +import { getToken } from '@/utils/auth' +import errorCode from '@/utils/errorCode' +import { blobValidate } from "@/utils/ruoyi"; + +const baseURL = process.env.VUE_APP_BASE_API + +export default { + name(name, isDelete = true) { + var url = baseURL + "/common/download?fileName=" + encodeURIComponent(name) + "&delete=" + isDelete + axios({ + method: 'get', + url: url, + responseType: 'blob', + headers: { 'Authorization': 'Bearer ' + getToken() } + }).then(async (res) => { + const isLogin = await blobValidate(res.data); + if (isLogin) { + const blob = new Blob([res.data]) + this.saveAs(blob, decodeURIComponent(res.headers['download-filename'])) + } else { + this.printErrMsg(res.data); + } + }) + }, + resource(resource) { + var url = baseURL + "/common/download/resource?resource=" + encodeURIComponent(resource); + axios({ + method: 'get', + url: url, + responseType: 'blob', + headers: { 'Authorization': 'Bearer ' + getToken() } + }).then(async (res) => { + const isLogin = await blobValidate(res.data); + if (isLogin) { + const blob = new Blob([res.data]) + this.saveAs(blob, decodeURIComponent(res.headers['download-filename'])) + } else { + this.printErrMsg(res.data); + } + }) + }, + zip(url, name) { + var url = baseURL + url + axios({ + method: 'get', + url: url, + responseType: 'blob', + headers: { 'Authorization': 'Bearer ' + getToken() } + }).then(async (res) => { + const isLogin = await blobValidate(res.data); + if (isLogin) { + const blob = new Blob([res.data], { type: 'application/zip' }) + this.saveAs(blob, name) + } else { + this.printErrMsg(res.data); + } + }) + }, + saveAs(text, name, opts) { + saveAs(text, name, opts); + }, + async printErrMsg(data) { + const resText = await data.text(); + const rspObj = JSON.parse(resText); + const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default'] + Message.error(errMsg); + } +} + diff --git a/custom-ui/src/plugins/index.js b/custom-ui/src/plugins/index.js new file mode 100644 index 0000000..d000f2d --- /dev/null +++ b/custom-ui/src/plugins/index.js @@ -0,0 +1,20 @@ +import tab from './tab' +import auth from './auth' +import cache from './cache' +import modal from './modal' +import download from './download' + +export default { + install(Vue) { + // 页签操作 + Vue.prototype.$tab = tab + // 认证对象 + Vue.prototype.$auth = auth + // 缓存对象 + Vue.prototype.$cache = cache + // 模态框对象 + Vue.prototype.$modal = modal + // 下载文件 + Vue.prototype.$download = download + } +} diff --git a/custom-ui/src/plugins/modal.js b/custom-ui/src/plugins/modal.js new file mode 100644 index 0000000..b37ca14 --- /dev/null +++ b/custom-ui/src/plugins/modal.js @@ -0,0 +1,83 @@ +import { Message, MessageBox, Notification, Loading } from 'element-ui' + +let loadingInstance; + +export default { + // 消息提示 + msg(content) { + Message.info(content) + }, + // 错误消息 + msgError(content) { + Message.error(content) + }, + // 成功消息 + msgSuccess(content) { + Message.success(content) + }, + // 警告消息 + msgWarning(content) { + Message.warning(content) + }, + // 弹出提示 + alert(content) { + MessageBox.alert(content, "系统提示") + }, + // 错误提示 + alertError(content) { + MessageBox.alert(content, "系统提示", { type: 'error' }) + }, + // 成功提示 + alertSuccess(content) { + MessageBox.alert(content, "系统提示", { type: 'success' }) + }, + // 警告提示 + alertWarning(content) { + MessageBox.alert(content, "系统提示", { type: 'warning' }) + }, + // 通知提示 + notify(content) { + Notification.info(content) + }, + // 错误通知 + notifyError(content) { + Notification.error(content); + }, + // 成功通知 + notifySuccess(content) { + Notification.success(content) + }, + // 警告通知 + notifyWarning(content) { + Notification.warning(content) + }, + // 确认窗体 + confirm(content) { + return MessageBox.confirm(content, "系统提示", { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: "warning", + }) + }, + // 提交内容 + prompt(content) { + return MessageBox.prompt(content, "系统提示", { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: "warning", + }) + }, + // 打开遮罩层 + loading(content) { + loadingInstance = Loading.service({ + lock: true, + text: content, + spinner: "el-icon-loading", + background: "rgba(0, 0, 0, 0.7)", + }) + }, + // 关闭遮罩层 + closeLoading() { + loadingInstance.close(); + } +} diff --git a/custom-ui/src/plugins/tab.js b/custom-ui/src/plugins/tab.js new file mode 100644 index 0000000..cade9f7 --- /dev/null +++ b/custom-ui/src/plugins/tab.js @@ -0,0 +1,67 @@ +import store from '@/store' +import router from '@/router'; + +export default { + // 刷新当前tab页签 + refreshPage(obj) { + const { path, query, matched } = router.currentRoute; + if (obj === undefined) { + matched.forEach((m) => { + if (m.components && m.components.default && m.components.default.name) { + if (!['Layout', 'ParentView'].includes(m.components.default.name)) { + obj = { name: m.components.default.name, path: path, query: query }; + } + } + }); + } + return store.dispatch('tagsView/delCachedView', obj).then(() => { + const { path, query } = obj + router.replace({ + path: '/redirect' + path, + query: query + }) + }) + }, + // 关闭当前tab页签,打开新页签 + closeOpenPage(obj) { + store.dispatch("tagsView/delView", router.currentRoute); + if (obj !== undefined) { + return router.push(obj); + } + }, + // 关闭指定tab页签 + closePage(obj) { + if (obj === undefined) { + return store.dispatch('tagsView/delView', router.currentRoute).then(({ lastPath }) => { + return router.push(lastPath || '/'); + }); + } + return store.dispatch('tagsView/delView', obj); + }, + // 关闭所有tab页签 + closeAllPage() { + return store.dispatch('tagsView/delAllViews'); + }, + // 关闭左侧tab页签 + closeLeftPage(obj) { + return store.dispatch('tagsView/delLeftTags', obj || router.currentRoute); + }, + // 关闭右侧tab页签 + closeRightPage(obj) { + return store.dispatch('tagsView/delRightTags', obj || router.currentRoute); + }, + // 关闭其他tab页签 + closeOtherPage(obj) { + return store.dispatch('tagsView/delOthersViews', obj || router.currentRoute); + }, + // 添加tab页签 + openPage(title, url, params) { + var obj = { path: url, meta: { title: title } } + store.dispatch('tagsView/addView', obj); + return router.push({ path: url, query: params }); + }, + // 修改tab页签 + updatePage(obj) { + return store.dispatch('tagsView/updateVisitedView', obj); + } +} diff --git a/custom-ui/src/router/index.js b/custom-ui/src/router/index.js new file mode 100644 index 0000000..b370bdd --- /dev/null +++ b/custom-ui/src/router/index.js @@ -0,0 +1,177 @@ +import Vue from 'vue' +import Router from 'vue-router' + +Vue.use(Router) + +/* Layout */ +import Layout from '@/layout' + +/** + * Note: 路由配置项 + * + * hidden: true // 当设置 true 的时候该路由不会再侧边栏出现 如401,login等页面,或者如一些编辑页面/edit/1 + * alwaysShow: true // 当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式--如组件页面 + * // 只有一个时,会将那个子路由当做根路由显示在侧边栏--如引导页面 + * // 若你想不管路由下面的 children 声明的个数都显示你的根路由 + * // 你可以设置 alwaysShow: true,这样它就会忽略之前定义的规则,一直显示根路由 + * redirect: noRedirect // 当设置 noRedirect 的时候该路由在面包屑导航中不可被点击 + * name:'router-name' // 设定路由的名字,一定要填写不然使用时会出现各种问题 + * query: '{"id": 1, "name": "ry"}' // 访问路由的默认传递参数 + * roles: ['admin', 'common'] // 访问路由的角色权限 + * permissions: ['a:a:a', 'b:b:b'] // 访问路由的菜单权限 + * meta : { + noCache: true // 如果设置为true,则不会被 缓存(默认 false) + title: 'title' // 设置该路由在侧边栏和面包屑中展示的名字 + icon: 'svg-name' // 设置该路由的图标,对应路径src/assets/icons/svg + breadcrumb: false // 如果设置为false,则不会在breadcrumb面包屑中显示 + activeMenu: '/system/user' // 当路由设置了该属性,则会高亮相对应的侧边栏。 + } + */ + +// 公共路由 +export const constantRoutes = [ + { + path: '/redirect', + component: Layout, + hidden: true, + children: [ + { + path: '/redirect/:path(.*)', + component: () => import('@/views/redirect') + } + ] + }, + { + path: '/login', + component: () => import('@/views/login'), + hidden: true + }, + { + path: '/register', + component: () => import('@/views/register'), + hidden: true + }, + { + path: '/404', + component: () => import('@/views/error/404'), + hidden: true + }, + { + path: '/401', + component: () => import('@/views/error/401'), + hidden: true + }, + { + path: '', + component: Layout, + redirect: 'index', + children: [ + { + path: 'index', + component: () => import('@/views/index'), + name: 'Index', + meta: { title: '首页', icon: 'dashboard', affix: true } + } + ] + }, + { + path: '/user', + component: Layout, + hidden: true, + redirect: 'noredirect', + children: [ + { + path: 'profile', + component: () => import('@/views/system/user/profile/index'), + name: 'Profile', + meta: { title: '个人中心', icon: 'user' } + } + ] + } +] + +// 动态路由,基于用户权限动态去加载 +export const dynamicRoutes = [ + { + path: '/system/user-auth', + component: Layout, + hidden: true, + permissions: ['system:user:edit'], + children: [ + { + path: 'role/:userId(\\d+)', + component: () => import('@/views/system/user/authRole'), + name: 'AuthRole', + meta: { title: '分配角色', activeMenu: '/system/user' } + } + ] + }, + { + path: '/system/role-auth', + component: Layout, + hidden: true, + permissions: ['system:role:edit'], + children: [ + { + path: 'user/:roleId(\\d+)', + component: () => import('@/views/system/role/authUser'), + name: 'AuthUser', + meta: { title: '分配用户', activeMenu: '/system/role' } + } + ] + }, + { + path: '/system/dict-data', + component: Layout, + hidden: true, + permissions: ['system:dict:list'], + children: [ + { + path: 'index/:dictId(\\d+)', + component: () => import('@/views/system/dict/data'), + name: 'Data', + meta: { title: '字典数据', activeMenu: '/system/dict' } + } + ] + }, + { + path: '/monitor/job-log', + component: Layout, + hidden: true, + permissions: ['monitor:job:list'], + children: [ + { + path: 'index/:jobId(\\d+)', + component: () => import('@/views/monitor/job/log'), + name: 'JobLog', + meta: { title: '调度日志', activeMenu: '/monitor/job' } + } + ] + }, + { + path: '/tool/gen-edit', + component: Layout, + hidden: true, + permissions: ['tool:gen:edit'], + children: [ + { + path: 'index/:tableId(\\d+)', + component: () => import('@/views/tool/gen/editTable'), + name: 'GenEdit', + meta: { title: '修改生成配置', activeMenu: '/tool/gen' } + } + ] + } +] + +// 防止连续点击多次路由报错 +let routerPush = Router.prototype.push; +Router.prototype.push = function push(location) { + return routerPush.call(this, location).catch(err => err) +} + +export default new Router({ + mode: 'history', // 去掉url中的# + scrollBehavior: () => ({ y: 0 }), + routes: constantRoutes +}) diff --git a/custom-ui/src/settings.js b/custom-ui/src/settings.js new file mode 100644 index 0000000..6a0b09f --- /dev/null +++ b/custom-ui/src/settings.js @@ -0,0 +1,44 @@ +module.exports = { + /** + * 侧边栏主题 深色主题theme-dark,浅色主题theme-light + */ + sideTheme: 'theme-dark', + + /** + * 是否系统布局配置 + */ + showSettings: false, + + /** + * 是否显示顶部导航 + */ + topNav: false, + + /** + * 是否显示 tagsView + */ + tagsView: true, + + /** + * 是否固定头部 + */ + fixedHeader: false, + + /** + * 是否显示logo + */ + sidebarLogo: true, + + /** + * 是否显示动态标题 + */ + dynamicTitle: false, + + /** + * @type {string | array} 'production' | ['production', 'development'] + * @description Need show err logs component. + * The default is only used in the production env + * If you want to also use it in dev, you can pass ['production', 'development'] + */ + errorLog: 'production' +} diff --git a/custom-ui/src/store/getters.js b/custom-ui/src/store/getters.js new file mode 100644 index 0000000..8adb1b6 --- /dev/null +++ b/custom-ui/src/store/getters.js @@ -0,0 +1,19 @@ +const getters = { + sidebar: state => state.app.sidebar, + size: state => state.app.size, + device: state => state.app.device, + dict: state => state.dict.dict, + visitedViews: state => state.tagsView.visitedViews, + cachedViews: state => state.tagsView.cachedViews, + token: state => state.user.token, + avatar: state => state.user.avatar, + name: state => state.user.name, + introduction: state => state.user.introduction, + roles: state => state.user.roles, + permissions: state => state.user.permissions, + permission_routes: state => state.permission.routes, + topbarRouters:state => state.permission.topbarRouters, + defaultRoutes:state => state.permission.defaultRoutes, + sidebarRouters:state => state.permission.sidebarRouters, +} +export default getters diff --git a/custom-ui/src/store/index.js b/custom-ui/src/store/index.js new file mode 100644 index 0000000..97aaef8 --- /dev/null +++ b/custom-ui/src/store/index.js @@ -0,0 +1,25 @@ +import Vue from 'vue' +import Vuex from 'vuex' +import app from './modules/app' +import dict from './modules/dict' +import user from './modules/user' +import tagsView from './modules/tagsView' +import permission from './modules/permission' +import settings from './modules/settings' +import getters from './getters' + +Vue.use(Vuex) + +const store = new Vuex.Store({ + modules: { + app, + dict, + user, + tagsView, + permission, + settings + }, + getters +}) + +export default store diff --git a/custom-ui/src/store/modules/app.js b/custom-ui/src/store/modules/app.js new file mode 100644 index 0000000..3e22d1c --- /dev/null +++ b/custom-ui/src/store/modules/app.js @@ -0,0 +1,66 @@ +import Cookies from 'js-cookie' + +const state = { + sidebar: { + opened: Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true, + withoutAnimation: false, + hide: false + }, + device: 'desktop', + size: Cookies.get('size') || 'medium' +} + +const mutations = { + TOGGLE_SIDEBAR: state => { + if (state.sidebar.hide) { + return false; + } + state.sidebar.opened = !state.sidebar.opened + state.sidebar.withoutAnimation = false + if (state.sidebar.opened) { + Cookies.set('sidebarStatus', 1) + } else { + Cookies.set('sidebarStatus', 0) + } + }, + CLOSE_SIDEBAR: (state, withoutAnimation) => { + Cookies.set('sidebarStatus', 0) + state.sidebar.opened = false + state.sidebar.withoutAnimation = withoutAnimation + }, + TOGGLE_DEVICE: (state, device) => { + state.device = device + }, + SET_SIZE: (state, size) => { + state.size = size + Cookies.set('size', size) + }, + SET_SIDEBAR_HIDE: (state, status) => { + state.sidebar.hide = status + } +} + +const actions = { + toggleSideBar({ commit }) { + commit('TOGGLE_SIDEBAR') + }, + closeSideBar({ commit }, { withoutAnimation }) { + commit('CLOSE_SIDEBAR', withoutAnimation) + }, + toggleDevice({ commit }, device) { + commit('TOGGLE_DEVICE', device) + }, + setSize({ commit }, size) { + commit('SET_SIZE', size) + }, + toggleSideBarHide({ commit }, status) { + commit('SET_SIDEBAR_HIDE', status) + } +} + +export default { + namespaced: true, + state, + mutations, + actions +} diff --git a/custom-ui/src/store/modules/dict.js b/custom-ui/src/store/modules/dict.js new file mode 100644 index 0000000..f95bead --- /dev/null +++ b/custom-ui/src/store/modules/dict.js @@ -0,0 +1,50 @@ +const state = { + dict: new Array() +} +const mutations = { + SET_DICT: (state, { key, value }) => { + if (key !== null && key !== "") { + state.dict.push({ + key: key, + value: value + }) + } + }, + REMOVE_DICT: (state, key) => { + try { + for (let i = 0; i < state.dict.length; i++) { + if (state.dict[i].key == key) { + state.dict.splice(i, i) + return true + } + } + } catch (e) { + } + }, + CLEAN_DICT: (state) => { + state.dict = new Array() + } +} + +const actions = { + // 设置字典 + setDict({ commit }, data) { + commit('SET_DICT', data) + }, + // 删除字典 + removeDict({ commit }, key) { + commit('REMOVE_DICT', key) + }, + // 清空字典 + cleanDict({ commit }) { + commit('CLEAN_DICT') + } +} + +export default { + namespaced: true, + state, + mutations, + actions +} + diff --git a/custom-ui/src/store/modules/permission.js b/custom-ui/src/store/modules/permission.js new file mode 100644 index 0000000..2287665 --- /dev/null +++ b/custom-ui/src/store/modules/permission.js @@ -0,0 +1,133 @@ +import auth from '@/plugins/auth' +import router, { constantRoutes, dynamicRoutes } from '@/router' +import { getRouters } from '@/api/menu' +import Layout from '@/layout/index' +import ParentView from '@/components/ParentView' +import InnerLink from '@/layout/components/InnerLink' + +const permission = { + state: { + routes: [], + addRoutes: [], + defaultRoutes: [], + topbarRouters: [], + sidebarRouters: [] + }, + mutations: { + SET_ROUTES: (state, routes) => { + state.addRoutes = routes + state.routes = constantRoutes.concat(routes) + }, + SET_DEFAULT_ROUTES: (state, routes) => { + state.defaultRoutes = constantRoutes.concat(routes) + }, + SET_TOPBAR_ROUTES: (state, routes) => { + state.topbarRouters = routes + }, + SET_SIDEBAR_ROUTERS: (state, routes) => { + state.sidebarRouters = routes + }, + }, + actions: { + // 生成路由 + GenerateRoutes({ commit }) { + return new Promise(resolve => { + // 向后端请求路由数据 + getRouters().then(res => { + const sdata = JSON.parse(JSON.stringify(res.data)) + const rdata = JSON.parse(JSON.stringify(res.data)) + const sidebarRoutes = filterAsyncRouter(sdata) + const rewriteRoutes = filterAsyncRouter(rdata, false, true) + const asyncRoutes = filterDynamicRoutes(dynamicRoutes); + rewriteRoutes.push({ path: '*', redirect: '/404', hidden: true }) + router.addRoutes(asyncRoutes); + commit('SET_ROUTES', rewriteRoutes) + commit('SET_SIDEBAR_ROUTERS', constantRoutes.concat(sidebarRoutes)) + commit('SET_DEFAULT_ROUTES', sidebarRoutes) + commit('SET_TOPBAR_ROUTES', sidebarRoutes) + resolve(rewriteRoutes) + }) + }) + } + } +} + +// 遍历后台传来的路由字符串,转换为组件对象 +function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) { + return asyncRouterMap.filter(route => { + if (type && route.children) { + route.children = filterChildren(route.children) + } + if (route.component) { + // Layout ParentView 组件特殊处理 + if (route.component === 'Layout') { + route.component = Layout + } else if (route.component === 'ParentView') { + route.component = ParentView + } else if (route.component === 'InnerLink') { + route.component = InnerLink + } else { + route.component = loadView(route.component) + } + } + if (route.children != null && route.children && route.children.length) { + route.children = filterAsyncRouter(route.children, route, type) + } else { + delete route['children'] + delete route['redirect'] + } + return true + }) +} + +function filterChildren(childrenMap, lastRouter = false) { + var children = [] + childrenMap.forEach((el, index) => { + if (el.children && el.children.length) { + if (el.component === 'ParentView' && !lastRouter) { + el.children.forEach(c => { + c.path = el.path + '/' + c.path + if (c.children && c.children.length) { + children = children.concat(filterChildren(c.children, c)) + return + } + children.push(c) + }) + return + } + } + if (lastRouter) { + el.path = lastRouter.path + '/' + el.path + } + children = children.concat(el) + }) + return children +} + +// 动态路由遍历,验证是否具备权限 +export function filterDynamicRoutes(routes) { + const res = [] + routes.forEach(route => { + if (route.permissions) { + if (auth.hasPermiOr(route.permissions)) { + res.push(route) + } + } else if (route.roles) { + if (auth.hasRoleOr(route.roles)) { + res.push(route) + } + } + }) + return res +} + +export const loadView = (view) => { + if (process.env.NODE_ENV === 'development') { + return (resolve) => require([`@/views/${view}`], resolve) + } else { + // 使用 import 实现生产环境的路由懒加载 + return () => import(`@/views/${view}`) + } +} + +export default permission diff --git a/custom-ui/src/store/modules/settings.js b/custom-ui/src/store/modules/settings.js new file mode 100644 index 0000000..2455a1e --- /dev/null +++ b/custom-ui/src/store/modules/settings.js @@ -0,0 +1,42 @@ +import defaultSettings from '@/settings' + +const { sideTheme, showSettings, topNav, tagsView, fixedHeader, sidebarLogo, dynamicTitle } = defaultSettings + +const storageSetting = JSON.parse(localStorage.getItem('layout-setting')) || '' +const state = { + title: '', + theme: storageSetting.theme || '#409EFF', + sideTheme: storageSetting.sideTheme || sideTheme, + showSettings: showSettings, + topNav: storageSetting.topNav === undefined ? topNav : storageSetting.topNav, + tagsView: storageSetting.tagsView === undefined ? tagsView : storageSetting.tagsView, + fixedHeader: storageSetting.fixedHeader === undefined ? fixedHeader : storageSetting.fixedHeader, + sidebarLogo: storageSetting.sidebarLogo === undefined ? sidebarLogo : storageSetting.sidebarLogo, + dynamicTitle: storageSetting.dynamicTitle === undefined ? dynamicTitle : storageSetting.dynamicTitle +} +const mutations = { + CHANGE_SETTING: (state, { key, value }) => { + if (state.hasOwnProperty(key)) { + state[key] = value + } + } +} + +const actions = { + // 修改布局设置 + changeSetting({ commit }, data) { + commit('CHANGE_SETTING', data) + }, + // 设置网页标题 + setTitle({ commit }, title) { + state.title = title + } +} + +export default { + namespaced: true, + state, + mutations, + actions +} + diff --git a/custom-ui/src/store/modules/tagsView.js b/custom-ui/src/store/modules/tagsView.js new file mode 100644 index 0000000..5fc011c --- /dev/null +++ b/custom-ui/src/store/modules/tagsView.js @@ -0,0 +1,228 @@ +const state = { + visitedViews: [], + cachedViews: [], + iframeViews: [] +} + +const mutations = { + ADD_IFRAME_VIEW: (state, view) => { + if (state.iframeViews.some(v => v.path === view.path)) return + state.iframeViews.push( + Object.assign({}, view, { + title: view.meta.title || 'no-name' + }) + ) + }, + ADD_VISITED_VIEW: (state, view) => { + if (state.visitedViews.some(v => v.path === view.path)) return + state.visitedViews.push( + Object.assign({}, view, { + title: view.meta.title || 'no-name' + }) + ) + }, + ADD_CACHED_VIEW: (state, view) => { + if (state.cachedViews.includes(view.name)) return + if (view.meta && !view.meta.noCache) { + state.cachedViews.push(view.name) + } + }, + DEL_VISITED_VIEW: (state, view) => { + for (const [i, v] of state.visitedViews.entries()) { + if (v.path === view.path) { + state.visitedViews.splice(i, 1) + break + } + } + state.iframeViews = state.iframeViews.filter(item => item.path !== view.path) + }, + DEL_IFRAME_VIEW: (state, view) => { + state.iframeViews = state.iframeViews.filter(item => item.path !== view.path) + }, + DEL_CACHED_VIEW: (state, view) => { + const index = state.cachedViews.indexOf(view.name) + index > -1 && state.cachedViews.splice(index, 1) + }, + + DEL_OTHERS_VISITED_VIEWS: (state, view) => { + state.visitedViews = state.visitedViews.filter(v => { + return v.meta.affix || v.path === view.path + }) + state.iframeViews = state.iframeViews.filter(item => item.path === view.path) + }, + DEL_OTHERS_CACHED_VIEWS: (state, view) => { + const index = state.cachedViews.indexOf(view.name) + if (index > -1) { + state.cachedViews = state.cachedViews.slice(index, index + 1) + } else { + state.cachedViews = [] + } + }, + DEL_ALL_VISITED_VIEWS: state => { + // keep affix tags + const affixTags = state.visitedViews.filter(tag => tag.meta.affix) + state.visitedViews = affixTags + state.iframeViews = [] + }, + DEL_ALL_CACHED_VIEWS: state => { + state.cachedViews = [] + }, + UPDATE_VISITED_VIEW: (state, view) => { + for (let v of state.visitedViews) { + if (v.path === view.path) { + v = Object.assign(v, view) + break + } + } + }, + DEL_RIGHT_VIEWS: (state, view) => { + const index = state.visitedViews.findIndex(v => v.path === view.path) + if (index === -1) { + return + } + state.visitedViews = state.visitedViews.filter((item, idx) => { + if (idx <= index || (item.meta && item.meta.affix)) { + return true + } + const i = state.cachedViews.indexOf(item.name) + if (i > -1) { + state.cachedViews.splice(i, 1) + } + if(item.meta.link) { + const fi = state.iframeViews.findIndex(v => v.path === item.path) + state.iframeViews.splice(fi, 1) + } + return false + }) + }, + DEL_LEFT_VIEWS: (state, view) => { + const index = state.visitedViews.findIndex(v => v.path === view.path) + if (index === -1) { + return + } + state.visitedViews = state.visitedViews.filter((item, idx) => { + if (idx >= index || (item.meta && item.meta.affix)) { + return true + } + const i = state.cachedViews.indexOf(item.name) + if (i > -1) { + state.cachedViews.splice(i, 1) + } + if(item.meta.link) { + const fi = state.iframeViews.findIndex(v => v.path === item.path) + state.iframeViews.splice(fi, 1) + } + return false + }) + } +} + +const actions = { + addView({ dispatch }, view) { + dispatch('addVisitedView', view) + dispatch('addCachedView', view) + }, + addIframeView({ commit }, view) { + commit('ADD_IFRAME_VIEW', view) + }, + addVisitedView({ commit }, view) { + commit('ADD_VISITED_VIEW', view) + }, + addCachedView({ commit }, view) { + commit('ADD_CACHED_VIEW', view) + }, + delView({ dispatch, state }, view) { + return new Promise(resolve => { + dispatch('delVisitedView', view) + dispatch('delCachedView', view) + resolve({ + visitedViews: [...state.visitedViews], + cachedViews: [...state.cachedViews] + }) + }) + }, + delVisitedView({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_VISITED_VIEW', view) + resolve([...state.visitedViews]) + }) + }, + delIframeView({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_IFRAME_VIEW', view) + resolve([...state.iframeViews]) + }) + }, + delCachedView({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_CACHED_VIEW', view) + resolve([...state.cachedViews]) + }) + }, + delOthersViews({ dispatch, state }, view) { + return new Promise(resolve => { + dispatch('delOthersVisitedViews', view) + dispatch('delOthersCachedViews', view) + resolve({ + visitedViews: [...state.visitedViews], + cachedViews: [...state.cachedViews] + }) + }) + }, + delOthersVisitedViews({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_OTHERS_VISITED_VIEWS', view) + resolve([...state.visitedViews]) + }) + }, + delOthersCachedViews({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_OTHERS_CACHED_VIEWS', view) + resolve([...state.cachedViews]) + }) + }, + delAllViews({ dispatch, state }, view) { + return new Promise(resolve => { + dispatch('delAllVisitedViews', view) + dispatch('delAllCachedViews', view) + resolve({ + visitedViews: [...state.visitedViews], + cachedViews: [...state.cachedViews] + }) + }) + }, + delAllVisitedViews({ commit, state }) { + return new Promise(resolve => { + commit('DEL_ALL_VISITED_VIEWS') + resolve([...state.visitedViews]) + }) + }, + delAllCachedViews({ commit, state }) { + return new Promise(resolve => { + commit('DEL_ALL_CACHED_VIEWS') + resolve([...state.cachedViews]) + }) + }, + updateVisitedView({ commit }, view) { + commit('UPDATE_VISITED_VIEW', view) + }, + delRightTags({ commit }, view) { + return new Promise(resolve => { + commit('DEL_RIGHT_VIEWS', view) + resolve([...state.visitedViews]) + }) + }, + delLeftTags({ commit }, view) { + return new Promise(resolve => { + commit('DEL_LEFT_VIEWS', view) + resolve([...state.visitedViews]) + }) + }, +} + +export default { + namespaced: true, + state, + mutations, + actions +} diff --git a/custom-ui/src/store/modules/user.js b/custom-ui/src/store/modules/user.js new file mode 100644 index 0000000..ab0a6fe --- /dev/null +++ b/custom-ui/src/store/modules/user.js @@ -0,0 +1,96 @@ +import { login, logout, getInfo } from '@/api/login' +import { getToken, setToken, removeToken } from '@/utils/auth' + +const user = { + state: { + token: getToken(), + name: '', + avatar: '', + roles: [], + permissions: [] + }, + + mutations: { + SET_TOKEN: (state, token) => { + state.token = token + }, + SET_NAME: (state, name) => { + state.name = name + }, + SET_AVATAR: (state, avatar) => { + state.avatar = avatar + }, + SET_ROLES: (state, roles) => { + state.roles = roles + }, + SET_PERMISSIONS: (state, permissions) => { + state.permissions = permissions + } + }, + + actions: { + // 登录 + Login({ commit }, userInfo) { + const username = userInfo.username.trim() + const password = userInfo.password + const code = userInfo.code + const uuid = userInfo.uuid + return new Promise((resolve, reject) => { + login(username, password, code, uuid).then(res => { + setToken(res.token) + commit('SET_TOKEN', res.token) + resolve() + }).catch(error => { + reject(error) + }) + }) + }, + + // 获取用户信息 + GetInfo({ commit, state }) { + return new Promise((resolve, reject) => { + getInfo().then(res => { + const user = res.user + const avatar = (user.avatar == "" || user.avatar == null) ? require("@/assets/images/profile.jpg") : process.env.VUE_APP_BASE_API + user.avatar; + if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组 + commit('SET_ROLES', res.roles) + commit('SET_PERMISSIONS', res.permissions) + } else { + commit('SET_ROLES', ['ROLE_DEFAULT']) + } + commit('SET_NAME', user.userName) + commit('SET_AVATAR', avatar) + resolve(res) + }).catch(error => { + reject(error) + }) + }) + }, + + // 退出系统 + LogOut({ commit, state }) { + return new Promise((resolve, reject) => { + logout(state.token).then(() => { + commit('SET_TOKEN', '') + commit('SET_ROLES', []) + commit('SET_PERMISSIONS', []) + removeToken() + resolve() + }).catch(error => { + reject(error) + }) + }) + }, + + // 前端 登出 + FedLogOut({ commit }) { + return new Promise(resolve => { + commit('SET_TOKEN', '') + removeToken() + resolve() + }) + } + } +} + +export default user diff --git a/custom-ui/src/utils/auth.js b/custom-ui/src/utils/auth.js new file mode 100644 index 0000000..08a43d6 --- /dev/null +++ b/custom-ui/src/utils/auth.js @@ -0,0 +1,15 @@ +import Cookies from 'js-cookie' + +const TokenKey = 'Admin-Token' + +export function getToken() { + return Cookies.get(TokenKey) +} + +export function setToken(token) { + return Cookies.set(TokenKey, token) +} + +export function removeToken() { + return Cookies.remove(TokenKey) +} diff --git a/custom-ui/src/utils/dict/Dict.js b/custom-ui/src/utils/dict/Dict.js new file mode 100644 index 0000000..104bd6e --- /dev/null +++ b/custom-ui/src/utils/dict/Dict.js @@ -0,0 +1,82 @@ +import Vue from 'vue' +import { mergeRecursive } from "@/utils/ruoyi"; +import DictMeta from './DictMeta' +import DictData from './DictData' + +const DEFAULT_DICT_OPTIONS = { + types: [], +} + +/** + * @classdesc 字典 + * @property {Object} label 标签对象,内部属性名为字典类型名称 + * @property {Object} dict 字段数组,内部属性名为字典类型名称 + * @property {Array.} _dictMetas 字典元数据数组 + */ +export default class Dict { + constructor() { + this.owner = null + this.label = {} + this.type = {} + } + + init(options) { + if (options instanceof Array) { + options = { types: options } + } + const opts = mergeRecursive(DEFAULT_DICT_OPTIONS, options) + if (opts.types === undefined) { + throw new Error('need dict types') + } + const ps = [] + this._dictMetas = opts.types.map(t => DictMeta.parse(t)) + this._dictMetas.forEach(dictMeta => { + const type = dictMeta.type + Vue.set(this.label, type, {}) + Vue.set(this.type, type, []) + if (dictMeta.lazy) { + return + } + ps.push(loadDict(this, dictMeta)) + }) + return Promise.all(ps) + } + + /** + * 重新加载字典 + * @param {String} type 字典类型 + */ + reloadDict(type) { + const dictMeta = this._dictMetas.find(e => e.type === type) + if (dictMeta === undefined) { + return Promise.reject(`the dict meta of ${type} was not found`) + } + return loadDict(this, dictMeta) + } +} + +/** + * 加载字典 + * @param {Dict} dict 字典 + * @param {DictMeta} dictMeta 字典元数据 + * @returns {Promise} + */ +function loadDict(dict, dictMeta) { + return dictMeta.request(dictMeta) + .then(response => { + const type = dictMeta.type + let dicts = dictMeta.responseConverter(response, dictMeta) + if (!(dicts instanceof Array)) { + console.error('the return of responseConverter must be Array.') + dicts = [] + } else if (dicts.filter(d => d instanceof DictData).length !== dicts.length) { + console.error('the type of elements in dicts must be DictData') + dicts = [] + } + dict.type[type].splice(0, Number.MAX_SAFE_INTEGER, ...dicts) + dicts.forEach(d => { + Vue.set(dict.label[type], d.value, d.label) + }) + return dicts + }) +} diff --git a/custom-ui/src/utils/dict/DictConverter.js b/custom-ui/src/utils/dict/DictConverter.js new file mode 100644 index 0000000..0cf5df8 --- /dev/null +++ b/custom-ui/src/utils/dict/DictConverter.js @@ -0,0 +1,17 @@ +import DictOptions from './DictOptions' +import DictData from './DictData' + +export default function(dict, dictMeta) { + const label = determineDictField(dict, dictMeta.labelField, ...DictOptions.DEFAULT_LABEL_FIELDS) + const value = determineDictField(dict, dictMeta.valueField, ...DictOptions.DEFAULT_VALUE_FIELDS) + return new DictData(dict[label], dict[value], dict) +} + +/** + * 确定字典字段 + * @param {DictData} dict + * @param {...String} fields + */ +function determineDictField(dict, ...fields) { + return fields.find(f => Object.prototype.hasOwnProperty.call(dict, f)) +} diff --git a/custom-ui/src/utils/dict/DictData.js b/custom-ui/src/utils/dict/DictData.js new file mode 100644 index 0000000..afc763e --- /dev/null +++ b/custom-ui/src/utils/dict/DictData.js @@ -0,0 +1,13 @@ +/** + * @classdesc 字典数据 + * @property {String} label 标签 + * @property {*} value 标签 + * @property {Object} raw 原始数据 + */ +export default class DictData { + constructor(label, value, raw) { + this.label = label + this.value = value + this.raw = raw + } +} diff --git a/custom-ui/src/utils/dict/DictMeta.js b/custom-ui/src/utils/dict/DictMeta.js new file mode 100644 index 0000000..9779daa --- /dev/null +++ b/custom-ui/src/utils/dict/DictMeta.js @@ -0,0 +1,38 @@ +import { mergeRecursive } from "@/utils/ruoyi"; +import DictOptions from './DictOptions' + +/** + * @classdesc 字典元数据 + * @property {String} type 类型 + * @property {Function} request 请求 + * @property {String} label 标签字段 + * @property {String} value 值字段 + */ +export default class DictMeta { + constructor(options) { + this.type = options.type + this.request = options.request + this.responseConverter = options.responseConverter + this.labelField = options.labelField + this.valueField = options.valueField + this.lazy = options.lazy === true + } +} + + +/** + * 解析字典元数据 + * @param {Object} options + * @returns {DictMeta} + */ +DictMeta.parse= function(options) { + let opts = null + if (typeof options === 'string') { + opts = DictOptions.metas[options] || {} + opts.type = options + } else if (typeof options === 'object') { + opts = options + } + opts = mergeRecursive(DictOptions.metas['*'], opts) + return new DictMeta(opts) +} diff --git a/custom-ui/src/utils/dict/DictOptions.js b/custom-ui/src/utils/dict/DictOptions.js new file mode 100644 index 0000000..338a94e --- /dev/null +++ b/custom-ui/src/utils/dict/DictOptions.js @@ -0,0 +1,51 @@ +import { mergeRecursive } from "@/utils/ruoyi"; +import dictConverter from './DictConverter' + +export const options = { + metas: { + '*': { + /** + * 字典请求,方法签名为function(dictMeta: DictMeta): Promise + */ + request: (dictMeta) => { + console.log(`load dict ${dictMeta.type}`) + return Promise.resolve([]) + }, + /** + * 字典响应数据转换器,方法签名为function(response: Object, dictMeta: DictMeta): DictData + */ + responseConverter, + labelField: 'label', + valueField: 'value', + }, + }, + /** + * 默认标签字段 + */ + DEFAULT_LABEL_FIELDS: ['label', 'name', 'title'], + /** + * 默认值字段 + */ + DEFAULT_VALUE_FIELDS: ['value', 'id', 'uid', 'key'], +} + +/** + * 映射字典 + * @param {Object} response 字典数据 + * @param {DictMeta} dictMeta 字典元数据 + * @returns {DictData} + */ +function responseConverter(response, dictMeta) { + const dicts = response.content instanceof Array ? response.content : response + if (dicts === undefined) { + console.warn(`no dict data of "${dictMeta.type}" found in the response`) + return [] + } + return dicts.map(d => dictConverter(d, dictMeta)) +} + +export function mergeOptions(src) { + mergeRecursive(options, src) +} + +export default options diff --git a/custom-ui/src/utils/dict/index.js b/custom-ui/src/utils/dict/index.js new file mode 100644 index 0000000..215eb9e --- /dev/null +++ b/custom-ui/src/utils/dict/index.js @@ -0,0 +1,33 @@ +import Dict from './Dict' +import { mergeOptions } from './DictOptions' + +export default function(Vue, options) { + mergeOptions(options) + Vue.mixin({ + data() { + if (this.$options === undefined || this.$options.dicts === undefined || this.$options.dicts === null) { + return {} + } + const dict = new Dict() + dict.owner = this + return { + dict + } + }, + created() { + if (!(this.dict instanceof Dict)) { + return + } + options.onCreated && options.onCreated(this.dict) + this.dict.init(this.$options.dicts).then(() => { + options.onReady && options.onReady(this.dict) + this.$nextTick(() => { + this.$emit('dictReady', this.dict) + if (this.$options.methods && this.$options.methods.onDictReady instanceof Function) { + this.$options.methods.onDictReady.call(this, this.dict) + } + }) + }) + }, + }) +} diff --git a/custom-ui/src/utils/errorCode.js b/custom-ui/src/utils/errorCode.js new file mode 100644 index 0000000..d2111ee --- /dev/null +++ b/custom-ui/src/utils/errorCode.js @@ -0,0 +1,6 @@ +export default { + '401': '认证失败,无法访问系统资源', + '403': '当前操作没有权限', + '404': '访问资源不存在', + 'default': '系统未知错误,请反馈给管理员' +} diff --git a/custom-ui/src/utils/generator/config.js b/custom-ui/src/utils/generator/config.js new file mode 100644 index 0000000..7abf227 --- /dev/null +++ b/custom-ui/src/utils/generator/config.js @@ -0,0 +1,438 @@ +export const formConf = { + formRef: 'elForm', + formModel: 'formData', + size: 'medium', + labelPosition: 'right', + labelWidth: 100, + formRules: 'rules', + gutter: 15, + disabled: false, + span: 24, + formBtns: true +} + +export const inputComponents = [ + { + label: '单行文本', + tag: 'el-input', + tagIcon: 'input', + placeholder: '请输入', + defaultValue: undefined, + span: 24, + labelWidth: null, + style: { width: '100%' }, + clearable: true, + prepend: '', + append: '', + 'prefix-icon': '', + 'suffix-icon': '', + maxlength: null, + 'show-word-limit': false, + readonly: false, + disabled: false, + required: true, + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/input' + }, + { + label: '多行文本', + tag: 'el-input', + tagIcon: 'textarea', + type: 'textarea', + placeholder: '请输入', + defaultValue: undefined, + span: 24, + labelWidth: null, + autosize: { + minRows: 4, + maxRows: 4 + }, + style: { width: '100%' }, + maxlength: null, + 'show-word-limit': false, + readonly: false, + disabled: false, + required: true, + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/input' + }, + { + label: '密码', + tag: 'el-input', + tagIcon: 'password', + placeholder: '请输入', + defaultValue: undefined, + span: 24, + 'show-password': true, + labelWidth: null, + style: { width: '100%' }, + clearable: true, + prepend: '', + append: '', + 'prefix-icon': '', + 'suffix-icon': '', + maxlength: null, + 'show-word-limit': false, + readonly: false, + disabled: false, + required: true, + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/input' + }, + { + label: '计数器', + tag: 'el-input-number', + tagIcon: 'number', + placeholder: '', + defaultValue: undefined, + span: 24, + labelWidth: null, + min: undefined, + max: undefined, + step: undefined, + 'step-strictly': false, + precision: undefined, + 'controls-position': '', + disabled: false, + required: true, + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/input-number' + } +] + +export const selectComponents = [ + { + label: '下拉选择', + tag: 'el-select', + tagIcon: 'select', + placeholder: '请选择', + defaultValue: undefined, + span: 24, + labelWidth: null, + style: { width: '100%' }, + clearable: true, + disabled: false, + required: true, + filterable: false, + multiple: false, + options: [{ + label: '选项一', + value: 1 + }, { + label: '选项二', + value: 2 + }], + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/select' + }, + { + label: '级联选择', + tag: 'el-cascader', + tagIcon: 'cascader', + placeholder: '请选择', + defaultValue: [], + span: 24, + labelWidth: null, + style: { width: '100%' }, + props: { + props: { + multiple: false + } + }, + 'show-all-levels': true, + disabled: false, + clearable: true, + filterable: false, + required: true, + options: [{ + id: 1, + value: 1, + label: '选项1', + children: [{ + id: 2, + value: 2, + label: '选项1-1' + }] + }], + dataType: 'dynamic', + labelKey: 'label', + valueKey: 'value', + childrenKey: 'children', + separator: '/', + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/cascader' + }, + { + label: '单选框组', + tag: 'el-radio-group', + tagIcon: 'radio', + defaultValue: undefined, + span: 24, + labelWidth: null, + style: {}, + optionType: 'default', + border: false, + size: 'medium', + disabled: false, + required: true, + options: [{ + label: '选项一', + value: 1 + }, { + label: '选项二', + value: 2 + }], + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/radio' + }, + { + label: '多选框组', + tag: 'el-checkbox-group', + tagIcon: 'checkbox', + defaultValue: [], + span: 24, + labelWidth: null, + style: {}, + optionType: 'default', + border: false, + size: 'medium', + disabled: false, + required: true, + options: [{ + label: '选项一', + value: 1 + }, { + label: '选项二', + value: 2 + }], + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/checkbox' + }, + { + label: '开关', + tag: 'el-switch', + tagIcon: 'switch', + defaultValue: false, + span: 24, + labelWidth: null, + style: {}, + disabled: false, + required: true, + 'active-text': '', + 'inactive-text': '', + 'active-color': null, + 'inactive-color': null, + 'active-value': true, + 'inactive-value': false, + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/switch' + }, + { + label: '滑块', + tag: 'el-slider', + tagIcon: 'slider', + defaultValue: null, + span: 24, + labelWidth: null, + disabled: false, + required: true, + min: 0, + max: 100, + step: 1, + 'show-stops': false, + range: false, + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/slider' + }, + { + label: '时间选择', + tag: 'el-time-picker', + tagIcon: 'time', + placeholder: '请选择', + defaultValue: null, + span: 24, + labelWidth: null, + style: { width: '100%' }, + disabled: false, + clearable: true, + required: true, + 'picker-options': { + selectableRange: '00:00:00-23:59:59' + }, + format: 'HH:mm:ss', + 'value-format': 'HH:mm:ss', + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/time-picker' + }, + { + label: '时间范围', + tag: 'el-time-picker', + tagIcon: 'time-range', + defaultValue: null, + span: 24, + labelWidth: null, + style: { width: '100%' }, + disabled: false, + clearable: true, + required: true, + 'is-range': true, + 'range-separator': '至', + 'start-placeholder': '开始时间', + 'end-placeholder': '结束时间', + format: 'HH:mm:ss', + 'value-format': 'HH:mm:ss', + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/time-picker' + }, + { + label: '日期选择', + tag: 'el-date-picker', + tagIcon: 'date', + placeholder: '请选择', + defaultValue: null, + type: 'date', + span: 24, + labelWidth: null, + style: { width: '100%' }, + disabled: false, + clearable: true, + required: true, + format: 'yyyy-MM-dd', + 'value-format': 'yyyy-MM-dd', + readonly: false, + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/date-picker' + }, + { + label: '日期范围', + tag: 'el-date-picker', + tagIcon: 'date-range', + defaultValue: null, + span: 24, + labelWidth: null, + style: { width: '100%' }, + type: 'daterange', + 'range-separator': '至', + 'start-placeholder': '开始日期', + 'end-placeholder': '结束日期', + disabled: false, + clearable: true, + required: true, + format: 'yyyy-MM-dd', + 'value-format': 'yyyy-MM-dd', + readonly: false, + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/date-picker' + }, + { + label: '评分', + tag: 'el-rate', + tagIcon: 'rate', + defaultValue: 0, + span: 24, + labelWidth: null, + style: {}, + max: 5, + 'allow-half': false, + 'show-text': false, + 'show-score': false, + disabled: false, + required: true, + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/rate' + }, + { + label: '颜色选择', + tag: 'el-color-picker', + tagIcon: 'color', + defaultValue: null, + labelWidth: null, + 'show-alpha': false, + 'color-format': '', + disabled: false, + required: true, + size: 'medium', + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/color-picker' + }, + { + label: '上传', + tag: 'el-upload', + tagIcon: 'upload', + action: 'https://jsonplaceholder.typicode.com/posts/', + defaultValue: null, + labelWidth: null, + disabled: false, + required: true, + accept: '', + name: 'file', + 'auto-upload': true, + showTip: false, + buttonText: '点击上传', + fileSize: 2, + sizeUnit: 'MB', + 'list-type': 'text', + multiple: false, + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/upload' + } +] + +export const layoutComponents = [ + { + layout: 'rowFormItem', + tagIcon: 'row', + type: 'default', + justify: 'start', + align: 'top', + label: '行容器', + layoutTree: true, + children: [], + document: 'https://element.eleme.cn/#/zh-CN/component/layout' + }, + { + layout: 'colFormItem', + label: '按钮', + changeTag: true, + labelWidth: null, + tag: 'el-button', + tagIcon: 'button', + span: 24, + default: '主要按钮', + type: 'primary', + icon: 'el-icon-search', + size: 'medium', + disabled: false, + document: 'https://element.eleme.cn/#/zh-CN/component/button' + } +] + +// 组件rule的触发方式,无触发方式的组件不生成rule +export const trigger = { + 'el-input': 'blur', + 'el-input-number': 'blur', + 'el-select': 'change', + 'el-radio-group': 'change', + 'el-checkbox-group': 'change', + 'el-cascader': 'change', + 'el-time-picker': 'change', + 'el-date-picker': 'change', + 'el-rate': 'change' +} diff --git a/custom-ui/src/utils/generator/css.js b/custom-ui/src/utils/generator/css.js new file mode 100644 index 0000000..c1c62e6 --- /dev/null +++ b/custom-ui/src/utils/generator/css.js @@ -0,0 +1,18 @@ +const styles = { + 'el-rate': '.el-rate{display: inline-block; vertical-align: text-top;}', + 'el-upload': '.el-upload__tip{line-height: 1.2;}' +} + +function addCss(cssList, el) { + const css = styles[el.tag] + css && cssList.indexOf(css) === -1 && cssList.push(css) + if (el.children) { + el.children.forEach(el2 => addCss(cssList, el2)) + } +} + +export function makeUpCss(conf) { + const cssList = [] + conf.fields.forEach(el => addCss(cssList, el)) + return cssList.join('\n') +} diff --git a/custom-ui/src/utils/generator/drawingDefault.js b/custom-ui/src/utils/generator/drawingDefault.js new file mode 100644 index 0000000..09f133c --- /dev/null +++ b/custom-ui/src/utils/generator/drawingDefault.js @@ -0,0 +1,29 @@ +export default [ + { + layout: 'colFormItem', + tagIcon: 'input', + label: '手机号', + vModel: 'mobile', + formId: 6, + tag: 'el-input', + placeholder: '请输入手机号', + defaultValue: '', + span: 24, + style: { width: '100%' }, + clearable: true, + prepend: '', + append: '', + 'prefix-icon': 'el-icon-mobile', + 'suffix-icon': '', + maxlength: 11, + 'show-word-limit': true, + readonly: false, + disabled: false, + required: true, + changeTag: true, + regList: [{ + pattern: '/^1(3|4|5|7|8|9)\\d{9}$/', + message: '手机号格式错误' + }] + } +] diff --git a/custom-ui/src/utils/generator/html.js b/custom-ui/src/utils/generator/html.js new file mode 100644 index 0000000..9bcc536 --- /dev/null +++ b/custom-ui/src/utils/generator/html.js @@ -0,0 +1,359 @@ +/* eslint-disable max-len */ +import { trigger } from './config' + +let confGlobal +let someSpanIsNot24 + +export function dialogWrapper(str) { + return ` + ${str} +

+ ` +} + +export function vueTemplate(str) { + return `` +} + +export function vueScript(str) { + return `` +} + +export function cssStyle(cssStr) { + return `` +} + +function buildFormTemplate(conf, child, type) { + let labelPosition = '' + if (conf.labelPosition !== 'right') { + labelPosition = `label-position="${conf.labelPosition}"` + } + const disabled = conf.disabled ? `:disabled="${conf.disabled}"` : '' + let str = ` + ${child} + ${buildFromBtns(conf, type)} + ` + if (someSpanIsNot24) { + str = ` + ${str} + ` + } + return str +} + +function buildFromBtns(conf, type) { + let str = '' + if (conf.formBtns && type === 'file') { + str = ` + 提交 + 重置 + ` + if (someSpanIsNot24) { + str = ` + ${str} + ` + } + } + return str +} + +// span不为24的用el-col包裹 +function colWrapper(element, str) { + if (someSpanIsNot24 || element.span !== 24) { + return ` + ${str} + ` + } + return str +} + +const layouts = { + colFormItem(element) { + let labelWidth = '' + if (element.labelWidth && element.labelWidth !== confGlobal.labelWidth) { + labelWidth = `label-width="${element.labelWidth}px"` + } + const required = !trigger[element.tag] && element.required ? 'required' : '' + const tagDom = tags[element.tag] ? tags[element.tag](element) : null + let str = ` + ${tagDom} + ` + str = colWrapper(element, str) + return str + }, + rowFormItem(element) { + const type = element.type === 'default' ? '' : `type="${element.type}"` + const justify = element.type === 'default' ? '' : `justify="${element.justify}"` + const align = element.type === 'default' ? '' : `align="${element.align}"` + const gutter = element.gutter ? `gutter="${element.gutter}"` : '' + const children = element.children.map(el => layouts[el.layout](el)) + let str = ` + ${children.join('\n')} + ` + str = colWrapper(element, str) + return str + } +} + +const tags = { + 'el-button': el => { + const { + tag, disabled + } = attrBuilder(el) + const type = el.type ? `type="${el.type}"` : '' + const icon = el.icon ? `icon="${el.icon}"` : '' + const size = el.size ? `size="${el.size}"` : '' + let child = buildElButtonChild(el) + + if (child) child = `\n${child}\n` // 换行 + return `<${el.tag} ${type} ${icon} ${size} ${disabled}>${child}` + }, + 'el-input': el => { + const { + disabled, vModel, clearable, placeholder, width + } = attrBuilder(el) + const maxlength = el.maxlength ? `:maxlength="${el.maxlength}"` : '' + const showWordLimit = el['show-word-limit'] ? 'show-word-limit' : '' + const readonly = el.readonly ? 'readonly' : '' + const prefixIcon = el['prefix-icon'] ? `prefix-icon='${el['prefix-icon']}'` : '' + const suffixIcon = el['suffix-icon'] ? `suffix-icon='${el['suffix-icon']}'` : '' + const showPassword = el['show-password'] ? 'show-password' : '' + const type = el.type ? `type="${el.type}"` : '' + const autosize = el.autosize && el.autosize.minRows + ? `:autosize="{minRows: ${el.autosize.minRows}, maxRows: ${el.autosize.maxRows}}"` + : '' + let child = buildElInputChild(el) + + if (child) child = `\n${child}\n` // 换行 + return `<${el.tag} ${vModel} ${type} ${placeholder} ${maxlength} ${showWordLimit} ${readonly} ${disabled} ${clearable} ${prefixIcon} ${suffixIcon} ${showPassword} ${autosize} ${width}>${child}` + }, + 'el-input-number': el => { + const { disabled, vModel, placeholder } = attrBuilder(el) + const controlsPosition = el['controls-position'] ? `controls-position=${el['controls-position']}` : '' + const min = el.min ? `:min='${el.min}'` : '' + const max = el.max ? `:max='${el.max}'` : '' + const step = el.step ? `:step='${el.step}'` : '' + const stepStrictly = el['step-strictly'] ? 'step-strictly' : '' + const precision = el.precision ? `:precision='${el.precision}'` : '' + + return `<${el.tag} ${vModel} ${placeholder} ${step} ${stepStrictly} ${precision} ${controlsPosition} ${min} ${max} ${disabled}>` + }, + 'el-select': el => { + const { + disabled, vModel, clearable, placeholder, width + } = attrBuilder(el) + const filterable = el.filterable ? 'filterable' : '' + const multiple = el.multiple ? 'multiple' : '' + let child = buildElSelectChild(el) + + if (child) child = `\n${child}\n` // 换行 + return `<${el.tag} ${vModel} ${placeholder} ${disabled} ${multiple} ${filterable} ${clearable} ${width}>${child}` + }, + 'el-radio-group': el => { + const { disabled, vModel } = attrBuilder(el) + const size = `size="${el.size}"` + let child = buildElRadioGroupChild(el) + + if (child) child = `\n${child}\n` // 换行 + return `<${el.tag} ${vModel} ${size} ${disabled}>${child}` + }, + 'el-checkbox-group': el => { + const { disabled, vModel } = attrBuilder(el) + const size = `size="${el.size}"` + const min = el.min ? `:min="${el.min}"` : '' + const max = el.max ? `:max="${el.max}"` : '' + let child = buildElCheckboxGroupChild(el) + + if (child) child = `\n${child}\n` // 换行 + return `<${el.tag} ${vModel} ${min} ${max} ${size} ${disabled}>${child}` + }, + 'el-switch': el => { + const { disabled, vModel } = attrBuilder(el) + const activeText = el['active-text'] ? `active-text="${el['active-text']}"` : '' + const inactiveText = el['inactive-text'] ? `inactive-text="${el['inactive-text']}"` : '' + const activeColor = el['active-color'] ? `active-color="${el['active-color']}"` : '' + const inactiveColor = el['inactive-color'] ? `inactive-color="${el['inactive-color']}"` : '' + const activeValue = el['active-value'] !== true ? `:active-value='${JSON.stringify(el['active-value'])}'` : '' + const inactiveValue = el['inactive-value'] !== false ? `:inactive-value='${JSON.stringify(el['inactive-value'])}'` : '' + + return `<${el.tag} ${vModel} ${activeText} ${inactiveText} ${activeColor} ${inactiveColor} ${activeValue} ${inactiveValue} ${disabled}>` + }, + 'el-cascader': el => { + const { + disabled, vModel, clearable, placeholder, width + } = attrBuilder(el) + const options = el.options ? `:options="${el.vModel}Options"` : '' + const props = el.props ? `:props="${el.vModel}Props"` : '' + const showAllLevels = el['show-all-levels'] ? '' : ':show-all-levels="false"' + const filterable = el.filterable ? 'filterable' : '' + const separator = el.separator === '/' ? '' : `separator="${el.separator}"` + + return `<${el.tag} ${vModel} ${options} ${props} ${width} ${showAllLevels} ${placeholder} ${separator} ${filterable} ${clearable} ${disabled}>` + }, + 'el-slider': el => { + const { disabled, vModel } = attrBuilder(el) + const min = el.min ? `:min='${el.min}'` : '' + const max = el.max ? `:max='${el.max}'` : '' + const step = el.step ? `:step='${el.step}'` : '' + const range = el.range ? 'range' : '' + const showStops = el['show-stops'] ? `:show-stops="${el['show-stops']}"` : '' + + return `<${el.tag} ${min} ${max} ${step} ${vModel} ${range} ${showStops} ${disabled}>` + }, + 'el-time-picker': el => { + const { + disabled, vModel, clearable, placeholder, width + } = attrBuilder(el) + const startPlaceholder = el['start-placeholder'] ? `start-placeholder="${el['start-placeholder']}"` : '' + const endPlaceholder = el['end-placeholder'] ? `end-placeholder="${el['end-placeholder']}"` : '' + const rangeSeparator = el['range-separator'] ? `range-separator="${el['range-separator']}"` : '' + const isRange = el['is-range'] ? 'is-range' : '' + const format = el.format ? `format="${el.format}"` : '' + const valueFormat = el['value-format'] ? `value-format="${el['value-format']}"` : '' + const pickerOptions = el['picker-options'] ? `:picker-options='${JSON.stringify(el['picker-options'])}'` : '' + + return `<${el.tag} ${vModel} ${isRange} ${format} ${valueFormat} ${pickerOptions} ${width} ${placeholder} ${startPlaceholder} ${endPlaceholder} ${rangeSeparator} ${clearable} ${disabled}>` + }, + 'el-date-picker': el => { + const { + disabled, vModel, clearable, placeholder, width + } = attrBuilder(el) + const startPlaceholder = el['start-placeholder'] ? `start-placeholder="${el['start-placeholder']}"` : '' + const endPlaceholder = el['end-placeholder'] ? `end-placeholder="${el['end-placeholder']}"` : '' + const rangeSeparator = el['range-separator'] ? `range-separator="${el['range-separator']}"` : '' + const format = el.format ? `format="${el.format}"` : '' + const valueFormat = el['value-format'] ? `value-format="${el['value-format']}"` : '' + const type = el.type === 'date' ? '' : `type="${el.type}"` + const readonly = el.readonly ? 'readonly' : '' + + return `<${el.tag} ${type} ${vModel} ${format} ${valueFormat} ${width} ${placeholder} ${startPlaceholder} ${endPlaceholder} ${rangeSeparator} ${clearable} ${readonly} ${disabled}>` + }, + 'el-rate': el => { + const { disabled, vModel } = attrBuilder(el) + const max = el.max ? `:max='${el.max}'` : '' + const allowHalf = el['allow-half'] ? 'allow-half' : '' + const showText = el['show-text'] ? 'show-text' : '' + const showScore = el['show-score'] ? 'show-score' : '' + + return `<${el.tag} ${vModel} ${allowHalf} ${showText} ${showScore} ${disabled}>` + }, + 'el-color-picker': el => { + const { disabled, vModel } = attrBuilder(el) + const size = `size="${el.size}"` + const showAlpha = el['show-alpha'] ? 'show-alpha' : '' + const colorFormat = el['color-format'] ? `color-format="${el['color-format']}"` : '' + + return `<${el.tag} ${vModel} ${size} ${showAlpha} ${colorFormat} ${disabled}>` + }, + 'el-upload': el => { + const disabled = el.disabled ? ':disabled=\'true\'' : '' + const action = el.action ? `:action="${el.vModel}Action"` : '' + const multiple = el.multiple ? 'multiple' : '' + const listType = el['list-type'] !== 'text' ? `list-type="${el['list-type']}"` : '' + const accept = el.accept ? `accept="${el.accept}"` : '' + const name = el.name !== 'file' ? `name="${el.name}"` : '' + const autoUpload = el['auto-upload'] === false ? ':auto-upload="false"' : '' + const beforeUpload = `:before-upload="${el.vModel}BeforeUpload"` + const fileList = `:file-list="${el.vModel}fileList"` + const ref = `ref="${el.vModel}"` + let child = buildElUploadChild(el) + + if (child) child = `\n${child}\n` // 换行 + return `<${el.tag} ${ref} ${fileList} ${action} ${autoUpload} ${multiple} ${beforeUpload} ${listType} ${accept} ${name} ${disabled}>${child}` + } +} + +function attrBuilder(el) { + return { + vModel: `v-model="${confGlobal.formModel}.${el.vModel}"`, + clearable: el.clearable ? 'clearable' : '', + placeholder: el.placeholder ? `placeholder="${el.placeholder}"` : '', + width: el.style && el.style.width ? ':style="{width: \'100%\'}"' : '', + disabled: el.disabled ? ':disabled=\'true\'' : '' + } +} + +// el-buttin 子级 +function buildElButtonChild(conf) { + const children = [] + if (conf.default) { + children.push(conf.default) + } + return children.join('\n') +} + +// el-input innerHTML +function buildElInputChild(conf) { + const children = [] + if (conf.prepend) { + children.push(``) + } + if (conf.append) { + children.push(``) + } + return children.join('\n') +} + +function buildElSelectChild(conf) { + const children = [] + if (conf.options && conf.options.length) { + children.push(``) + } + return children.join('\n') +} + +function buildElRadioGroupChild(conf) { + const children = [] + if (conf.options && conf.options.length) { + const tag = conf.optionType === 'button' ? 'el-radio-button' : 'el-radio' + const border = conf.border ? 'border' : '' + children.push(`<${tag} v-for="(item, index) in ${conf.vModel}Options" :key="index" :label="item.value" :disabled="item.disabled" ${border}>{{item.label}}`) + } + return children.join('\n') +} + +function buildElCheckboxGroupChild(conf) { + const children = [] + if (conf.options && conf.options.length) { + const tag = conf.optionType === 'button' ? 'el-checkbox-button' : 'el-checkbox' + const border = conf.border ? 'border' : '' + children.push(`<${tag} v-for="(item, index) in ${conf.vModel}Options" :key="index" :label="item.value" :disabled="item.disabled" ${border}>{{item.label}}`) + } + return children.join('\n') +} + +function buildElUploadChild(conf) { + const list = [] + if (conf['list-type'] === 'picture-card') list.push('') + else list.push(`${conf.buttonText}`) + if (conf.showTip) list.push(`
只能上传不超过 ${conf.fileSize}${conf.sizeUnit} 的${conf.accept}文件
`) + return list.join('\n') +} + +export function makeUpHtml(conf, type) { + const htmlList = [] + confGlobal = conf + someSpanIsNot24 = conf.fields.some(item => item.span !== 24) + conf.fields.forEach(el => { + htmlList.push(layouts[el.layout](el)) + }) + const htmlStr = htmlList.join('\n') + + let temp = buildFormTemplate(conf, htmlStr, type) + if (type === 'dialog') { + temp = dialogWrapper(temp) + } + confGlobal = null + return temp +} diff --git a/custom-ui/src/utils/generator/icon.json b/custom-ui/src/utils/generator/icon.json new file mode 100644 index 0000000..2d9999a --- /dev/null +++ b/custom-ui/src/utils/generator/icon.json @@ -0,0 +1 @@ +["platform-eleme","eleme","delete-solid","delete","s-tools","setting","user-solid","user","phone","phone-outline","more","more-outline","star-on","star-off","s-goods","goods","warning","warning-outline","question","info","remove","circle-plus","success","error","zoom-in","zoom-out","remove-outline","circle-plus-outline","circle-check","circle-close","s-help","help","minus","plus","check","close","picture","picture-outline","picture-outline-round","upload","upload2","download","camera-solid","camera","video-camera-solid","video-camera","message-solid","bell","s-cooperation","s-order","s-platform","s-fold","s-unfold","s-operation","s-promotion","s-home","s-release","s-ticket","s-management","s-open","s-shop","s-marketing","s-flag","s-comment","s-finance","s-claim","s-custom","s-opportunity","s-data","s-check","s-grid","menu","share","d-caret","caret-left","caret-right","caret-bottom","caret-top","bottom-left","bottom-right","back","right","bottom","top","top-left","top-right","arrow-left","arrow-right","arrow-down","arrow-up","d-arrow-left","d-arrow-right","video-pause","video-play","refresh","refresh-right","refresh-left","finished","sort","sort-up","sort-down","rank","loading","view","c-scale-to-original","date","edit","edit-outline","folder","folder-opened","folder-add","folder-remove","folder-delete","folder-checked","tickets","document-remove","document-delete","document-copy","document-checked","document","document-add","printer","paperclip","takeaway-box","search","monitor","attract","mobile","scissors","umbrella","headset","brush","mouse","coordinate","magic-stick","reading","data-line","data-board","pie-chart","data-analysis","collection-tag","film","suitcase","suitcase-1","receiving","collection","files","notebook-1","notebook-2","toilet-paper","office-building","school","table-lamp","house","no-smoking","smoking","shopping-cart-full","shopping-cart-1","shopping-cart-2","shopping-bag-1","shopping-bag-2","sold-out","sell","present","box","bank-card","money","coin","wallet","discount","price-tag","news","guide","male","female","thumb","cpu","link","connection","open","turn-off","set-up","chat-round","chat-line-round","chat-square","chat-dot-round","chat-dot-square","chat-line-square","message","postcard","position","turn-off-microphone","microphone","close-notification","bangzhu","time","odometer","crop","aim","switch-button","full-screen","copy-document","mic","stopwatch","medal-1","medal","trophy","trophy-1","first-aid-kit","discover","place","location","location-outline","location-information","add-location","delete-location","map-location","alarm-clock","timer","watch-1","watch","lock","unlock","key","service","mobile-phone","bicycle","truck","ship","basketball","football","soccer","baseball","wind-power","light-rain","lightning","heavy-rain","sunrise","sunrise-1","sunset","sunny","cloudy","partly-cloudy","cloudy-and-sunny","moon","moon-night","dish","dish-1","food","chicken","fork-spoon","knife-fork","burger","tableware","sugar","dessert","ice-cream","hot-water","water-cup","coffee-cup","cold-drink","goblet","goblet-full","goblet-square","goblet-square-full","refrigerator","grape","watermelon","cherry","apple","pear","orange","coffee","ice-tea","ice-drink","milk-tea","potato-strips","lollipop","ice-cream-square","ice-cream-round"] \ No newline at end of file diff --git a/custom-ui/src/utils/generator/js.js b/custom-ui/src/utils/generator/js.js new file mode 100644 index 0000000..35e3e21 --- /dev/null +++ b/custom-ui/src/utils/generator/js.js @@ -0,0 +1,236 @@ +import { isArray } from 'util' +import { exportDefault, titleCase } from '@/utils/index' +import { trigger } from './config' + +const units = { + KB: '1024', + MB: '1024 / 1024', + GB: '1024 / 1024 / 1024' +} +let confGlobal +const inheritAttrs = { + file: '', + dialog: 'inheritAttrs: false,' +} + + +export function makeUpJs(conf, type) { + confGlobal = conf = JSON.parse(JSON.stringify(conf)) + const dataList = [] + const ruleList = [] + const optionsList = [] + const propsList = [] + const methodList = mixinMethod(type) + const uploadVarList = [] + + conf.fields.forEach(el => { + buildAttributes(el, dataList, ruleList, optionsList, methodList, propsList, uploadVarList) + }) + + const script = buildexport( + conf, + type, + dataList.join('\n'), + ruleList.join('\n'), + optionsList.join('\n'), + uploadVarList.join('\n'), + propsList.join('\n'), + methodList.join('\n') + ) + confGlobal = null + return script +} + +function buildAttributes(el, dataList, ruleList, optionsList, methodList, propsList, uploadVarList) { + buildData(el, dataList) + buildRules(el, ruleList) + + if (el.options && el.options.length) { + buildOptions(el, optionsList) + if (el.dataType === 'dynamic') { + const model = `${el.vModel}Options` + const options = titleCase(model) + buildOptionMethod(`get${options}`, model, methodList) + } + } + + if (el.props && el.props.props) { + buildProps(el, propsList) + } + + if (el.action && el.tag === 'el-upload') { + uploadVarList.push( + `${el.vModel}Action: '${el.action}', + ${el.vModel}fileList: [],` + ) + methodList.push(buildBeforeUpload(el)) + if (!el['auto-upload']) { + methodList.push(buildSubmitUpload(el)) + } + } + + if (el.children) { + el.children.forEach(el2 => { + buildAttributes(el2, dataList, ruleList, optionsList, methodList, propsList, uploadVarList) + }) + } +} + +function mixinMethod(type) { + const list = []; const + minxins = { + file: confGlobal.formBtns ? { + submitForm: `submitForm() { + this.$refs['${confGlobal.formRef}'].validate(valid => { + if(!valid) return + // TODO 提交表单 + }) + },`, + resetForm: `resetForm() { + this.$refs['${confGlobal.formRef}'].resetFields() + },` + } : null, + dialog: { + onOpen: 'onOpen() {},', + onClose: `onClose() { + this.$refs['${confGlobal.formRef}'].resetFields() + },`, + close: `close() { + this.$emit('update:visible', false) + },`, + handleConfirm: `handleConfirm() { + this.$refs['${confGlobal.formRef}'].validate(valid => { + if(!valid) return + this.close() + }) + },` + } + } + + const methods = minxins[type] + if (methods) { + Object.keys(methods).forEach(key => { + list.push(methods[key]) + }) + } + + return list +} + +function buildData(conf, dataList) { + if (conf.vModel === undefined) return + let defaultValue + if (typeof (conf.defaultValue) === 'string' && !conf.multiple) { + defaultValue = `'${conf.defaultValue}'` + } else { + defaultValue = `${JSON.stringify(conf.defaultValue)}` + } + dataList.push(`${conf.vModel}: ${defaultValue},`) +} + +function buildRules(conf, ruleList) { + if (conf.vModel === undefined) return + const rules = [] + if (trigger[conf.tag]) { + if (conf.required) { + const type = isArray(conf.defaultValue) ? 'type: \'array\',' : '' + let message = isArray(conf.defaultValue) ? `请至少选择一个${conf.vModel}` : conf.placeholder + if (message === undefined) message = `${conf.label}不能为空` + rules.push(`{ required: true, ${type} message: '${message}', trigger: '${trigger[conf.tag]}' }`) + } + if (conf.regList && isArray(conf.regList)) { + conf.regList.forEach(item => { + if (item.pattern) { + rules.push(`{ pattern: ${eval(item.pattern)}, message: '${item.message}', trigger: '${trigger[conf.tag]}' }`) + } + }) + } + ruleList.push(`${conf.vModel}: [${rules.join(',')}],`) + } +} + +function buildOptions(conf, optionsList) { + if (conf.vModel === undefined) return + if (conf.dataType === 'dynamic') { conf.options = [] } + const str = `${conf.vModel}Options: ${JSON.stringify(conf.options)},` + optionsList.push(str) +} + +function buildProps(conf, propsList) { + if (conf.dataType === 'dynamic') { + conf.valueKey !== 'value' && (conf.props.props.value = conf.valueKey) + conf.labelKey !== 'label' && (conf.props.props.label = conf.labelKey) + conf.childrenKey !== 'children' && (conf.props.props.children = conf.childrenKey) + } + const str = `${conf.vModel}Props: ${JSON.stringify(conf.props.props)},` + propsList.push(str) +} + +function buildBeforeUpload(conf) { + const unitNum = units[conf.sizeUnit]; let rightSizeCode = ''; let acceptCode = ''; const + returnList = [] + if (conf.fileSize) { + rightSizeCode = `let isRightSize = file.size / ${unitNum} < ${conf.fileSize} + if(!isRightSize){ + this.$message.error('文件大小超过 ${conf.fileSize}${conf.sizeUnit}') + }` + returnList.push('isRightSize') + } + if (conf.accept) { + acceptCode = `let isAccept = new RegExp('${conf.accept}').test(file.type) + if(!isAccept){ + this.$message.error('应该选择${conf.accept}类型的文件') + }` + returnList.push('isAccept') + } + const str = `${conf.vModel}BeforeUpload(file) { + ${rightSizeCode} + ${acceptCode} + return ${returnList.join('&&')} + },` + return returnList.length ? str : '' +} + +function buildSubmitUpload(conf) { + const str = `submitUpload() { + this.$refs['${conf.vModel}'].submit() + },` + return str +} + +function buildOptionMethod(methodName, model, methodList) { + const str = `${methodName}() { + // TODO 发起请求获取数据 + this.${model} + },` + methodList.push(str) +} + +function buildexport(conf, type, data, rules, selectOptions, uploadVar, props, methods) { + const str = `${exportDefault}{ + ${inheritAttrs[type]} + components: {}, + props: [], + data () { + return { + ${conf.formModel}: { + ${data} + }, + ${conf.formRules}: { + ${rules} + }, + ${uploadVar} + ${selectOptions} + ${props} + } + }, + computed: {}, + watch: {}, + created () {}, + mounted () {}, + methods: { + ${methods} + } +}` + return str +} diff --git a/custom-ui/src/utils/generator/render.js b/custom-ui/src/utils/generator/render.js new file mode 100644 index 0000000..e8640f0 --- /dev/null +++ b/custom-ui/src/utils/generator/render.js @@ -0,0 +1,126 @@ +import { makeMap } from '@/utils/index' + +// 参考https://github.com/vuejs/vue/blob/v2.6.10/src/platforms/web/server/util.js +const isAttr = makeMap( + 'accept,accept-charset,accesskey,action,align,alt,async,autocomplete,' + + 'autofocus,autoplay,autosave,bgcolor,border,buffered,challenge,charset,' + + 'checked,cite,class,code,codebase,color,cols,colspan,content,http-equiv,' + + 'name,contenteditable,contextmenu,controls,coords,data,datetime,default,' + + 'defer,dir,dirname,disabled,download,draggable,dropzone,enctype,method,for,' + + 'form,formaction,headers,height,hidden,high,href,hreflang,http-equiv,' + + 'icon,id,ismap,itemprop,keytype,kind,label,lang,language,list,loop,low,' + + 'manifest,max,maxlength,media,method,GET,POST,min,multiple,email,file,' + + 'muted,name,novalidate,open,optimum,pattern,ping,placeholder,poster,' + + 'preload,radiogroup,readonly,rel,required,reversed,rows,rowspan,sandbox,' + + 'scope,scoped,seamless,selected,shape,size,type,text,password,sizes,span,' + + 'spellcheck,src,srcdoc,srclang,srcset,start,step,style,summary,tabindex,' + + 'target,title,type,usemap,value,width,wrap' +) + +function vModel(self, dataObject, defaultValue) { + dataObject.props.value = defaultValue + + dataObject.on.input = val => { + self.$emit('input', val) + } +} + +const componentChild = { + 'el-button': { + default(h, conf, key) { + return conf[key] + }, + }, + 'el-input': { + prepend(h, conf, key) { + return + }, + append(h, conf, key) { + return + } + }, + 'el-select': { + options(h, conf, key) { + const list = [] + conf.options.forEach(item => { + list.push() + }) + return list + } + }, + 'el-radio-group': { + options(h, conf, key) { + const list = [] + conf.options.forEach(item => { + if (conf.optionType === 'button') list.push({item.label}) + else list.push({item.label}) + }) + return list + } + }, + 'el-checkbox-group': { + options(h, conf, key) { + const list = [] + conf.options.forEach(item => { + if (conf.optionType === 'button') { + list.push({item.label}) + } else { + list.push({item.label}) + } + }) + return list + } + }, + 'el-upload': { + 'list-type': (h, conf, key) => { + const list = [] + if (conf['list-type'] === 'picture-card') { + list.push() + } else { + list.push({conf.buttonText}) + } + if (conf.showTip) { + list.push(
只能上传不超过 {conf.fileSize}{conf.sizeUnit} 的{conf.accept}文件
) + } + return list + } + } +} + +export default { + render(h) { + const dataObject = { + attrs: {}, + props: {}, + on: {}, + style: {} + } + const confClone = JSON.parse(JSON.stringify(this.conf)) + const children = [] + + const childObjs = componentChild[confClone.tag] + if (childObjs) { + Object.keys(childObjs).forEach(key => { + const childFunc = childObjs[key] + if (confClone[key]) { + children.push(childFunc(h, confClone, key)) + } + }) + } + + Object.keys(confClone).forEach(key => { + const val = confClone[key] + if (key === 'vModel') { + vModel(this, dataObject, confClone.defaultValue) + } else if (dataObject[key]) { + dataObject[key] = val + } else if (!isAttr(key)) { + dataObject.props[key] = val + } else { + dataObject.attrs[key] = val + } + }) + return h(this.conf.tag, dataObject, children) + }, + props: ['conf'] +} diff --git a/custom-ui/src/utils/index.js b/custom-ui/src/utils/index.js new file mode 100644 index 0000000..4e65504 --- /dev/null +++ b/custom-ui/src/utils/index.js @@ -0,0 +1,390 @@ +import { parseTime } from './ruoyi' + +/** + * 表格时间格式化 + */ +export function formatDate(cellValue) { + if (cellValue == null || cellValue == "") return ""; + var date = new Date(cellValue) + var year = date.getFullYear() + var month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1 + var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate() + var hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours() + var minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes() + var seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds() + return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds +} + +/** + * @param {number} time + * @param {string} option + * @returns {string} + */ +export function formatTime(time, option) { + if (('' + time).length === 10) { + time = parseInt(time) * 1000 + } else { + time = +time + } + const d = new Date(time) + const now = Date.now() + + const diff = (now - d) / 1000 + + if (diff < 30) { + return '刚刚' + } else if (diff < 3600) { + // less 1 hour + return Math.ceil(diff / 60) + '分钟前' + } else if (diff < 3600 * 24) { + return Math.ceil(diff / 3600) + '小时前' + } else if (diff < 3600 * 24 * 2) { + return '1天前' + } + if (option) { + return parseTime(time, option) + } else { + return ( + d.getMonth() + + 1 + + '月' + + d.getDate() + + '日' + + d.getHours() + + '时' + + d.getMinutes() + + '分' + ) + } +} + +/** + * @param {string} url + * @returns {Object} + */ +export function getQueryObject(url) { + url = url == null ? window.location.href : url + const search = url.substring(url.lastIndexOf('?') + 1) + const obj = {} + const reg = /([^?&=]+)=([^?&=]*)/g + search.replace(reg, (rs, $1, $2) => { + const name = decodeURIComponent($1) + let val = decodeURIComponent($2) + val = String(val) + obj[name] = val + return rs + }) + return obj +} + +/** + * @param {string} input value + * @returns {number} output value + */ +export function byteLength(str) { + // returns the byte length of an utf8 string + let s = str.length + for (var i = str.length - 1; i >= 0; i--) { + const code = str.charCodeAt(i) + if (code > 0x7f && code <= 0x7ff) s++ + else if (code > 0x7ff && code <= 0xffff) s += 2 + if (code >= 0xDC00 && code <= 0xDFFF) i-- + } + return s +} + +/** + * @param {Array} actual + * @returns {Array} + */ +export function cleanArray(actual) { + const newArray = [] + for (let i = 0; i < actual.length; i++) { + if (actual[i]) { + newArray.push(actual[i]) + } + } + return newArray +} + +/** + * @param {Object} json + * @returns {Array} + */ +export function param(json) { + if (!json) return '' + return cleanArray( + Object.keys(json).map(key => { + if (json[key] === undefined) return '' + return encodeURIComponent(key) + '=' + encodeURIComponent(json[key]) + }) + ).join('&') +} + +/** + * @param {string} url + * @returns {Object} + */ +export function param2Obj(url) { + const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ') + if (!search) { + return {} + } + const obj = {} + const searchArr = search.split('&') + searchArr.forEach(v => { + const index = v.indexOf('=') + if (index !== -1) { + const name = v.substring(0, index) + const val = v.substring(index + 1, v.length) + obj[name] = val + } + }) + return obj +} + +/** + * @param {string} val + * @returns {string} + */ +export function html2Text(val) { + const div = document.createElement('div') + div.innerHTML = val + return div.textContent || div.innerText +} + +/** + * Merges two objects, giving the last one precedence + * @param {Object} target + * @param {(Object|Array)} source + * @returns {Object} + */ +export function objectMerge(target, source) { + if (typeof target !== 'object') { + target = {} + } + if (Array.isArray(source)) { + return source.slice() + } + Object.keys(source).forEach(property => { + const sourceProperty = source[property] + if (typeof sourceProperty === 'object') { + target[property] = objectMerge(target[property], sourceProperty) + } else { + target[property] = sourceProperty + } + }) + return target +} + +/** + * @param {HTMLElement} element + * @param {string} className + */ +export function toggleClass(element, className) { + if (!element || !className) { + return + } + let classString = element.className + const nameIndex = classString.indexOf(className) + if (nameIndex === -1) { + classString += '' + className + } else { + classString = + classString.substr(0, nameIndex) + + classString.substr(nameIndex + className.length) + } + element.className = classString +} + +/** + * @param {string} type + * @returns {Date} + */ +export function getTime(type) { + if (type === 'start') { + return new Date().getTime() - 3600 * 1000 * 24 * 90 + } else { + return new Date(new Date().toDateString()) + } +} + +/** + * @param {Function} func + * @param {number} wait + * @param {boolean} immediate + * @return {*} + */ +export function debounce(func, wait, immediate) { + let timeout, args, context, timestamp, result + + const later = function() { + // 据上一次触发时间间隔 + const last = +new Date() - timestamp + + // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait + if (last < wait && last > 0) { + timeout = setTimeout(later, wait - last) + } else { + timeout = null + // 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用 + if (!immediate) { + result = func.apply(context, args) + if (!timeout) context = args = null + } + } + } + + return function(...args) { + context = this + timestamp = +new Date() + const callNow = immediate && !timeout + // 如果延时不存在,重新设定延时 + if (!timeout) timeout = setTimeout(later, wait) + if (callNow) { + result = func.apply(context, args) + context = args = null + } + + return result + } +} + +/** + * This is just a simple version of deep copy + * Has a lot of edge cases bug + * If you want to use a perfect deep copy, use lodash's _.cloneDeep + * @param {Object} source + * @returns {Object} + */ +export function deepClone(source) { + if (!source && typeof source !== 'object') { + throw new Error('error arguments', 'deepClone') + } + const targetObj = source.constructor === Array ? [] : {} + Object.keys(source).forEach(keys => { + if (source[keys] && typeof source[keys] === 'object') { + targetObj[keys] = deepClone(source[keys]) + } else { + targetObj[keys] = source[keys] + } + }) + return targetObj +} + +/** + * @param {Array} arr + * @returns {Array} + */ +export function uniqueArr(arr) { + return Array.from(new Set(arr)) +} + +/** + * @returns {string} + */ +export function createUniqueString() { + const timestamp = +new Date() + '' + const randomNum = parseInt((1 + Math.random()) * 65536) + '' + return (+(randomNum + timestamp)).toString(32) +} + +/** + * Check if an element has a class + * @param {HTMLElement} elm + * @param {string} cls + * @returns {boolean} + */ +export function hasClass(ele, cls) { + return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)')) +} + +/** + * Add class to element + * @param {HTMLElement} elm + * @param {string} cls + */ +export function addClass(ele, cls) { + if (!hasClass(ele, cls)) ele.className += ' ' + cls +} + +/** + * Remove class from element + * @param {HTMLElement} elm + * @param {string} cls + */ +export function removeClass(ele, cls) { + if (hasClass(ele, cls)) { + const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)') + ele.className = ele.className.replace(reg, ' ') + } +} + +export function makeMap(str, expectsLowerCase) { + const map = Object.create(null) + const list = str.split(',') + for (let i = 0; i < list.length; i++) { + map[list[i]] = true + } + return expectsLowerCase + ? val => map[val.toLowerCase()] + : val => map[val] +} + +export const exportDefault = 'export default ' + +export const beautifierConf = { + html: { + indent_size: '2', + indent_char: ' ', + max_preserve_newlines: '-1', + preserve_newlines: false, + keep_array_indentation: false, + break_chained_methods: false, + indent_scripts: 'separate', + brace_style: 'end-expand', + space_before_conditional: true, + unescape_strings: false, + jslint_happy: false, + end_with_newline: true, + wrap_line_length: '110', + indent_inner_html: true, + comma_first: false, + e4x: true, + indent_empty_lines: true + }, + js: { + indent_size: '2', + indent_char: ' ', + max_preserve_newlines: '-1', + preserve_newlines: false, + keep_array_indentation: false, + break_chained_methods: false, + indent_scripts: 'normal', + brace_style: 'end-expand', + space_before_conditional: true, + unescape_strings: false, + jslint_happy: true, + end_with_newline: true, + wrap_line_length: '110', + indent_inner_html: true, + comma_first: false, + e4x: true, + indent_empty_lines: true + } +} + +// 首字母大小 +export function titleCase(str) { + return str.replace(/( |^)[a-z]/g, L => L.toUpperCase()) +} + +// 下划转驼峰 +export function camelCase(str) { + return str.replace(/_[a-z]/g, str1 => str1.substr(-1).toUpperCase()) +} + +export function isNumberStr(str) { + return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str) +} + diff --git a/custom-ui/src/utils/jsencrypt.js b/custom-ui/src/utils/jsencrypt.js new file mode 100644 index 0000000..78d9523 --- /dev/null +++ b/custom-ui/src/utils/jsencrypt.js @@ -0,0 +1,30 @@ +import JSEncrypt from 'jsencrypt/bin/jsencrypt.min' + +// 密钥对生成 http://web.chacuo.net/netrsakeypair + +const publicKey = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdH\n' + + 'nzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ==' + +const privateKey = 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY\n' + + '7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKN\n' + + 'PuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gA\n' + + 'kM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWow\n' + + 'cSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99Ecv\n' + + 'DQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthh\n' + + 'YhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3\n' + + 'UP8iWi1Qw0Y=' + +// 加密 +export function encrypt(txt) { + const encryptor = new JSEncrypt() + encryptor.setPublicKey(publicKey) // 设置公钥 + return encryptor.encrypt(txt) // 对数据进行加密 +} + +// 解密 +export function decrypt(txt) { + const encryptor = new JSEncrypt() + encryptor.setPrivateKey(privateKey) // 设置私钥 + return encryptor.decrypt(txt) // 对数据进行解密 +} + diff --git a/custom-ui/src/utils/permission.js b/custom-ui/src/utils/permission.js new file mode 100644 index 0000000..1730e33 --- /dev/null +++ b/custom-ui/src/utils/permission.js @@ -0,0 +1,51 @@ +import store from '@/store' + +/** + * 字符权限校验 + * @param {Array} value 校验值 + * @returns {Boolean} + */ +export function checkPermi(value) { + if (value && value instanceof Array && value.length > 0) { + const permissions = store.getters && store.getters.permissions + const permissionDatas = value + const all_permission = "*:*:*"; + + const hasPermission = permissions.some(permission => { + return all_permission === permission || permissionDatas.includes(permission) + }) + + if (!hasPermission) { + return false + } + return true + } else { + console.error(`need roles! Like checkPermi="['system:user:add','system:user:edit']"`) + return false + } +} + +/** + * 角色权限校验 + * @param {Array} value 校验值 + * @returns {Boolean} + */ +export function checkRole(value) { + if (value && value instanceof Array && value.length > 0) { + const roles = store.getters && store.getters.roles + const permissionRoles = value + const super_admin = "admin"; + + const hasRole = roles.some(role => { + return super_admin === role || permissionRoles.includes(role) + }) + + if (!hasRole) { + return false + } + return true + } else { + console.error(`need roles! Like checkRole="['admin','editor']"`) + return false + } +} \ No newline at end of file diff --git a/custom-ui/src/utils/request.js b/custom-ui/src/utils/request.js new file mode 100644 index 0000000..ad9923c --- /dev/null +++ b/custom-ui/src/utils/request.js @@ -0,0 +1,146 @@ +import axios from 'axios' +import { Notification, MessageBox, Message, Loading } from 'element-ui' +import store from '@/store' +import { getToken } from '@/utils/auth' +import errorCode from '@/utils/errorCode' +import { tansParams, blobValidate } from "@/utils/ruoyi"; +import cache from '@/plugins/cache' +import { saveAs } from 'file-saver' + +let downloadLoadingInstance; +// 是否显示重新登录 +export let isRelogin = { show: false }; + +axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8' +// 创建axios实例 +const service = axios.create({ + // axios中请求配置有baseURL选项,表示请求URL公共部分 + baseURL: process.env.VUE_APP_BASE_API, + // 超时 + timeout: 10000 +}) + +// request拦截器 +service.interceptors.request.use(config => { + // 是否需要设置 token + const isToken = (config.headers || {}).isToken === false + // 是否需要防止数据重复提交 + const isRepeatSubmit = (config.headers || {}).repeatSubmit === false + if (getToken() && !isToken) { + config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改 + } + // get请求映射params参数 + if (config.method === 'get' && config.params) { + let url = config.url + '?' + tansParams(config.params); + url = url.slice(0, -1); + config.params = {}; + config.url = url; + } + if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) { + const requestObj = { + url: config.url, + data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data, + time: new Date().getTime() + } + const sessionObj = cache.session.getJSON('sessionObj') + if (sessionObj === undefined || sessionObj === null || sessionObj === '') { + cache.session.setJSON('sessionObj', requestObj) + } else { + const s_url = sessionObj.url; // 请求地址 + const s_data = sessionObj.data; // 请求数据 + const s_time = sessionObj.time; // 请求时间 + const interval = 1000; // 间隔时间(ms),小于此时间视为重复提交 + if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) { + const message = '数据正在处理,请勿重复提交'; + console.warn(`[${s_url}]: ` + message) + return Promise.reject(new Error(message)) + } else { + cache.session.setJSON('sessionObj', requestObj) + } + } + } + return config +}, error => { + console.log(error) + Promise.reject(error) +}) + +// 响应拦截器 +service.interceptors.response.use(res => { + // 未设置状态码则默认成功状态 + const code = res.data.code || 200; + // 获取错误信息 + const msg = errorCode[code] || res.data.msg || errorCode['default'] + // 二进制数据则直接返回 + if(res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer'){ + return res.data + } + if (code === 401) { + if (!isRelogin.show) { + isRelogin.show = true; + MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => { + isRelogin.show = false; + store.dispatch('LogOut').then(() => { + location.href = '/index'; + }) + }).catch(() => { + isRelogin.show = false; + }); + } + return Promise.reject('无效的会话,或者会话已过期,请重新登录。') + } else if (code === 500) { + Message({ message: msg, type: 'error' }) + return Promise.reject(new Error(msg)) + } else if (code === 601) { + Message({ message: msg, type: 'warning' }) + return Promise.reject('error') + } else if (code !== 200) { + Notification.error({ title: msg }) + return Promise.reject('error') + } else { + return res.data + } + }, + error => { + console.log('err' + error) + let { message } = error; + if (message == "Network Error") { + message = "后端接口连接异常"; + } else if (message.includes("timeout")) { + message = "系统接口请求超时"; + } else if (message.includes("Request failed with status code")) { + message = "系统接口" + message.substr(message.length - 3) + "异常"; + } + Message({ message: message, type: 'error', duration: 5 * 1000 }) + return Promise.reject(error) + } +) + +// 通用下载方法 +export function download(url, params, filename, config) { + downloadLoadingInstance = Loading.service({ text: "正在下载数据,请稍候", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)", }) + return service.post(url, params, { + transformRequest: [(params) => { return tansParams(params) }], + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + responseType: 'blob', + ...config + }).then(async (data) => { + const isLogin = await blobValidate(data); + if (isLogin) { + const blob = new Blob([data]) + saveAs(blob, filename) + } else { + const resText = await data.text(); + const rspObj = JSON.parse(resText); + const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default'] + Message.error(errMsg); + } + downloadLoadingInstance.close(); + }).catch((r) => { + console.error(r) + Message.error('下载文件出现错误,请联系管理员!') + downloadLoadingInstance.close(); + }) +} + +export default service diff --git a/custom-ui/src/utils/ruoyi.js b/custom-ui/src/utils/ruoyi.js new file mode 100644 index 0000000..243c4c7 --- /dev/null +++ b/custom-ui/src/utils/ruoyi.js @@ -0,0 +1,239 @@ + + +/** + * 通用js方法封装处理 + * Copyright (c) 2019 ruoyi + */ + +// 日期格式化 +export function parseTime(time, pattern) { + if (arguments.length === 0 || !time) { + return null + } + const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}' + let date + if (typeof time === 'object') { + date = time + } else { + if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) { + time = parseInt(time) + } else if (typeof time === 'string') { + time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm), ''); + } + if ((typeof time === 'number') && (time.toString().length === 10)) { + time = time * 1000 + } + date = new Date(time) + } + const formatObj = { + y: date.getFullYear(), + m: date.getMonth() + 1, + d: date.getDate(), + h: date.getHours(), + i: date.getMinutes(), + s: date.getSeconds(), + a: date.getDay() + } + const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => { + let value = formatObj[key] + // Note: getDay() returns 0 on Sunday + if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] } + if (result.length > 0 && value < 10) { + value = '0' + value + } + return value || 0 + }) + return time_str +} + +// 表单重置 +export function resetForm(refName) { + if (this.$refs[refName]) { + this.$refs[refName].resetFields(); + } +} + +// 添加日期范围 +export function addDateRange(params, dateRange, propName) { + let search = params; + search.params = typeof (search.params) === 'object' && search.params !== null && !Array.isArray(search.params) ? search.params : {}; + dateRange = Array.isArray(dateRange) ? dateRange : []; + if (typeof (propName) === 'undefined') { + search.params['beginTime'] = dateRange[0]; + search.params['endTime'] = dateRange[1]; + } else { + search.params['begin' + propName] = dateRange[0]; + search.params['end' + propName] = dateRange[1]; + } + return search; +} + +// 回显数据字典 +export function selectDictLabel(datas, value) { + if (value === undefined) { + return ""; + } + var actions = []; + Object.keys(datas).some((key) => { + if (datas[key].value == ('' + value)) { + actions.push(datas[key].label); + return true; + } + }) + if (actions.length === 0) { + actions.push(value); + } + return actions.join(''); +} + +// 回显数据字典(字符串、数组) +export function selectDictLabels(datas, value, separator) { + if (value === undefined || value.length ===0) { + return ""; + } + if (Array.isArray(value)) { + value = value.join(","); + } + var actions = []; + var currentSeparator = undefined === separator ? "," : separator; + var temp = value.split(currentSeparator); + Object.keys(value.split(currentSeparator)).some((val) => { + var match = false; + Object.keys(datas).some((key) => { + if (datas[key].value == ('' + temp[val])) { + actions.push(datas[key].label + currentSeparator); + match = true; + } + }) + if (!match) { + actions.push(temp[val] + currentSeparator); + } + }) + return actions.join('').substring(0, actions.join('').length - 1); +} + +// 字符串格式化(%s ) +export function sprintf(str) { + var args = arguments, flag = true, i = 1; + str = str.replace(/%s/g, function () { + var arg = args[i++]; + if (typeof arg === 'undefined') { + flag = false; + return ''; + } + return arg; + }); + return flag ? str : ''; +} + +// 转换字符串,undefined,null等转化为"" +export function parseStrEmpty(str) { + if (!str || str == "undefined" || str == "null") { + return ""; + } + return str; +} + +// 数据合并 +export function mergeRecursive(source, target) { + for (var p in target) { + try { + if (target[p].constructor == Object) { + source[p] = mergeRecursive(source[p], target[p]); + } else { + source[p] = target[p]; + } + } catch (e) { + source[p] = target[p]; + } + } + return source; +}; + +/** + * 构造树型结构数据 + * @param {*} data 数据源 + * @param {*} id id字段 默认 'id' + * @param {*} parentId 父节点字段 默认 'parentId' + * @param {*} children 孩子节点字段 默认 'children' + */ +export function handleTree(data, id, parentId, children) { + let config = { + id: id || 'id', + parentId: parentId || 'parentId', + childrenList: children || 'children' + }; + + var childrenListMap = {}; + var nodeIds = {}; + var tree = []; + + for (let d of data) { + let parentId = d[config.parentId]; + if (childrenListMap[parentId] == null) { + childrenListMap[parentId] = []; + } + nodeIds[d[config.id]] = d; + childrenListMap[parentId].push(d); + } + + for (let d of data) { + let parentId = d[config.parentId]; + if (nodeIds[parentId] == null) { + tree.push(d); + } + } + + for (let t of tree) { + adaptToChildrenList(t); + } + + function adaptToChildrenList(o) { + if (childrenListMap[o[config.id]] !== null) { + o[config.childrenList] = childrenListMap[o[config.id]]; + } + if (o[config.childrenList]) { + for (let c of o[config.childrenList]) { + adaptToChildrenList(c); + } + } + } + return tree; +} + +/** +* 参数处理 +* @param {*} params 参数 +*/ +export function tansParams(params) { + let result = '' + for (const propName of Object.keys(params)) { + const value = params[propName]; + var part = encodeURIComponent(propName) + "="; + if (value !== null && value !== "" && typeof (value) !== "undefined") { + if (typeof value === 'object') { + for (const key of Object.keys(value)) { + if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') { + let params = propName + '[' + key + ']'; + var subPart = encodeURIComponent(params) + "="; + result += subPart + encodeURIComponent(value[key]) + "&"; + } + } + } else { + result += part + encodeURIComponent(value) + "&"; + } + } + } + return result +} + +// 验证是否为blob格式 +export async function blobValidate(data) { + try { + const text = await data.text(); + JSON.parse(text); + return false; + } catch (error) { + return true; + } +} diff --git a/custom-ui/src/utils/scroll-to.js b/custom-ui/src/utils/scroll-to.js new file mode 100644 index 0000000..c5d8e04 --- /dev/null +++ b/custom-ui/src/utils/scroll-to.js @@ -0,0 +1,58 @@ +Math.easeInOutQuad = function(t, b, c, d) { + t /= d / 2 + if (t < 1) { + return c / 2 * t * t + b + } + t-- + return -c / 2 * (t * (t - 2) - 1) + b +} + +// requestAnimationFrame for Smart Animating http://goo.gl/sx5sts +var requestAnimFrame = (function() { + return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) { window.setTimeout(callback, 1000 / 60) } +})() + +/** + * Because it's so fucking difficult to detect the scrolling element, just move them all + * @param {number} amount + */ +function move(amount) { + document.documentElement.scrollTop = amount + document.body.parentNode.scrollTop = amount + document.body.scrollTop = amount +} + +function position() { + return document.documentElement.scrollTop || document.body.parentNode.scrollTop || document.body.scrollTop +} + +/** + * @param {number} to + * @param {number} duration + * @param {Function} callback + */ +export function scrollTo(to, duration, callback) { + const start = position() + const change = to - start + const increment = 20 + let currentTime = 0 + duration = (typeof (duration) === 'undefined') ? 500 : duration + var animateScroll = function() { + // increment the time + currentTime += increment + // find the value with the quadratic in-out easing function + var val = Math.easeInOutQuad(currentTime, start, change, duration) + // move the document.body + move(val) + // do the animation unless its over + if (currentTime < duration) { + requestAnimFrame(animateScroll) + } else { + if (callback && typeof (callback) === 'function') { + // the animation is done so lets callback + callback() + } + } + } + animateScroll() +} diff --git a/custom-ui/src/utils/validate.js b/custom-ui/src/utils/validate.js new file mode 100644 index 0000000..adfa254 --- /dev/null +++ b/custom-ui/src/utils/validate.js @@ -0,0 +1,83 @@ +/** + * @param {string} path + * @returns {Boolean} + */ +export function isExternal(path) { + return /^(https?:|mailto:|tel:)/.test(path) +} + +/** + * @param {string} str + * @returns {Boolean} + */ +export function validUsername(str) { + const valid_map = ['admin', 'editor'] + return valid_map.indexOf(str.trim()) >= 0 +} + +/** + * @param {string} url + * @returns {Boolean} + */ +export function validURL(url) { + const reg = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/ + return reg.test(url) +} + +/** + * @param {string} str + * @returns {Boolean} + */ +export function validLowerCase(str) { + const reg = /^[a-z]+$/ + return reg.test(str) +} + +/** + * @param {string} str + * @returns {Boolean} + */ +export function validUpperCase(str) { + const reg = /^[A-Z]+$/ + return reg.test(str) +} + +/** + * @param {string} str + * @returns {Boolean} + */ +export function validAlphabets(str) { + const reg = /^[A-Za-z]+$/ + return reg.test(str) +} + +/** + * @param {string} email + * @returns {Boolean} + */ +export function validEmail(email) { + const reg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ + return reg.test(email) +} + +/** + * @param {string} str + * @returns {Boolean} + */ +export function isString(str) { + if (typeof str === 'string' || str instanceof String) { + return true + } + return false +} + +/** + * @param {Array} arg + * @returns {Boolean} + */ +export function isArray(arg) { + if (typeof Array.isArray === 'undefined') { + return Object.prototype.toString.call(arg) === '[object Array]' + } + return Array.isArray(arg) +} diff --git a/custom-ui/src/views/business/countGroup/index.vue b/custom-ui/src/views/business/countGroup/index.vue new file mode 100644 index 0000000..404ffc9 --- /dev/null +++ b/custom-ui/src/views/business/countGroup/index.vue @@ -0,0 +1,175 @@ + + + + + diff --git a/custom-ui/src/views/business/survey/index.vue b/custom-ui/src/views/business/survey/index.vue new file mode 100644 index 0000000..c5e7526 --- /dev/null +++ b/custom-ui/src/views/business/survey/index.vue @@ -0,0 +1,347 @@ + + + diff --git a/custom-ui/src/views/business/surveySubmit/index.vue b/custom-ui/src/views/business/surveySubmit/index.vue new file mode 100644 index 0000000..97e00e9 --- /dev/null +++ b/custom-ui/src/views/business/surveySubmit/index.vue @@ -0,0 +1,166 @@ + + + diff --git a/custom-ui/src/views/business/template/index.vue b/custom-ui/src/views/business/template/index.vue new file mode 100644 index 0000000..311496d --- /dev/null +++ b/custom-ui/src/views/business/template/index.vue @@ -0,0 +1,298 @@ + + + diff --git a/custom-ui/src/views/business/templateProp/index.vue b/custom-ui/src/views/business/templateProp/index.vue new file mode 100644 index 0000000..9455b0c --- /dev/null +++ b/custom-ui/src/views/business/templateProp/index.vue @@ -0,0 +1,363 @@ + + + diff --git a/custom-ui/src/views/business/templatePropValue/index.vue b/custom-ui/src/views/business/templatePropValue/index.vue new file mode 100644 index 0000000..372a633 --- /dev/null +++ b/custom-ui/src/views/business/templatePropValue/index.vue @@ -0,0 +1,307 @@ + + + diff --git a/custom-ui/src/views/components/icons/element-icons.js b/custom-ui/src/views/components/icons/element-icons.js new file mode 100644 index 0000000..9ea4d63 --- /dev/null +++ b/custom-ui/src/views/components/icons/element-icons.js @@ -0,0 +1,3 @@ +const elementIcons = ['platform-eleme', 'eleme', 'delete-solid', 'delete', 's-tools', 'setting', 'user-solid', 'user', 'phone', 'phone-outline', 'more', 'more-outline', 'star-on', 'star-off', 's-goods', 'goods', 'warning', 'warning-outline', 'question', 'info', 'remove', 'circle-plus', 'success', 'error', 'zoom-in', 'zoom-out', 'remove-outline', 'circle-plus-outline', 'circle-check', 'circle-close', 's-help', 'help', 'minus', 'plus', 'check', 'close', 'picture', 'picture-outline', 'picture-outline-round', 'upload', 'upload2', 'download', 'camera-solid', 'camera', 'video-camera-solid', 'video-camera', 'message-solid', 'bell', 's-cooperation', 's-order', 's-platform', 's-fold', 's-unfold', 's-operation', 's-promotion', 's-home', 's-release', 's-ticket', 's-management', 's-open', 's-shop', 's-marketing', 's-flag', 's-comment', 's-finance', 's-claim', 's-custom', 's-opportunity', 's-data', 's-check', 's-grid', 'menu', 'share', 'd-caret', 'caret-left', 'caret-right', 'caret-bottom', 'caret-top', 'bottom-left', 'bottom-right', 'back', 'right', 'bottom', 'top', 'top-left', 'top-right', 'arrow-left', 'arrow-right', 'arrow-down', 'arrow-up', 'd-arrow-left', 'd-arrow-right', 'video-pause', 'video-play', 'refresh', 'refresh-right', 'refresh-left', 'finished', 'sort', 'sort-up', 'sort-down', 'rank', 'loading', 'view', 'c-scale-to-original', 'date', 'edit', 'edit-outline', 'folder', 'folder-opened', 'folder-add', 'folder-remove', 'folder-delete', 'folder-checked', 'tickets', 'document-remove', 'document-delete', 'document-copy', 'document-checked', 'document', 'document-add', 'printer', 'paperclip', 'takeaway-box', 'search', 'monitor', 'attract', 'mobile', 'scissors', 'umbrella', 'headset', 'brush', 'mouse', 'coordinate', 'magic-stick', 'reading', 'data-line', 'data-board', 'pie-chart', 'data-analysis', 'collection-tag', 'film', 'suitcase', 'suitcase-1', 'receiving', 'collection', 'files', 'notebook-1', 'notebook-2', 'toilet-paper', 'office-building', 'school', 'table-lamp', 'house', 'no-smoking', 'smoking', 'shopping-cart-full', 'shopping-cart-1', 'shopping-cart-2', 'shopping-bag-1', 'shopping-bag-2', 'sold-out', 'sell', 'present', 'box', 'bank-card', 'money', 'coin', 'wallet', 'discount', 'price-tag', 'news', 'guide', 'male', 'female', 'thumb', 'cpu', 'link', 'connection', 'open', 'turn-off', 'set-up', 'chat-round', 'chat-line-round', 'chat-square', 'chat-dot-round', 'chat-dot-square', 'chat-line-square', 'message', 'postcard', 'position', 'turn-off-microphone', 'microphone', 'close-notification', 'bangzhu', 'time', 'odometer', 'crop', 'aim', 'switch-button', 'full-screen', 'copy-document', 'mic', 'stopwatch', 'medal-1', 'medal', 'trophy', 'trophy-1', 'first-aid-kit', 'discover', 'place', 'location', 'location-outline', 'location-information', 'add-location', 'delete-location', 'map-location', 'alarm-clock', 'timer', 'watch-1', 'watch', 'lock', 'unlock', 'key', 'service', 'mobile-phone', 'bicycle', 'truck', 'ship', 'basketball', 'football', 'soccer', 'baseball', 'wind-power', 'light-rain', 'lightning', 'heavy-rain', 'sunrise', 'sunrise-1', 'sunset', 'sunny', 'cloudy', 'partly-cloudy', 'cloudy-and-sunny', 'moon', 'moon-night', 'dish', 'dish-1', 'food', 'chicken', 'fork-spoon', 'knife-fork', 'burger', 'tableware', 'sugar', 'dessert', 'ice-cream', 'hot-water', 'water-cup', 'coffee-cup', 'cold-drink', 'goblet', 'goblet-full', 'goblet-square', 'goblet-square-full', 'refrigerator', 'grape', 'watermelon', 'cherry', 'apple', 'pear', 'orange', 'coffee', 'ice-tea', 'ice-drink', 'milk-tea', 'potato-strips', 'lollipop', 'ice-cream-square', 'ice-cream-round'] + +export default elementIcons diff --git a/custom-ui/src/views/components/icons/index.vue b/custom-ui/src/views/components/icons/index.vue new file mode 100644 index 0000000..d3c9a71 --- /dev/null +++ b/custom-ui/src/views/components/icons/index.vue @@ -0,0 +1,87 @@ + + + + + diff --git a/custom-ui/src/views/components/icons/svg-icons.js b/custom-ui/src/views/components/icons/svg-icons.js new file mode 100644 index 0000000..724cd8e --- /dev/null +++ b/custom-ui/src/views/components/icons/svg-icons.js @@ -0,0 +1,10 @@ +const req = require.context('../../../assets/icons/svg', false, /\.svg$/) +const requireAll = requireContext => requireContext.keys() + +const re = /\.\/(.*)\.svg/ + +const svgIcons = requireAll(req).map(i => { + return i.match(re)[1] +}) + +export default svgIcons diff --git a/custom-ui/src/views/dashboard/BarChart.vue b/custom-ui/src/views/dashboard/BarChart.vue new file mode 100644 index 0000000..cd33d2d --- /dev/null +++ b/custom-ui/src/views/dashboard/BarChart.vue @@ -0,0 +1,102 @@ + + + diff --git a/custom-ui/src/views/dashboard/LineChart.vue b/custom-ui/src/views/dashboard/LineChart.vue new file mode 100644 index 0000000..ddd1063 --- /dev/null +++ b/custom-ui/src/views/dashboard/LineChart.vue @@ -0,0 +1,135 @@ + + + diff --git a/custom-ui/src/views/dashboard/PanelGroup.vue b/custom-ui/src/views/dashboard/PanelGroup.vue new file mode 100644 index 0000000..1a1081f --- /dev/null +++ b/custom-ui/src/views/dashboard/PanelGroup.vue @@ -0,0 +1,181 @@ + + + + + diff --git a/custom-ui/src/views/dashboard/PieChart.vue b/custom-ui/src/views/dashboard/PieChart.vue new file mode 100644 index 0000000..c360057 --- /dev/null +++ b/custom-ui/src/views/dashboard/PieChart.vue @@ -0,0 +1,79 @@ + + + diff --git a/custom-ui/src/views/dashboard/RaddarChart.vue b/custom-ui/src/views/dashboard/RaddarChart.vue new file mode 100644 index 0000000..b1790ca --- /dev/null +++ b/custom-ui/src/views/dashboard/RaddarChart.vue @@ -0,0 +1,116 @@ + + + diff --git a/custom-ui/src/views/dashboard/mixins/resize.js b/custom-ui/src/views/dashboard/mixins/resize.js new file mode 100644 index 0000000..b1e76e9 --- /dev/null +++ b/custom-ui/src/views/dashboard/mixins/resize.js @@ -0,0 +1,56 @@ +import { debounce } from '@/utils' + +export default { + data() { + return { + $_sidebarElm: null, + $_resizeHandler: null + } + }, + mounted() { + this.initListener() + }, + activated() { + if (!this.$_resizeHandler) { + // avoid duplication init + this.initListener() + } + + // when keep-alive chart activated, auto resize + this.resize() + }, + beforeDestroy() { + this.destroyListener() + }, + deactivated() { + this.destroyListener() + }, + methods: { + // use $_ for mixins properties + // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential + $_sidebarResizeHandler(e) { + if (e.propertyName === 'width') { + this.$_resizeHandler() + } + }, + initListener() { + this.$_resizeHandler = debounce(() => { + this.resize() + }, 100) + window.addEventListener('resize', this.$_resizeHandler) + + this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0] + this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler) + }, + destroyListener() { + window.removeEventListener('resize', this.$_resizeHandler) + this.$_resizeHandler = null + + this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler) + }, + resize() { + const { chart } = this + chart && chart.resize() + } + } +} diff --git a/custom-ui/src/views/error/401.vue b/custom-ui/src/views/error/401.vue new file mode 100644 index 0000000..448b6ec --- /dev/null +++ b/custom-ui/src/views/error/401.vue @@ -0,0 +1,88 @@ + + + + + diff --git a/custom-ui/src/views/error/404.vue b/custom-ui/src/views/error/404.vue new file mode 100644 index 0000000..96f075c --- /dev/null +++ b/custom-ui/src/views/error/404.vue @@ -0,0 +1,233 @@ + + + + + diff --git a/custom-ui/src/views/index.vue b/custom-ui/src/views/index.vue new file mode 100644 index 0000000..1014327 --- /dev/null +++ b/custom-ui/src/views/index.vue @@ -0,0 +1,87 @@ + + + + + + diff --git a/custom-ui/src/views/index_v1.vue b/custom-ui/src/views/index_v1.vue new file mode 100644 index 0000000..d2d2ec6 --- /dev/null +++ b/custom-ui/src/views/index_v1.vue @@ -0,0 +1,98 @@ + + + + + diff --git a/custom-ui/src/views/login.vue b/custom-ui/src/views/login.vue new file mode 100644 index 0000000..ecfaaea --- /dev/null +++ b/custom-ui/src/views/login.vue @@ -0,0 +1,225 @@ + + + + + diff --git a/custom-ui/src/views/monitor/cache/index.vue b/custom-ui/src/views/monitor/cache/index.vue new file mode 100644 index 0000000..53f6eee --- /dev/null +++ b/custom-ui/src/views/monitor/cache/index.vue @@ -0,0 +1,146 @@ + + + diff --git a/custom-ui/src/views/monitor/cache/list.vue b/custom-ui/src/views/monitor/cache/list.vue new file mode 100644 index 0000000..a1e7955 --- /dev/null +++ b/custom-ui/src/views/monitor/cache/list.vue @@ -0,0 +1,241 @@ + + + diff --git a/custom-ui/src/views/monitor/druid/index.vue b/custom-ui/src/views/monitor/druid/index.vue new file mode 100644 index 0000000..c6ad585 --- /dev/null +++ b/custom-ui/src/views/monitor/druid/index.vue @@ -0,0 +1,15 @@ + + diff --git a/custom-ui/src/views/monitor/job/index.vue b/custom-ui/src/views/monitor/job/index.vue new file mode 100644 index 0000000..37c8fc1 --- /dev/null +++ b/custom-ui/src/views/monitor/job/index.vue @@ -0,0 +1,513 @@ + + + diff --git a/custom-ui/src/views/monitor/job/log.vue b/custom-ui/src/views/monitor/job/log.vue new file mode 100644 index 0000000..60bee1d --- /dev/null +++ b/custom-ui/src/views/monitor/job/log.vue @@ -0,0 +1,295 @@ + + + diff --git a/custom-ui/src/views/monitor/logininfor/index.vue b/custom-ui/src/views/monitor/logininfor/index.vue new file mode 100644 index 0000000..8a9b17a --- /dev/null +++ b/custom-ui/src/views/monitor/logininfor/index.vue @@ -0,0 +1,245 @@ + + + + diff --git a/custom-ui/src/views/monitor/online/index.vue b/custom-ui/src/views/monitor/online/index.vue new file mode 100644 index 0000000..ad613c9 --- /dev/null +++ b/custom-ui/src/views/monitor/online/index.vue @@ -0,0 +1,122 @@ + + + + diff --git a/custom-ui/src/views/monitor/operlog/index.vue b/custom-ui/src/views/monitor/operlog/index.vue new file mode 100644 index 0000000..c1b5377 --- /dev/null +++ b/custom-ui/src/views/monitor/operlog/index.vue @@ -0,0 +1,305 @@ + + + + diff --git a/custom-ui/src/views/monitor/server/index.vue b/custom-ui/src/views/monitor/server/index.vue new file mode 100644 index 0000000..b122edf --- /dev/null +++ b/custom-ui/src/views/monitor/server/index.vue @@ -0,0 +1,207 @@ + + + \ No newline at end of file diff --git a/custom-ui/src/views/redirect.vue b/custom-ui/src/views/redirect.vue new file mode 100644 index 0000000..db4c1d6 --- /dev/null +++ b/custom-ui/src/views/redirect.vue @@ -0,0 +1,12 @@ + diff --git a/custom-ui/src/views/register.vue b/custom-ui/src/views/register.vue new file mode 100644 index 0000000..6167069 --- /dev/null +++ b/custom-ui/src/views/register.vue @@ -0,0 +1,209 @@ + + + + + diff --git a/custom-ui/src/views/system/config/index.vue b/custom-ui/src/views/system/config/index.vue new file mode 100644 index 0000000..f580b98 --- /dev/null +++ b/custom-ui/src/views/system/config/index.vue @@ -0,0 +1,343 @@ + + + diff --git a/custom-ui/src/views/system/dept/index.vue b/custom-ui/src/views/system/dept/index.vue new file mode 100644 index 0000000..e502b4e --- /dev/null +++ b/custom-ui/src/views/system/dept/index.vue @@ -0,0 +1,340 @@ + + + diff --git a/custom-ui/src/views/system/dict/data.vue b/custom-ui/src/views/system/dict/data.vue new file mode 100644 index 0000000..324bb64 --- /dev/null +++ b/custom-ui/src/views/system/dict/data.vue @@ -0,0 +1,402 @@ + + + \ No newline at end of file diff --git a/custom-ui/src/views/system/dict/index.vue b/custom-ui/src/views/system/dict/index.vue new file mode 100644 index 0000000..6ca5457 --- /dev/null +++ b/custom-ui/src/views/system/dict/index.vue @@ -0,0 +1,347 @@ + + + \ No newline at end of file diff --git a/custom-ui/src/views/system/menu/index.vue b/custom-ui/src/views/system/menu/index.vue new file mode 100644 index 0000000..57b56e5 --- /dev/null +++ b/custom-ui/src/views/system/menu/index.vue @@ -0,0 +1,453 @@ + + + diff --git a/custom-ui/src/views/system/notice/index.vue b/custom-ui/src/views/system/notice/index.vue new file mode 100644 index 0000000..7982b54 --- /dev/null +++ b/custom-ui/src/views/system/notice/index.vue @@ -0,0 +1,312 @@ + + + diff --git a/custom-ui/src/views/system/post/index.vue b/custom-ui/src/views/system/post/index.vue new file mode 100644 index 0000000..444bf63 --- /dev/null +++ b/custom-ui/src/views/system/post/index.vue @@ -0,0 +1,309 @@ + + + diff --git a/custom-ui/src/views/system/role/authUser.vue b/custom-ui/src/views/system/role/authUser.vue new file mode 100644 index 0000000..147aa33 --- /dev/null +++ b/custom-ui/src/views/system/role/authUser.vue @@ -0,0 +1,199 @@ + + + \ No newline at end of file diff --git a/custom-ui/src/views/system/role/index.vue b/custom-ui/src/views/system/role/index.vue new file mode 100644 index 0000000..fb3b5ef --- /dev/null +++ b/custom-ui/src/views/system/role/index.vue @@ -0,0 +1,605 @@ + + + \ No newline at end of file diff --git a/custom-ui/src/views/system/role/selectUser.vue b/custom-ui/src/views/system/role/selectUser.vue new file mode 100644 index 0000000..b2b072f --- /dev/null +++ b/custom-ui/src/views/system/role/selectUser.vue @@ -0,0 +1,138 @@ + + + diff --git a/custom-ui/src/views/system/user/authRole.vue b/custom-ui/src/views/system/user/authRole.vue new file mode 100644 index 0000000..ab5e72f --- /dev/null +++ b/custom-ui/src/views/system/user/authRole.vue @@ -0,0 +1,117 @@ + + + \ No newline at end of file diff --git a/custom-ui/src/views/system/user/index.vue b/custom-ui/src/views/system/user/index.vue new file mode 100644 index 0000000..ae87fe4 --- /dev/null +++ b/custom-ui/src/views/system/user/index.vue @@ -0,0 +1,670 @@ + + + \ No newline at end of file diff --git a/custom-ui/src/views/system/user/profile/index.vue b/custom-ui/src/views/system/user/profile/index.vue new file mode 100644 index 0000000..ad530f9 --- /dev/null +++ b/custom-ui/src/views/system/user/profile/index.vue @@ -0,0 +1,91 @@ + + + diff --git a/custom-ui/src/views/system/user/profile/resetPwd.vue b/custom-ui/src/views/system/user/profile/resetPwd.vue new file mode 100644 index 0000000..64e8f8c --- /dev/null +++ b/custom-ui/src/views/system/user/profile/resetPwd.vue @@ -0,0 +1,68 @@ + + + diff --git a/custom-ui/src/views/system/user/profile/userAvatar.vue b/custom-ui/src/views/system/user/profile/userAvatar.vue new file mode 100644 index 0000000..70d8487 --- /dev/null +++ b/custom-ui/src/views/system/user/profile/userAvatar.vue @@ -0,0 +1,187 @@ + + + + diff --git a/custom-ui/src/views/system/user/profile/userInfo.vue b/custom-ui/src/views/system/user/profile/userInfo.vue new file mode 100644 index 0000000..c09a20b --- /dev/null +++ b/custom-ui/src/views/system/user/profile/userInfo.vue @@ -0,0 +1,75 @@ + + + diff --git a/custom-ui/src/views/tool/build/CodeTypeDialog.vue b/custom-ui/src/views/tool/build/CodeTypeDialog.vue new file mode 100644 index 0000000..b5c2e2e --- /dev/null +++ b/custom-ui/src/views/tool/build/CodeTypeDialog.vue @@ -0,0 +1,106 @@ + + diff --git a/custom-ui/src/views/tool/build/DraggableItem.vue b/custom-ui/src/views/tool/build/DraggableItem.vue new file mode 100644 index 0000000..e881778 --- /dev/null +++ b/custom-ui/src/views/tool/build/DraggableItem.vue @@ -0,0 +1,100 @@ + diff --git a/custom-ui/src/views/tool/build/IconsDialog.vue b/custom-ui/src/views/tool/build/IconsDialog.vue new file mode 100644 index 0000000..958be50 --- /dev/null +++ b/custom-ui/src/views/tool/build/IconsDialog.vue @@ -0,0 +1,123 @@ + + + diff --git a/custom-ui/src/views/tool/build/RightPanel.vue b/custom-ui/src/views/tool/build/RightPanel.vue new file mode 100644 index 0000000..c2760eb --- /dev/null +++ b/custom-ui/src/views/tool/build/RightPanel.vue @@ -0,0 +1,946 @@ + + + + + diff --git a/custom-ui/src/views/tool/build/TreeNodeDialog.vue b/custom-ui/src/views/tool/build/TreeNodeDialog.vue new file mode 100644 index 0000000..fa7f0b2 --- /dev/null +++ b/custom-ui/src/views/tool/build/TreeNodeDialog.vue @@ -0,0 +1,149 @@ + + diff --git a/custom-ui/src/views/tool/build/index.vue b/custom-ui/src/views/tool/build/index.vue new file mode 100644 index 0000000..ff475df --- /dev/null +++ b/custom-ui/src/views/tool/build/index.vue @@ -0,0 +1,826 @@ + + + + + diff --git a/custom-ui/src/views/tool/gen/basicInfoForm.vue b/custom-ui/src/views/tool/gen/basicInfoForm.vue new file mode 100644 index 0000000..7029529 --- /dev/null +++ b/custom-ui/src/views/tool/gen/basicInfoForm.vue @@ -0,0 +1,60 @@ + + + diff --git a/custom-ui/src/views/tool/gen/editTable.vue b/custom-ui/src/views/tool/gen/editTable.vue new file mode 100644 index 0000000..951497a --- /dev/null +++ b/custom-ui/src/views/tool/gen/editTable.vue @@ -0,0 +1,234 @@ + + + diff --git a/custom-ui/src/views/tool/gen/genInfoForm.vue b/custom-ui/src/views/tool/gen/genInfoForm.vue new file mode 100644 index 0000000..3f8d67f --- /dev/null +++ b/custom-ui/src/views/tool/gen/genInfoForm.vue @@ -0,0 +1,299 @@ + + + diff --git a/custom-ui/src/views/tool/gen/importTable.vue b/custom-ui/src/views/tool/gen/importTable.vue new file mode 100644 index 0000000..3ea9532 --- /dev/null +++ b/custom-ui/src/views/tool/gen/importTable.vue @@ -0,0 +1,120 @@ + + + diff --git a/custom-ui/src/views/tool/gen/index.vue b/custom-ui/src/views/tool/gen/index.vue new file mode 100644 index 0000000..3f1f930 --- /dev/null +++ b/custom-ui/src/views/tool/gen/index.vue @@ -0,0 +1,337 @@ + + + diff --git a/custom-ui/src/views/tool/swagger/index.vue b/custom-ui/src/views/tool/swagger/index.vue new file mode 100644 index 0000000..b782968 --- /dev/null +++ b/custom-ui/src/views/tool/swagger/index.vue @@ -0,0 +1,15 @@ + + diff --git a/custom-ui/vue.config.js b/custom-ui/vue.config.js new file mode 100644 index 0000000..8bd226f --- /dev/null +++ b/custom-ui/vue.config.js @@ -0,0 +1,136 @@ +'use strict' +const path = require('path') + +function resolve(dir) { + return path.join(__dirname, dir) +} + +const CompressionPlugin = require('compression-webpack-plugin') + +const name = process.env.VUE_APP_TITLE || '后台管理系统' // 网页标题 + +const port = process.env.port || process.env.npm_config_port || 80 // 端口 + +// vue.config.js 配置说明 +//官方vue.config.js 参考文档 https://cli.vuejs.org/zh/config/#css-loaderoptions +// 这里只列一部分,具体配置参考文档 +module.exports = { + // 部署生产环境和开发环境下的URL。 + // 默认情况下,Vue CLI 会假设你的应用是被部署在一个域名的根路径上 + // 例如 https://www.ruoyi.vip/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.ruoyi.vip/admin/,则设置 baseUrl 为 /admin/。 + publicPath: process.env.NODE_ENV === "production" ? "/" : "/", + // 在npm run build 或 yarn build 时 ,生成文件的目录名称(要和baseUrl的生产环境路径一致)(默认dist) + outputDir: 'dist', + // 用于放置生成的静态资源 (js、css、img、fonts) 的;(项目打包之后,静态资源会放在这个文件夹下) + assetsDir: 'static', + // 是否开启eslint保存检测,有效值:ture | false | 'error' + lintOnSave: process.env.NODE_ENV === 'development', + // 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。 + productionSourceMap: false, + // webpack-dev-server 相关配置 + devServer: { + host: '0.0.0.0', + port: port, + open: true, + proxy: { + // detail: https://cli.vuejs.org/config/#devserver-proxy + [process.env.VUE_APP_BASE_API]: { + target: `http://localhost:9000`, + changeOrigin: true, + pathRewrite: { + ['^' + process.env.VUE_APP_BASE_API]: '' + } + } + }, + disableHostCheck: true + }, + css: { + loaderOptions: { + sass: { + sassOptions: { outputStyle: "expanded" } + } + } + }, + configureWebpack: { + name: name, + resolve: { + alias: { + '@': resolve('src') + } + }, + plugins: [ + // http://doc.ruoyi.vip/ruoyi-vue/other/faq.html#使用gzip解压缩静态文件 + new CompressionPlugin({ + cache: false, // 不启用文件缓存 + test: /\.(js|css|html)?$/i, // 压缩文件格式 + filename: '[path].gz[query]', // 压缩后的文件名 + algorithm: 'gzip', // 使用gzip压缩 + minRatio: 0.8 // 压缩率小于1才会压缩 + }) + ], + }, + chainWebpack(config) { + config.plugins.delete('preload') // TODO: need test + config.plugins.delete('prefetch') // TODO: need test + + // set svg-sprite-loader + config.module + .rule('svg') + .exclude.add(resolve('src/assets/icons')) + .end() + config.module + .rule('icons') + .test(/\.svg$/) + .include.add(resolve('src/assets/icons')) + .end() + .use('svg-sprite-loader') + .loader('svg-sprite-loader') + .options({ + symbolId: 'icon-[name]' + }) + .end() + + config + .when(process.env.NODE_ENV !== 'development', + config => { + config + .plugin('ScriptExtHtmlWebpackPlugin') + .after('html') + .use('script-ext-html-webpack-plugin', [{ + // `runtime` must same as runtimeChunk name. default is `runtime` + inline: /runtime\..*\.js$/ + }]) + .end() + config + .optimization.splitChunks({ + chunks: 'all', + cacheGroups: { + libs: { + name: 'chunk-libs', + test: /[\\/]node_modules[\\/]/, + priority: 10, + chunks: 'initial' // only package third parties that are initially dependent + }, + elementUI: { + name: 'chunk-elementUI', // split elementUI into a single package + priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app + test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm + }, + commons: { + name: 'chunk-commons', + test: resolve('src/components'), // can customize your rules + minChunks: 3, // minimum common number + priority: 5, + reuseExistingChunk: true + } + } + }) + config.optimization.runtimeChunk('single'), + { + from: path.resolve(__dirname, './public/robots.txt'), //防爬虫文件 + to: './' //到根目录下 + } + } + ) + } +} diff --git a/custom-ui/启动必看.txt b/custom-ui/启动必看.txt new file mode 100644 index 0000000..6a44e0f --- /dev/null +++ b/custom-ui/启动必看.txt @@ -0,0 +1,5 @@ +首次运行 +npm install --registry=https://registry.npmmirror.com + +# 本地开发 启动项目 +npm run dev \ No newline at end of file diff --git a/pom.xml b/pom.xml index 313c8bc..75ca6cb 100644 --- a/pom.xml +++ b/pom.xml @@ -2,293 +2,231 @@ - 4.0.0 - - me.zhengjie - wjcy - pom - 1.0 - - - wjcy-common - wjcy-logging - wjcy-system - wjcy-tools - wjcy-generator - - - EL-ADMIN 后台管理 - http://auauz.net - - - org.springframework.boot - spring-boot-starter-parent - 2.2.10.RELEASE - - + 4.0.0 + + com.ruoyi + ruoyi + 3.8.5 + + + 管理系统 + + 3.8.5 UTF-8 UTF-8 1.8 - 1.16 - 1.2.70 - 1.1.24 - 2.5.0 - 1.3.1.Final - 2.1.1 - 2.15.0 - 2.0.7 + 3.1.1 + 1.2.15 + 1.21 + 3.0.0 + 2.3.3 + 1.4.6 + 2.0.23 + 6.4.0 + 2.11.0 + 1.4 + 3.2.2 + 4.1.2 + 2.3 + 0.9.1 + + + + + + + + org.springframework.boot + spring-boot-dependencies + 2.5.14 + pom + import + + + + + com.alibaba + druid-spring-boot-starter + ${druid.version} + + + + + eu.bitwalker + UserAgentUtils + ${bitwalker.version} + + + + + com.github.pagehelper + pagehelper-spring-boot-starter + ${pagehelper.boot.version} + + + + + com.github.oshi + oshi-core + ${oshi.version} + + + + + io.springfox + springfox-boot-starter + ${swagger.version} + + + io.swagger + swagger-models + + + + + + + commons-io + commons-io + ${commons.io.version} + + + + + commons-fileupload + commons-fileupload + ${commons.fileupload.version} + + + + + org.apache.poi + poi-ooxml + ${poi.version} + + + + + org.apache.velocity + velocity-engine-core + ${velocity.version} + + + + + commons-collections + commons-collections + ${commons.collections.version} + + + + + com.alibaba.fastjson2 + fastjson2 + ${fastjson.version} + + + + + io.jsonwebtoken + jjwt + ${jwt.version} + + + + + pro.fessional + kaptcha + ${kaptcha.version} + + + + + com.ruoyi + ruoyi-quartz + ${ruoyi.version} + + + + + com.ruoyi + ruoyi-generator + ${ruoyi.version} + + + + + com.ruoyi + ruoyi-framework + ${ruoyi.version} + + + + + com.ruoyi + ruoyi-system + ${ruoyi.version} + + + + + com.ruoyi + ruoyi-business + ${ruoyi.version} + + + + + com.ruoyi + ruoyi-common + ${ruoyi.version} + + + + org.projectlombok + lombok + 1.18.24 + + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.2 + + + + + + + + ruoyi-admin + ruoyi-framework + ruoyi-system + ruoyi-business + ruoyi-quartz + ruoyi-generator + ruoyi-common + + pom + - - - org.springframework.boot - spring-boot-starter-logging - - - * - * - - - - - - org.springframework.boot - spring-boot-starter-data-jpa - - - - - org.springframework.boot - spring-boot-starter-web - - - - - org.springframework.boot - spring-boot-starter-test - test - - - - - org.springframework.boot - spring-boot-starter-security - - - - - org.springframework.boot - spring-boot-starter-cache - - - - - org.springframework.boot - spring-boot-starter-data-redis - - - - - org.apache.commons - commons-pool2 - ${commons-pool2.version} - - - org.apache.commons - commons-lang3 - - - org.springframework.boot - spring-boot-configuration-processor - true - - - - org.bgee.log4jdbc-log4j2 - log4jdbc-log4j2-jdbc4.1 - ${log4jdbc.version} - - - - - com.github.xiaoymin - knife4j-spring-boot-starter - ${knife4j.version} - - - - - mysql - mysql-connector-java - runtime - - - - - com.alibaba - druid-spring-boot-starter - ${druid.version} - - - org.lionsoul - ip2region - 1.7.2 - - - - - org.projectlombok - lombok - true - - - - - - - com.alibaba - fastjson - ${fastjson.version} - - - - - org.mapstruct - mapstruct - ${mapstruct.version} - - - org.mapstruct - mapstruct-processor - ${mapstruct.version} - provided - - - javax.inject - javax.inject - 1 - - - - - com.github.whvcse - easy-captcha - 1.6.2 - - - - - nl.basjes.parse.useragent - yauaa - 5.23 - - - - - com.baomidou - mybatis-plus-boot-starter - 3.3.2 - - - com.h2database - h2 - runtime - - - - - org.springframework.boot - spring-boot-starter-log4j2 - - - - - org.apache.poi - poi - 4.0.1 - - - - - org.apache.poi - poi-ooxml - 4.0.1 - - - - net.sourceforge.jexcelapi - jxl - 2.6.10 - - - - org.redisson - redisson - 3.5.7 - - - - - org.apache.rocketmq - rocketmq-client - 4.4.0 - - - - - com.google.guava - guava - 24.1-jre - - - com.madgag.spongycastle - core - 1.58.0.0 - - - - org.springframework.boot - spring-boot-starter-thymeleaf - - - - org.springframework.cloud - spring-cloud-starter-openfeign - 2.2.5.RELEASE - - - com.netflix.feign - feign-jackson - 8.18.0 - - - - org.telegram - telegrambots - 5.5.0 - - - - src/main/java - - **/*.xml - - true - - - org.apache.maven.plugins - maven-surefire-plugin + maven-compiler-plugin + 3.1 - true + ${java.version} + ${java.version} + ${project.build.sourceEncoding} @@ -298,7 +236,7 @@ public aliyun nexus - http://maven.aliyun.com/nexus/content/groups/public/ + https://maven.aliyun.com/repository/public true @@ -309,7 +247,7 @@ public aliyun nexus - http://maven.aliyun.com/nexus/content/groups/public/ + https://maven.aliyun.com/repository/public true @@ -318,4 +256,5 @@ + \ No newline at end of file diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml new file mode 100644 index 0000000..945307b --- /dev/null +++ b/ruoyi-admin/pom.xml @@ -0,0 +1,112 @@ + + + + ruoyi + com.ruoyi + 3.8.5 + + 4.0.0 + jar + ruoyi-admin + + + web服务入口 + + + + + + + org.springframework.boot + spring-boot-devtools + true + + + + + io.springfox + springfox-boot-starter + + + + + io.swagger + swagger-models + 1.6.2 + + + + + mysql + mysql-connector-java + + + + + com.ruoyi + ruoyi-framework + + + + + com.ruoyi + ruoyi-quartz + + + + + com.ruoyi + ruoyi-generator + + + + + com.github.xiaoymin + knife4j-spring-boot-starter + 3.0.3 + + + com.google.guava + guava + + + org.yaml + snakeyaml + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.1.RELEASE + + true + + + + + repackage + + + + + + org.apache.maven.plugins + maven-war-plugin + 3.1.0 + + false + ${project.artifactId} + + + + ${project.artifactId} + + + \ No newline at end of file diff --git a/ruoyi-admin/src/main/java/com/ruoyi/RunApplication.java b/ruoyi-admin/src/main/java/com/ruoyi/RunApplication.java new file mode 100644 index 0000000..adf49b3 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/RunApplication.java @@ -0,0 +1,30 @@ +package com.ruoyi; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; + +/** + * 启动程序 + * + * @author #author# + */ +@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }) +public class RunApplication +{ + public static void main(String[] args) + { + // System.setProperty("spring.devtools.restart.enabled", "false"); + SpringApplication.run(RunApplication.class, args); + System.out.println("(♥◠‿◠)ノ゙ 项目启动成功 ლ(´ڡ`ლ)゙ \n" + + " .-------. ____ __ \n" + + " | _ _ \\ \\ \\ / / \n" + + " | ( ' ) | \\ _. / ' \n" + + " |(_ o _) / _( )_ .' \n" + + " | (_,_).' __ ___(_ o _)' \n" + + " | |\\ \\ | || |(_,_)' \n" + + " | | \\ `' /| `-' / \n" + + " | | \\ / \\ / \n" + + " ''-' `'-' `-..-' "); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/RunServletInitializer.java b/ruoyi-admin/src/main/java/com/ruoyi/RunServletInitializer.java new file mode 100644 index 0000000..083da28 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/RunServletInitializer.java @@ -0,0 +1,18 @@ +package com.ruoyi; + +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; + +/** + * web容器中进行部署 + * + * @author #author# + */ +public class RunServletInitializer extends SpringBootServletInitializer +{ + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) + { + return application.sources(RunApplication.class); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java new file mode 100644 index 0000000..53bdfa9 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java @@ -0,0 +1,94 @@ +package com.ruoyi.web.controller.common; + +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.concurrent.TimeUnit; +import javax.annotation.Resource; +import javax.imageio.ImageIO; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.FastByteArrayOutputStream; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; +import com.google.code.kaptcha.Producer; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.utils.sign.Base64; +import com.ruoyi.common.utils.uuid.IdUtils; +import com.ruoyi.system.service.ISysConfigService; + +/** + * 验证码操作处理 + * + * @author #author# + */ +@RestController +public class CaptchaController +{ + @Resource(name = "captchaProducer") + private Producer captchaProducer; + + @Resource(name = "captchaProducerMath") + private Producer captchaProducerMath; + + @Autowired + private RedisCache redisCache; + + @Autowired + private ISysConfigService configService; + /** + * 生成验证码 + */ + @GetMapping("/captchaImage") + public AjaxResult getCode(HttpServletResponse response) throws IOException + { + AjaxResult ajax = AjaxResult.success(); + boolean captchaEnabled = configService.selectCaptchaEnabled(); + ajax.put("captchaEnabled", captchaEnabled); + if (!captchaEnabled) + { + return ajax; + } + + // 保存验证码信息 + String uuid = IdUtils.simpleUUID(); + String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid; + + String capStr = null, code = null; + BufferedImage image = null; + + // 生成验证码 + String captchaType = RuoYiConfig.getCaptchaType(); + if ("math".equals(captchaType)) + { + String capText = captchaProducerMath.createText(); + capStr = capText.substring(0, capText.lastIndexOf("@")); + code = capText.substring(capText.lastIndexOf("@") + 1); + image = captchaProducerMath.createImage(capStr); + } + else if ("char".equals(captchaType)) + { + capStr = code = captchaProducer.createText(); + image = captchaProducer.createImage(capStr); + } + + redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES); + // 转换流信息写出 + FastByteArrayOutputStream os = new FastByteArrayOutputStream(); + try + { + ImageIO.write(image, "jpg", os); + } + catch (IOException e) + { + return AjaxResult.error(e.getMessage()); + } + + ajax.put("uuid", uuid); + ajax.put("img", Base64.encode(os.toByteArray())); + return ajax; + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java new file mode 100644 index 0000000..053a988 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java @@ -0,0 +1,163 @@ +package com.ruoyi.web.controller.common; + +import java.util.ArrayList; +import java.util.List; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.file.FileUploadUtils; +import com.ruoyi.common.utils.file.FileUtils; +import com.ruoyi.framework.config.ServerConfig; + +/** + * 通用请求处理 + * + * @author #author# + */ +@RestController +@RequestMapping("/common") +public class CommonController +{ + private static final Logger log = LoggerFactory.getLogger(CommonController.class); + + @Autowired + private ServerConfig serverConfig; + + private static final String FILE_DELIMETER = ","; + + /** + * 通用下载请求 + * + * @param fileName 文件名称 + * @param delete 是否删除 + */ + @GetMapping("/download") + public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request) + { + try + { + if (!FileUtils.checkAllowDownload(fileName)) + { + throw new Exception(StringUtils.format("文件名称({})非法,不允许下载。 ", fileName)); + } + String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1); + String filePath = RuoYiConfig.getDownloadPath() + fileName; + + response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); + FileUtils.setAttachmentResponseHeader(response, realFileName); + FileUtils.writeBytes(filePath, response.getOutputStream()); + if (delete) + { + FileUtils.deleteFile(filePath); + } + } + catch (Exception e) + { + log.error("下载文件失败", e); + } + } + + /** + * 通用上传请求(单个) + */ + @PostMapping("/upload") + public AjaxResult uploadFile(MultipartFile file) throws Exception + { + try + { + // 上传文件路径 + String filePath = RuoYiConfig.getUploadPath(); + // 上传并返回新文件名称 + String fileName = FileUploadUtils.upload(filePath, file); + String url = serverConfig.getUrl() + fileName; + AjaxResult ajax = AjaxResult.success(); + ajax.put("url", url); + ajax.put("fileName", fileName); + ajax.put("newFileName", FileUtils.getName(fileName)); + ajax.put("originalFilename", file.getOriginalFilename()); + return ajax; + } + catch (Exception e) + { + return AjaxResult.error(e.getMessage()); + } + } + + /** + * 通用上传请求(多个) + */ + @PostMapping("/uploads") + public AjaxResult uploadFiles(List files) throws Exception + { + try + { + // 上传文件路径 + String filePath = RuoYiConfig.getUploadPath(); + List urls = new ArrayList(); + List fileNames = new ArrayList(); + List newFileNames = new ArrayList(); + List originalFilenames = new ArrayList(); + for (MultipartFile file : files) + { + // 上传并返回新文件名称 + String fileName = FileUploadUtils.upload(filePath, file); + String url = serverConfig.getUrl() + fileName; + urls.add(url); + fileNames.add(fileName); + newFileNames.add(FileUtils.getName(fileName)); + originalFilenames.add(file.getOriginalFilename()); + } + AjaxResult ajax = AjaxResult.success(); + ajax.put("urls", StringUtils.join(urls, FILE_DELIMETER)); + ajax.put("fileNames", StringUtils.join(fileNames, FILE_DELIMETER)); + ajax.put("newFileNames", StringUtils.join(newFileNames, FILE_DELIMETER)); + ajax.put("originalFilenames", StringUtils.join(originalFilenames, FILE_DELIMETER)); + return ajax; + } + catch (Exception e) + { + return AjaxResult.error(e.getMessage()); + } + } + + /** + * 本地资源通用下载 + */ + @GetMapping("/download/resource") + public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response) + throws Exception + { + try + { + if (!FileUtils.checkAllowDownload(resource)) + { + throw new Exception(StringUtils.format("资源文件({})非法,不允许下载。 ", resource)); + } + // 本地资源路径 + String localPath = RuoYiConfig.getProfile(); + // 数据库资源地址 + String downloadPath = localPath + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX); + // 下载名称 + String downloadName = StringUtils.substringAfterLast(downloadPath, "/"); + response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); + FileUtils.setAttachmentResponseHeader(response, downloadName); + FileUtils.writeBytes(downloadPath, response.getOutputStream()); + } + catch (Exception e) + { + log.error("下载文件失败", e); + } + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java new file mode 100644 index 0000000..d86c5bf --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java @@ -0,0 +1,120 @@ +package com.ruoyi.web.controller.monitor; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisCallback; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.system.domain.SysCache; + +/** + * 缓存监控 + * + * @author #author# + */ +@RestController +@RequestMapping("/monitor/cache") +public class CacheController +{ + @Autowired + private RedisTemplate redisTemplate; + + private final static List caches = new ArrayList(); + { + caches.add(new SysCache(CacheConstants.LOGIN_TOKEN_KEY, "用户信息")); + caches.add(new SysCache(CacheConstants.SYS_CONFIG_KEY, "配置信息")); + caches.add(new SysCache(CacheConstants.SYS_DICT_KEY, "数据字典")); + caches.add(new SysCache(CacheConstants.CAPTCHA_CODE_KEY, "验证码")); + caches.add(new SysCache(CacheConstants.REPEAT_SUBMIT_KEY, "防重提交")); + caches.add(new SysCache(CacheConstants.RATE_LIMIT_KEY, "限流处理")); + caches.add(new SysCache(CacheConstants.PWD_ERR_CNT_KEY, "密码错误次数")); + } + + @PreAuthorize("@ss.hasPermi('monitor:cache:list')") + @GetMapping() + public AjaxResult getInfo() throws Exception + { + Properties info = (Properties) redisTemplate.execute((RedisCallback) connection -> connection.info()); + Properties commandStats = (Properties) redisTemplate.execute((RedisCallback) connection -> connection.info("commandstats")); + Object dbSize = redisTemplate.execute((RedisCallback) connection -> connection.dbSize()); + + Map result = new HashMap<>(3); + result.put("info", info); + result.put("dbSize", dbSize); + + List> pieList = new ArrayList<>(); + commandStats.stringPropertyNames().forEach(key -> { + Map data = new HashMap<>(2); + String property = commandStats.getProperty(key); + data.put("name", StringUtils.removeStart(key, "cmdstat_")); + data.put("value", StringUtils.substringBetween(property, "calls=", ",usec")); + pieList.add(data); + }); + result.put("commandStats", pieList); + return AjaxResult.success(result); + } + + @PreAuthorize("@ss.hasPermi('monitor:cache:list')") + @GetMapping("/getNames") + public AjaxResult cache() + { + return AjaxResult.success(caches); + } + + @PreAuthorize("@ss.hasPermi('monitor:cache:list')") + @GetMapping("/getKeys/{cacheName}") + public AjaxResult getCacheKeys(@PathVariable String cacheName) + { + Set cacheKeys = redisTemplate.keys(cacheName + "*"); + return AjaxResult.success(cacheKeys); + } + + @PreAuthorize("@ss.hasPermi('monitor:cache:list')") + @GetMapping("/getValue/{cacheName}/{cacheKey}") + public AjaxResult getCacheValue(@PathVariable String cacheName, @PathVariable String cacheKey) + { + String cacheValue = redisTemplate.opsForValue().get(cacheKey); + SysCache sysCache = new SysCache(cacheName, cacheKey, cacheValue); + return AjaxResult.success(sysCache); + } + + @PreAuthorize("@ss.hasPermi('monitor:cache:list')") + @DeleteMapping("/clearCacheName/{cacheName}") + public AjaxResult clearCacheName(@PathVariable String cacheName) + { + Collection cacheKeys = redisTemplate.keys(cacheName + "*"); + redisTemplate.delete(cacheKeys); + return AjaxResult.success(); + } + + @PreAuthorize("@ss.hasPermi('monitor:cache:list')") + @DeleteMapping("/clearCacheKey/{cacheKey}") + public AjaxResult clearCacheKey(@PathVariable String cacheKey) + { + redisTemplate.delete(cacheKey); + return AjaxResult.success(); + } + + @PreAuthorize("@ss.hasPermi('monitor:cache:list')") + @DeleteMapping("/clearCacheAll") + public AjaxResult clearCacheAll() + { + Collection cacheKeys = redisTemplate.keys("*"); + redisTemplate.delete(cacheKeys); + return AjaxResult.success(); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java new file mode 100644 index 0000000..8eea96f --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java @@ -0,0 +1,27 @@ +package com.ruoyi.web.controller.monitor; + +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.framework.web.domain.Server; + +/** + * 服务器监控 + * + * @author #author# + */ +@RestController +@RequestMapping("/monitor/server") +public class ServerController +{ + @PreAuthorize("@ss.hasPermi('monitor:server:list')") + @GetMapping() + public AjaxResult getInfo() throws Exception + { + Server server = new Server(); + server.copyTo(); + return AjaxResult.success(server); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java new file mode 100644 index 0000000..6c135da --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java @@ -0,0 +1,82 @@ +package com.ruoyi.web.controller.monitor; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.framework.web.service.SysPasswordService; +import com.ruoyi.system.domain.SysLogininfor; +import com.ruoyi.system.service.ISysLogininforService; + +/** + * 系统访问记录 + * + * @author #author# + */ +@RestController +@RequestMapping("/monitor/logininfor") +public class SysLogininforController extends BaseController +{ + @Autowired + private ISysLogininforService logininforService; + + @Autowired + private SysPasswordService passwordService; + + @PreAuthorize("@ss.hasPermi('monitor:logininfor:list')") + @GetMapping("/list") + public TableDataInfo list(SysLogininfor logininfor) + { + startPage(); + List list = logininforService.selectLogininforList(logininfor); + return getDataTable(list); + } + + @Log(title = "登录日志", businessType = BusinessType.EXPORT) + @PreAuthorize("@ss.hasPermi('monitor:logininfor:export')") + @PostMapping("/export") + public void export(HttpServletResponse response, SysLogininfor logininfor) + { + List list = logininforService.selectLogininforList(logininfor); + ExcelUtil util = new ExcelUtil(SysLogininfor.class); + util.exportExcel(response, list, "登录日志"); + } + + @PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')") + @Log(title = "登录日志", businessType = BusinessType.DELETE) + @DeleteMapping("/{infoIds}") + public AjaxResult remove(@PathVariable Long[] infoIds) + { + return toAjax(logininforService.deleteLogininforByIds(infoIds)); + } + + @PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')") + @Log(title = "登录日志", businessType = BusinessType.CLEAN) + @DeleteMapping("/clean") + public AjaxResult clean() + { + logininforService.cleanLogininfor(); + return success(); + } + + @PreAuthorize("@ss.hasPermi('monitor:logininfor:unlock')") + @Log(title = "账户解锁", businessType = BusinessType.OTHER) + @GetMapping("/unlock/{userName}") + public AjaxResult unlock(@PathVariable("userName") String userName) + { + passwordService.clearLoginRecordCache(userName); + return success(); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java new file mode 100644 index 0000000..62da6cf --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java @@ -0,0 +1,69 @@ +package com.ruoyi.web.controller.monitor; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.system.domain.SysOperLog; +import com.ruoyi.system.service.ISysOperLogService; + +/** + * 操作日志记录 + * + * @author #author# + */ +@RestController +@RequestMapping("/monitor/operlog") +public class SysOperlogController extends BaseController +{ + @Autowired + private ISysOperLogService operLogService; + + @PreAuthorize("@ss.hasPermi('monitor:operlog:list')") + @GetMapping("/list") + public TableDataInfo list(SysOperLog operLog) + { + startPage(); + List list = operLogService.selectOperLogList(operLog); + return getDataTable(list); + } + + @Log(title = "操作日志", businessType = BusinessType.EXPORT) + @PreAuthorize("@ss.hasPermi('monitor:operlog:export')") + @PostMapping("/export") + public void export(HttpServletResponse response, SysOperLog operLog) + { + List list = operLogService.selectOperLogList(operLog); + ExcelUtil util = new ExcelUtil(SysOperLog.class); + util.exportExcel(response, list, "操作日志"); + } + + @Log(title = "操作日志", businessType = BusinessType.DELETE) + @PreAuthorize("@ss.hasPermi('monitor:operlog:remove')") + @DeleteMapping("/{operIds}") + public AjaxResult remove(@PathVariable Long[] operIds) + { + return toAjax(operLogService.deleteOperLogByIds(operIds)); + } + + @Log(title = "操作日志", businessType = BusinessType.CLEAN) + @PreAuthorize("@ss.hasPermi('monitor:operlog:remove')") + @DeleteMapping("/clean") + public AjaxResult clean() + { + operLogService.cleanOperLog(); + return success(); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java new file mode 100644 index 0000000..7943c9f --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java @@ -0,0 +1,92 @@ +package com.ruoyi.web.controller.monitor; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.system.domain.SysUserOnline; +import com.ruoyi.system.service.ISysUserOnlineService; + +/** + * 在线用户监控 + * + * @author #author# + */ +@RestController +@RequestMapping("/monitor/online") +public class SysUserOnlineController extends BaseController +{ + @Autowired + private ISysUserOnlineService userOnlineService; + + @Autowired + private RedisCache redisCache; + + @PreAuthorize("@ss.hasPermi('monitor:online:list')") + @GetMapping("/list") + public TableDataInfo list(String ipaddr, String userName) + { + Collection keys = redisCache.keys(CacheConstants.LOGIN_TOKEN_KEY + "*"); + List userOnlineList = new ArrayList(); + for (String key : keys) + { + LoginUser user = redisCache.getCacheObject(key); + if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName)) + { + if (StringUtils.equals(ipaddr, user.getIpaddr()) && StringUtils.equals(userName, user.getUsername())) + { + userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user)); + } + } + else if (StringUtils.isNotEmpty(ipaddr)) + { + if (StringUtils.equals(ipaddr, user.getIpaddr())) + { + userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user)); + } + } + else if (StringUtils.isNotEmpty(userName) && StringUtils.isNotNull(user.getUser())) + { + if (StringUtils.equals(userName, user.getUsername())) + { + userOnlineList.add(userOnlineService.selectOnlineByUserName(userName, user)); + } + } + else + { + userOnlineList.add(userOnlineService.loginUserToUserOnline(user)); + } + } + Collections.reverse(userOnlineList); + userOnlineList.removeAll(Collections.singleton(null)); + return getDataTable(userOnlineList); + } + + /** + * 强退用户 + */ + @PreAuthorize("@ss.hasPermi('monitor:online:forceLogout')") + @Log(title = "在线用户", businessType = BusinessType.FORCE) + @DeleteMapping("/{tokenId}") + public AjaxResult forceLogout(@PathVariable String tokenId) + { + redisCache.deleteObject(CacheConstants.LOGIN_TOKEN_KEY + tokenId); + return success(); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java new file mode 100644 index 0000000..a0b840e --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java @@ -0,0 +1,134 @@ +package com.ruoyi.web.controller.system; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.system.domain.SysConfig; +import com.ruoyi.system.service.ISysConfigService; + +/** + * 参数配置 信息操作处理 + * + * @author #author# + */ +@RestController +@RequestMapping("/system/config") +public class SysConfigController extends BaseController +{ + @Autowired + private ISysConfigService configService; + + /** + * 获取参数配置列表 + */ + @PreAuthorize("@ss.hasPermi('system:config:list')") + @GetMapping("/list") + public TableDataInfo list(SysConfig config) + { + startPage(); + List list = configService.selectConfigList(config); + return getDataTable(list); + } + + @Log(title = "参数管理", businessType = BusinessType.EXPORT) + @PreAuthorize("@ss.hasPermi('system:config:export')") + @PostMapping("/export") + public void export(HttpServletResponse response, SysConfig config) + { + List list = configService.selectConfigList(config); + ExcelUtil util = new ExcelUtil(SysConfig.class); + util.exportExcel(response, list, "参数数据"); + } + + /** + * 根据参数编号获取详细信息 + */ + @PreAuthorize("@ss.hasPermi('system:config:query')") + @GetMapping(value = "/{configId}") + public AjaxResult getInfo(@PathVariable Long configId) + { + return success(configService.selectConfigById(configId)); + } + + /** + * 根据参数键名查询参数值 + */ + @GetMapping(value = "/configKey/{configKey}") + public AjaxResult getConfigKey(@PathVariable String configKey) + { + return success(configService.selectConfigByKey(configKey)); + } + + /** + * 新增参数配置 + */ + @PreAuthorize("@ss.hasPermi('system:config:add')") + @Log(title = "参数管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysConfig config) + { + if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) + { + return error("新增参数'" + config.getConfigName() + "'失败,参数键名已存在"); + } + config.setCreateBy(getUsername()); + return toAjax(configService.insertConfig(config)); + } + + /** + * 修改参数配置 + */ + @PreAuthorize("@ss.hasPermi('system:config:edit')") + @Log(title = "参数管理", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysConfig config) + { + if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) + { + return error("修改参数'" + config.getConfigName() + "'失败,参数键名已存在"); + } + config.setUpdateBy(getUsername()); + return toAjax(configService.updateConfig(config)); + } + + /** + * 删除参数配置 + */ + @PreAuthorize("@ss.hasPermi('system:config:remove')") + @Log(title = "参数管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{configIds}") + public AjaxResult remove(@PathVariable Long[] configIds) + { + configService.deleteConfigByIds(configIds); + return success(); + } + + /** + * 刷新参数缓存 + */ + @PreAuthorize("@ss.hasPermi('system:config:remove')") + @Log(title = "参数管理", businessType = BusinessType.CLEAN) + @DeleteMapping("/refreshCache") + public AjaxResult refreshCache() + { + configService.resetConfigCache(); + return success(); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java new file mode 100644 index 0000000..6d91ceb --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java @@ -0,0 +1,132 @@ +package com.ruoyi.web.controller.system; + +import java.util.List; +import org.apache.commons.lang3.ArrayUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysDept; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.system.service.ISysDeptService; + +/** + * 部门信息 + * + * @author #author# + */ +@RestController +@RequestMapping("/system/dept") +public class SysDeptController extends BaseController +{ + @Autowired + private ISysDeptService deptService; + + /** + * 获取部门列表 + */ + @PreAuthorize("@ss.hasPermi('system:dept:list')") + @GetMapping("/list") + public AjaxResult list(SysDept dept) + { + List depts = deptService.selectDeptList(dept); + return success(depts); + } + + /** + * 查询部门列表(排除节点) + */ + @PreAuthorize("@ss.hasPermi('system:dept:list')") + @GetMapping("/list/exclude/{deptId}") + public AjaxResult excludeChild(@PathVariable(value = "deptId", required = false) Long deptId) + { + List depts = deptService.selectDeptList(new SysDept()); + depts.removeIf(d -> d.getDeptId().intValue() == deptId || ArrayUtils.contains(StringUtils.split(d.getAncestors(), ","), deptId + "")); + return success(depts); + } + + /** + * 根据部门编号获取详细信息 + */ + @PreAuthorize("@ss.hasPermi('system:dept:query')") + @GetMapping(value = "/{deptId}") + public AjaxResult getInfo(@PathVariable Long deptId) + { + deptService.checkDeptDataScope(deptId); + return success(deptService.selectDeptById(deptId)); + } + + /** + * 新增部门 + */ + @PreAuthorize("@ss.hasPermi('system:dept:add')") + @Log(title = "部门管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysDept dept) + { + if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept))) + { + return error("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在"); + } + dept.setCreateBy(getUsername()); + return toAjax(deptService.insertDept(dept)); + } + + /** + * 修改部门 + */ + @PreAuthorize("@ss.hasPermi('system:dept:edit')") + @Log(title = "部门管理", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysDept dept) + { + Long deptId = dept.getDeptId(); + deptService.checkDeptDataScope(deptId); + if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept))) + { + return error("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在"); + } + else if (dept.getParentId().equals(deptId)) + { + return error("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己"); + } + else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus()) && deptService.selectNormalChildrenDeptById(deptId) > 0) + { + return error("该部门包含未停用的子部门!"); + } + dept.setUpdateBy(getUsername()); + return toAjax(deptService.updateDept(dept)); + } + + /** + * 删除部门 + */ + @PreAuthorize("@ss.hasPermi('system:dept:remove')") + @Log(title = "部门管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{deptId}") + public AjaxResult remove(@PathVariable Long deptId) + { + if (deptService.hasChildByDeptId(deptId)) + { + return warn("存在下级部门,不允许删除"); + } + if (deptService.checkDeptExistUser(deptId)) + { + return warn("部门存在用户,不允许删除"); + } + deptService.checkDeptDataScope(deptId); + return toAjax(deptService.deleteDeptById(deptId)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java new file mode 100644 index 0000000..2973488 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java @@ -0,0 +1,121 @@ +package com.ruoyi.web.controller.system; + +import java.util.ArrayList; +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysDictData; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.system.service.ISysDictDataService; +import com.ruoyi.system.service.ISysDictTypeService; + +/** + * 数据字典信息 + * + * @author #author# + */ +@RestController +@RequestMapping("/system/dict/data") +public class SysDictDataController extends BaseController +{ + @Autowired + private ISysDictDataService dictDataService; + + @Autowired + private ISysDictTypeService dictTypeService; + + @PreAuthorize("@ss.hasPermi('system:dict:list')") + @GetMapping("/list") + public TableDataInfo list(SysDictData dictData) + { + startPage(); + List list = dictDataService.selectDictDataList(dictData); + return getDataTable(list); + } + + @Log(title = "字典数据", businessType = BusinessType.EXPORT) + @PreAuthorize("@ss.hasPermi('system:dict:export')") + @PostMapping("/export") + public void export(HttpServletResponse response, SysDictData dictData) + { + List list = dictDataService.selectDictDataList(dictData); + ExcelUtil util = new ExcelUtil(SysDictData.class); + util.exportExcel(response, list, "字典数据"); + } + + /** + * 查询字典数据详细 + */ + @PreAuthorize("@ss.hasPermi('system:dict:query')") + @GetMapping(value = "/{dictCode}") + public AjaxResult getInfo(@PathVariable Long dictCode) + { + return success(dictDataService.selectDictDataById(dictCode)); + } + + /** + * 根据字典类型查询字典数据信息 + */ + @GetMapping(value = "/type/{dictType}") + public AjaxResult dictType(@PathVariable String dictType) + { + List data = dictTypeService.selectDictDataByType(dictType); + if (StringUtils.isNull(data)) + { + data = new ArrayList(); + } + return success(data); + } + + /** + * 新增字典类型 + */ + @PreAuthorize("@ss.hasPermi('system:dict:add')") + @Log(title = "字典数据", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysDictData dict) + { + dict.setCreateBy(getUsername()); + return toAjax(dictDataService.insertDictData(dict)); + } + + /** + * 修改保存字典类型 + */ + @PreAuthorize("@ss.hasPermi('system:dict:edit')") + @Log(title = "字典数据", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysDictData dict) + { + dict.setUpdateBy(getUsername()); + return toAjax(dictDataService.updateDictData(dict)); + } + + /** + * 删除字典类型 + */ + @PreAuthorize("@ss.hasPermi('system:dict:remove')") + @Log(title = "字典类型", businessType = BusinessType.DELETE) + @DeleteMapping("/{dictCodes}") + public AjaxResult remove(@PathVariable Long[] dictCodes) + { + dictDataService.deleteDictDataByIds(dictCodes); + return success(); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java new file mode 100644 index 0000000..4cf2ba2 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java @@ -0,0 +1,132 @@ +package com.ruoyi.web.controller.system; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysDictType; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.system.service.ISysDictTypeService; + +/** + * 数据字典信息 + * + * @author #author# + */ +@RestController +@RequestMapping("/system/dict/type") +public class SysDictTypeController extends BaseController +{ + @Autowired + private ISysDictTypeService dictTypeService; + + @PreAuthorize("@ss.hasPermi('system:dict:list')") + @GetMapping("/list") + public TableDataInfo list(SysDictType dictType) + { + startPage(); + List list = dictTypeService.selectDictTypeList(dictType); + return getDataTable(list); + } + + @Log(title = "字典类型", businessType = BusinessType.EXPORT) + @PreAuthorize("@ss.hasPermi('system:dict:export')") + @PostMapping("/export") + public void export(HttpServletResponse response, SysDictType dictType) + { + List list = dictTypeService.selectDictTypeList(dictType); + ExcelUtil util = new ExcelUtil(SysDictType.class); + util.exportExcel(response, list, "字典类型"); + } + + /** + * 查询字典类型详细 + */ + @PreAuthorize("@ss.hasPermi('system:dict:query')") + @GetMapping(value = "/{dictId}") + public AjaxResult getInfo(@PathVariable Long dictId) + { + return success(dictTypeService.selectDictTypeById(dictId)); + } + + /** + * 新增字典类型 + */ + @PreAuthorize("@ss.hasPermi('system:dict:add')") + @Log(title = "字典类型", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysDictType dict) + { + if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict))) + { + return error("新增字典'" + dict.getDictName() + "'失败,字典类型已存在"); + } + dict.setCreateBy(getUsername()); + return toAjax(dictTypeService.insertDictType(dict)); + } + + /** + * 修改字典类型 + */ + @PreAuthorize("@ss.hasPermi('system:dict:edit')") + @Log(title = "字典类型", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysDictType dict) + { + if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict))) + { + return error("修改字典'" + dict.getDictName() + "'失败,字典类型已存在"); + } + dict.setUpdateBy(getUsername()); + return toAjax(dictTypeService.updateDictType(dict)); + } + + /** + * 删除字典类型 + */ + @PreAuthorize("@ss.hasPermi('system:dict:remove')") + @Log(title = "字典类型", businessType = BusinessType.DELETE) + @DeleteMapping("/{dictIds}") + public AjaxResult remove(@PathVariable Long[] dictIds) + { + dictTypeService.deleteDictTypeByIds(dictIds); + return success(); + } + + /** + * 刷新字典缓存 + */ + @PreAuthorize("@ss.hasPermi('system:dict:remove')") + @Log(title = "字典类型", businessType = BusinessType.CLEAN) + @DeleteMapping("/refreshCache") + public AjaxResult refreshCache() + { + dictTypeService.resetDictCache(); + return success(); + } + + /** + * 获取字典选择框列表 + */ + @GetMapping("/optionselect") + public AjaxResult optionselect() + { + List dictTypes = dictTypeService.selectDictTypeAll(); + return success(dictTypes); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java new file mode 100644 index 0000000..eb2479c --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java @@ -0,0 +1,29 @@ +package com.ruoyi.web.controller.system; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.utils.StringUtils; + +/** + * 首页 + * + * @author #author# + */ +@RestController +public class SysIndexController +{ + /** 系统基础配置 */ + @Autowired + private RuoYiConfig ruoyiConfig; + + /** + * 访问首页,提示语 + */ + @RequestMapping("/") + public String index() + { + return StringUtils.format("欢迎使用{}后台管理框架,当前版本:v{},请通过前端地址访问。", ruoyiConfig.getName(), ruoyiConfig.getVersion()); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java new file mode 100644 index 0000000..88d7eb0 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java @@ -0,0 +1,86 @@ +package com.ruoyi.web.controller.system; + +import java.util.List; +import java.util.Set; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysMenu; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.domain.model.LoginBody; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.framework.web.service.SysLoginService; +import com.ruoyi.framework.web.service.SysPermissionService; +import com.ruoyi.system.service.ISysMenuService; + +/** + * 登录验证 + * + * @author #author# + */ +@RestController +public class SysLoginController +{ + @Autowired + private SysLoginService loginService; + + @Autowired + private ISysMenuService menuService; + + @Autowired + private SysPermissionService permissionService; + + /** + * 登录方法 + * + * @param loginBody 登录信息 + * @return 结果 + */ + @PostMapping("/login") + public AjaxResult login(@RequestBody LoginBody loginBody) + { + AjaxResult ajax = AjaxResult.success(); + // 生成令牌 + String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(), + loginBody.getUuid()); + ajax.put(Constants.TOKEN, token); + return ajax; + } + + /** + * 获取用户信息 + * + * @return 用户信息 + */ + @GetMapping("getInfo") + public AjaxResult getInfo() + { + SysUser user = SecurityUtils.getLoginUser().getUser(); + // 角色集合 + Set roles = permissionService.getRolePermission(user); + // 权限集合 + Set permissions = permissionService.getMenuPermission(user); + AjaxResult ajax = AjaxResult.success(); + ajax.put("user", user); + ajax.put("roles", roles); + ajax.put("permissions", permissions); + return ajax; + } + + /** + * 获取路由信息 + * + * @return 路由信息 + */ + @GetMapping("getRouters") + public AjaxResult getRouters() + { + Long userId = SecurityUtils.getUserId(); + List menus = menuService.selectMenuTreeByUserId(userId); + return AjaxResult.success(menuService.buildMenus(menus)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java new file mode 100644 index 0000000..fc6e9a9 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java @@ -0,0 +1,142 @@ +package com.ruoyi.web.controller.system; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysMenu; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.system.service.ISysMenuService; + +/** + * 菜单信息 + * + * @author #author# + */ +@RestController +@RequestMapping("/system/menu") +public class SysMenuController extends BaseController +{ + @Autowired + private ISysMenuService menuService; + + /** + * 获取菜单列表 + */ + @PreAuthorize("@ss.hasPermi('system:menu:list')") + @GetMapping("/list") + public AjaxResult list(SysMenu menu) + { + List menus = menuService.selectMenuList(menu, getUserId()); + return success(menus); + } + + /** + * 根据菜单编号获取详细信息 + */ + @PreAuthorize("@ss.hasPermi('system:menu:query')") + @GetMapping(value = "/{menuId}") + public AjaxResult getInfo(@PathVariable Long menuId) + { + return success(menuService.selectMenuById(menuId)); + } + + /** + * 获取菜单下拉树列表 + */ + @GetMapping("/treeselect") + public AjaxResult treeselect(SysMenu menu) + { + List menus = menuService.selectMenuList(menu, getUserId()); + return success(menuService.buildMenuTreeSelect(menus)); + } + + /** + * 加载对应角色菜单列表树 + */ + @GetMapping(value = "/roleMenuTreeselect/{roleId}") + public AjaxResult roleMenuTreeselect(@PathVariable("roleId") Long roleId) + { + List menus = menuService.selectMenuList(getUserId()); + AjaxResult ajax = AjaxResult.success(); + ajax.put("checkedKeys", menuService.selectMenuListByRoleId(roleId)); + ajax.put("menus", menuService.buildMenuTreeSelect(menus)); + return ajax; + } + + /** + * 新增菜单 + */ + @PreAuthorize("@ss.hasPermi('system:menu:add')") + @Log(title = "菜单管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysMenu menu) + { + if (UserConstants.NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu))) + { + return error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); + } + else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) + { + return error("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头"); + } + menu.setCreateBy(getUsername()); + return toAjax(menuService.insertMenu(menu)); + } + + /** + * 修改菜单 + */ + @PreAuthorize("@ss.hasPermi('system:menu:edit')") + @Log(title = "菜单管理", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysMenu menu) + { + if (UserConstants.NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu))) + { + return error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); + } + else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) + { + return error("修改菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头"); + } + else if (menu.getMenuId().equals(menu.getParentId())) + { + return error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己"); + } + menu.setUpdateBy(getUsername()); + return toAjax(menuService.updateMenu(menu)); + } + + /** + * 删除菜单 + */ + @PreAuthorize("@ss.hasPermi('system:menu:remove')") + @Log(title = "菜单管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{menuId}") + public AjaxResult remove(@PathVariable("menuId") Long menuId) + { + if (menuService.hasChildByMenuId(menuId)) + { + return warn("存在子菜单,不允许删除"); + } + if (menuService.checkMenuExistRole(menuId)) + { + return warn("菜单已分配,不允许删除"); + } + return toAjax(menuService.deleteMenuById(menuId)); + } +} \ No newline at end of file diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java new file mode 100644 index 0000000..b81dbaa --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java @@ -0,0 +1,91 @@ +package com.ruoyi.web.controller.system; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.system.domain.SysNotice; +import com.ruoyi.system.service.ISysNoticeService; + +/** + * 公告 信息操作处理 + * + * @author #author# + */ +@RestController +@RequestMapping("/system/notice") +public class SysNoticeController extends BaseController +{ + @Autowired + private ISysNoticeService noticeService; + + /** + * 获取通知公告列表 + */ + @PreAuthorize("@ss.hasPermi('system:notice:list')") + @GetMapping("/list") + public TableDataInfo list(SysNotice notice) + { + startPage(); + List list = noticeService.selectNoticeList(notice); + return getDataTable(list); + } + + /** + * 根据通知公告编号获取详细信息 + */ + @PreAuthorize("@ss.hasPermi('system:notice:query')") + @GetMapping(value = "/{noticeId}") + public AjaxResult getInfo(@PathVariable Long noticeId) + { + return success(noticeService.selectNoticeById(noticeId)); + } + + /** + * 新增通知公告 + */ + @PreAuthorize("@ss.hasPermi('system:notice:add')") + @Log(title = "通知公告", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysNotice notice) + { + notice.setCreateBy(getUsername()); + return toAjax(noticeService.insertNotice(notice)); + } + + /** + * 修改通知公告 + */ + @PreAuthorize("@ss.hasPermi('system:notice:edit')") + @Log(title = "通知公告", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysNotice notice) + { + notice.setUpdateBy(getUsername()); + return toAjax(noticeService.updateNotice(notice)); + } + + /** + * 删除通知公告 + */ + @PreAuthorize("@ss.hasPermi('system:notice:remove')") + @Log(title = "通知公告", businessType = BusinessType.DELETE) + @DeleteMapping("/{noticeIds}") + public AjaxResult remove(@PathVariable Long[] noticeIds) + { + return toAjax(noticeService.deleteNoticeByIds(noticeIds)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java new file mode 100644 index 0000000..3b1fd60 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java @@ -0,0 +1,130 @@ +package com.ruoyi.web.controller.system; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.system.domain.SysPost; +import com.ruoyi.system.service.ISysPostService; + +/** + * 岗位信息操作处理 + * + * @author #author# + */ +@RestController +@RequestMapping("/system/post") +public class SysPostController extends BaseController +{ + @Autowired + private ISysPostService postService; + + /** + * 获取岗位列表 + */ + @PreAuthorize("@ss.hasPermi('system:post:list')") + @GetMapping("/list") + public TableDataInfo list(SysPost post) + { + startPage(); + List list = postService.selectPostList(post); + return getDataTable(list); + } + + @Log(title = "岗位管理", businessType = BusinessType.EXPORT) + @PreAuthorize("@ss.hasPermi('system:post:export')") + @PostMapping("/export") + public void export(HttpServletResponse response, SysPost post) + { + List list = postService.selectPostList(post); + ExcelUtil util = new ExcelUtil(SysPost.class); + util.exportExcel(response, list, "岗位数据"); + } + + /** + * 根据岗位编号获取详细信息 + */ + @PreAuthorize("@ss.hasPermi('system:post:query')") + @GetMapping(value = "/{postId}") + public AjaxResult getInfo(@PathVariable Long postId) + { + return success(postService.selectPostById(postId)); + } + + /** + * 新增岗位 + */ + @PreAuthorize("@ss.hasPermi('system:post:add')") + @Log(title = "岗位管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysPost post) + { + if (UserConstants.NOT_UNIQUE.equals(postService.checkPostNameUnique(post))) + { + return error("新增岗位'" + post.getPostName() + "'失败,岗位名称已存在"); + } + else if (UserConstants.NOT_UNIQUE.equals(postService.checkPostCodeUnique(post))) + { + return error("新增岗位'" + post.getPostName() + "'失败,岗位编码已存在"); + } + post.setCreateBy(getUsername()); + return toAjax(postService.insertPost(post)); + } + + /** + * 修改岗位 + */ + @PreAuthorize("@ss.hasPermi('system:post:edit')") + @Log(title = "岗位管理", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysPost post) + { + if (UserConstants.NOT_UNIQUE.equals(postService.checkPostNameUnique(post))) + { + return error("修改岗位'" + post.getPostName() + "'失败,岗位名称已存在"); + } + else if (UserConstants.NOT_UNIQUE.equals(postService.checkPostCodeUnique(post))) + { + return error("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在"); + } + post.setUpdateBy(getUsername()); + return toAjax(postService.updatePost(post)); + } + + /** + * 删除岗位 + */ + @PreAuthorize("@ss.hasPermi('system:post:remove')") + @Log(title = "岗位管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{postIds}") + public AjaxResult remove(@PathVariable Long[] postIds) + { + return toAjax(postService.deletePostByIds(postIds)); + } + + /** + * 获取岗位选择框列表 + */ + @GetMapping("/optionselect") + public AjaxResult optionselect() + { + List posts = postService.selectPostAll(); + return success(posts); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java new file mode 100644 index 0000000..44914f5 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java @@ -0,0 +1,144 @@ +package com.ruoyi.web.controller.system; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.file.FileUploadUtils; +import com.ruoyi.common.utils.file.MimeTypeUtils; +import com.ruoyi.framework.web.service.TokenService; +import com.ruoyi.system.service.ISysUserService; + +/** + * 个人信息 业务处理 + * + * @author #author# + */ +@RestController +@RequestMapping("/system/user/profile") +public class SysProfileController extends BaseController +{ + @Autowired + private ISysUserService userService; + + @Autowired + private TokenService tokenService; + + /** + * 个人信息 + */ + @GetMapping + public AjaxResult profile() + { + LoginUser loginUser = getLoginUser(); + SysUser user = loginUser.getUser(); + AjaxResult ajax = AjaxResult.success(user); + ajax.put("roleGroup", userService.selectUserRoleGroup(loginUser.getUsername())); + ajax.put("postGroup", userService.selectUserPostGroup(loginUser.getUsername())); + return ajax; + } + + /** + * 修改用户 + */ + @Log(title = "个人信息", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult updateProfile(@RequestBody SysUser user) + { + LoginUser loginUser = getLoginUser(); + SysUser sysUser = loginUser.getUser(); + user.setUserName(sysUser.getUserName()); + if (StringUtils.isNotEmpty(user.getPhonenumber()) + && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) + { + return error("修改用户'" + user.getUserName() + "'失败,手机号码已存在"); + } + if (StringUtils.isNotEmpty(user.getEmail()) + && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) + { + return error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在"); + } + user.setUserId(sysUser.getUserId()); + user.setPassword(null); + user.setAvatar(null); + user.setDeptId(null); + if (userService.updateUserProfile(user) > 0) + { + // 更新缓存用户信息 + sysUser.setNickName(user.getNickName()); + sysUser.setPhonenumber(user.getPhonenumber()); + sysUser.setEmail(user.getEmail()); + sysUser.setSex(user.getSex()); + tokenService.setLoginUser(loginUser); + return success(); + } + return error("修改个人信息异常,请联系管理员"); + } + + /** + * 重置密码 + */ + @Log(title = "个人信息", businessType = BusinessType.UPDATE) + @PutMapping("/updatePwd") + public AjaxResult updatePwd(String oldPassword, String newPassword) + { + LoginUser loginUser = getLoginUser(); + String userName = loginUser.getUsername(); + String password = loginUser.getPassword(); + if (!SecurityUtils.matchesPassword(oldPassword, password)) + { + return error("修改密码失败,旧密码错误"); + } + if (SecurityUtils.matchesPassword(newPassword, password)) + { + return error("新密码不能与旧密码相同"); + } + if (userService.resetUserPwd(userName, SecurityUtils.encryptPassword(newPassword)) > 0) + { + // 更新缓存用户密码 + loginUser.getUser().setPassword(SecurityUtils.encryptPassword(newPassword)); + tokenService.setLoginUser(loginUser); + return success(); + } + return error("修改密码异常,请联系管理员"); + } + + /** + * 头像上传 + */ + @Log(title = "用户头像", businessType = BusinessType.UPDATE) + @PostMapping("/avatar") + public AjaxResult avatar(@RequestParam("avatarfile") MultipartFile file) throws Exception + { + if (!file.isEmpty()) + { + LoginUser loginUser = getLoginUser(); + String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file, MimeTypeUtils.IMAGE_EXTENSION); + if (userService.updateUserAvatar(loginUser.getUsername(), avatar)) + { + AjaxResult ajax = AjaxResult.success(); + ajax.put("imgUrl", avatar); + // 更新缓存用户头像 + loginUser.getUser().setAvatar(avatar); + tokenService.setLoginUser(loginUser); + return ajax; + } + } + return error("上传图片异常,请联系管理员"); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java new file mode 100644 index 0000000..244ea2f --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java @@ -0,0 +1,38 @@ +package com.ruoyi.web.controller.system; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.model.RegisterBody; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.framework.web.service.SysRegisterService; +import com.ruoyi.system.service.ISysConfigService; + +/** + * 注册验证 + * + * @author #author# + */ +@RestController +public class SysRegisterController extends BaseController +{ + @Autowired + private SysRegisterService registerService; + + @Autowired + private ISysConfigService configService; + + @PostMapping("/register") + public AjaxResult register(@RequestBody RegisterBody user) + { + if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser")))) + { + return error("当前系统没有开启注册功能!"); + } + String msg = registerService.register(user); + return StringUtils.isEmpty(msg) ? success() : error(msg); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java new file mode 100644 index 0000000..6f3d52f --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java @@ -0,0 +1,263 @@ +package com.ruoyi.web.controller.system; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysDept; +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.framework.web.service.SysPermissionService; +import com.ruoyi.framework.web.service.TokenService; +import com.ruoyi.system.domain.SysUserRole; +import com.ruoyi.system.service.ISysDeptService; +import com.ruoyi.system.service.ISysRoleService; +import com.ruoyi.system.service.ISysUserService; + +/** + * 角色信息 + * + * @author #author# + */ +@RestController +@RequestMapping("/system/role") +public class SysRoleController extends BaseController +{ + @Autowired + private ISysRoleService roleService; + + @Autowired + private TokenService tokenService; + + @Autowired + private SysPermissionService permissionService; + + @Autowired + private ISysUserService userService; + + @Autowired + private ISysDeptService deptService; + + @PreAuthorize("@ss.hasPermi('system:role:list')") + @GetMapping("/list") + public TableDataInfo list(SysRole role) + { + startPage(); + List list = roleService.selectRoleList(role); + return getDataTable(list); + } + + @Log(title = "角色管理", businessType = BusinessType.EXPORT) + @PreAuthorize("@ss.hasPermi('system:role:export')") + @PostMapping("/export") + public void export(HttpServletResponse response, SysRole role) + { + List list = roleService.selectRoleList(role); + ExcelUtil util = new ExcelUtil(SysRole.class); + util.exportExcel(response, list, "角色数据"); + } + + /** + * 根据角色编号获取详细信息 + */ + @PreAuthorize("@ss.hasPermi('system:role:query')") + @GetMapping(value = "/{roleId}") + public AjaxResult getInfo(@PathVariable Long roleId) + { + roleService.checkRoleDataScope(roleId); + return success(roleService.selectRoleById(roleId)); + } + + /** + * 新增角色 + */ + @PreAuthorize("@ss.hasPermi('system:role:add')") + @Log(title = "角色管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysRole role) + { + if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role))) + { + return error("新增角色'" + role.getRoleName() + "'失败,角色名称已存在"); + } + else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role))) + { + return error("新增角色'" + role.getRoleName() + "'失败,角色权限已存在"); + } + role.setCreateBy(getUsername()); + return toAjax(roleService.insertRole(role)); + + } + + /** + * 修改保存角色 + */ + @PreAuthorize("@ss.hasPermi('system:role:edit')") + @Log(title = "角色管理", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysRole role) + { + roleService.checkRoleAllowed(role); + roleService.checkRoleDataScope(role.getRoleId()); + if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role))) + { + return error("修改角色'" + role.getRoleName() + "'失败,角色名称已存在"); + } + else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role))) + { + return error("修改角色'" + role.getRoleName() + "'失败,角色权限已存在"); + } + role.setUpdateBy(getUsername()); + + if (roleService.updateRole(role) > 0) + { + // 更新缓存用户权限 + LoginUser loginUser = getLoginUser(); + if (StringUtils.isNotNull(loginUser.getUser()) && !loginUser.getUser().isAdmin()) + { + loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser())); + loginUser.setUser(userService.selectUserByUserName(loginUser.getUser().getUserName())); + tokenService.setLoginUser(loginUser); + } + return success(); + } + return error("修改角色'" + role.getRoleName() + "'失败,请联系管理员"); + } + + /** + * 修改保存数据权限 + */ + @PreAuthorize("@ss.hasPermi('system:role:edit')") + @Log(title = "角色管理", businessType = BusinessType.UPDATE) + @PutMapping("/dataScope") + public AjaxResult dataScope(@RequestBody SysRole role) + { + roleService.checkRoleAllowed(role); + roleService.checkRoleDataScope(role.getRoleId()); + return toAjax(roleService.authDataScope(role)); + } + + /** + * 状态修改 + */ + @PreAuthorize("@ss.hasPermi('system:role:edit')") + @Log(title = "角色管理", businessType = BusinessType.UPDATE) + @PutMapping("/changeStatus") + public AjaxResult changeStatus(@RequestBody SysRole role) + { + roleService.checkRoleAllowed(role); + roleService.checkRoleDataScope(role.getRoleId()); + role.setUpdateBy(getUsername()); + return toAjax(roleService.updateRoleStatus(role)); + } + + /** + * 删除角色 + */ + @PreAuthorize("@ss.hasPermi('system:role:remove')") + @Log(title = "角色管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{roleIds}") + public AjaxResult remove(@PathVariable Long[] roleIds) + { + return toAjax(roleService.deleteRoleByIds(roleIds)); + } + + /** + * 获取角色选择框列表 + */ + @PreAuthorize("@ss.hasPermi('system:role:query')") + @GetMapping("/optionselect") + public AjaxResult optionselect() + { + return success(roleService.selectRoleAll()); + } + + /** + * 查询已分配用户角色列表 + */ + @PreAuthorize("@ss.hasPermi('system:role:list')") + @GetMapping("/authUser/allocatedList") + public TableDataInfo allocatedList(SysUser user) + { + startPage(); + List list = userService.selectAllocatedList(user); + return getDataTable(list); + } + + /** + * 查询未分配用户角色列表 + */ + @PreAuthorize("@ss.hasPermi('system:role:list')") + @GetMapping("/authUser/unallocatedList") + public TableDataInfo unallocatedList(SysUser user) + { + startPage(); + List list = userService.selectUnallocatedList(user); + return getDataTable(list); + } + + /** + * 取消授权用户 + */ + @PreAuthorize("@ss.hasPermi('system:role:edit')") + @Log(title = "角色管理", businessType = BusinessType.GRANT) + @PutMapping("/authUser/cancel") + public AjaxResult cancelAuthUser(@RequestBody SysUserRole userRole) + { + return toAjax(roleService.deleteAuthUser(userRole)); + } + + /** + * 批量取消授权用户 + */ + @PreAuthorize("@ss.hasPermi('system:role:edit')") + @Log(title = "角色管理", businessType = BusinessType.GRANT) + @PutMapping("/authUser/cancelAll") + public AjaxResult cancelAuthUserAll(Long roleId, Long[] userIds) + { + return toAjax(roleService.deleteAuthUsers(roleId, userIds)); + } + + /** + * 批量选择用户授权 + */ + @PreAuthorize("@ss.hasPermi('system:role:edit')") + @Log(title = "角色管理", businessType = BusinessType.GRANT) + @PutMapping("/authUser/selectAll") + public AjaxResult selectAuthUserAll(Long roleId, Long[] userIds) + { + roleService.checkRoleDataScope(roleId); + return toAjax(roleService.insertAuthUsers(roleId, userIds)); + } + + /** + * 获取对应角色部门树列表 + */ + @PreAuthorize("@ss.hasPermi('system:role:query')") + @GetMapping(value = "/deptTree/{roleId}") + public AjaxResult deptTree(@PathVariable("roleId") Long roleId) + { + AjaxResult ajax = AjaxResult.success(); + ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId)); + ajax.put("depts", deptService.selectDeptTreeList(new SysDept())); + return ajax; + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java new file mode 100644 index 0000000..a71ee04 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java @@ -0,0 +1,256 @@ +package com.ruoyi.web.controller.system; + +import java.util.List; +import java.util.stream.Collectors; +import javax.servlet.http.HttpServletResponse; +import org.apache.commons.lang3.ArrayUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysDept; +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.system.service.ISysDeptService; +import com.ruoyi.system.service.ISysPostService; +import com.ruoyi.system.service.ISysRoleService; +import com.ruoyi.system.service.ISysUserService; + +/** + * 用户信息 + * + * @author #author# + */ +@RestController +@RequestMapping("/system/user") +public class SysUserController extends BaseController +{ + @Autowired + private ISysUserService userService; + + @Autowired + private ISysRoleService roleService; + + @Autowired + private ISysDeptService deptService; + + @Autowired + private ISysPostService postService; + + /** + * 获取用户列表 + */ + @PreAuthorize("@ss.hasPermi('system:user:list')") + @GetMapping("/list") + public TableDataInfo list(SysUser user) + { + startPage(); + List list = userService.selectUserList(user); + return getDataTable(list); + } + + @Log(title = "用户管理", businessType = BusinessType.EXPORT) + @PreAuthorize("@ss.hasPermi('system:user:export')") + @PostMapping("/export") + public void export(HttpServletResponse response, SysUser user) + { + List list = userService.selectUserList(user); + ExcelUtil util = new ExcelUtil(SysUser.class); + util.exportExcel(response, list, "用户数据"); + } + + @Log(title = "用户管理", businessType = BusinessType.IMPORT) + @PreAuthorize("@ss.hasPermi('system:user:import')") + @PostMapping("/importData") + public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception + { + ExcelUtil util = new ExcelUtil(SysUser.class); + List userList = util.importExcel(file.getInputStream()); + String operName = getUsername(); + String message = userService.importUser(userList, updateSupport, operName); + return success(message); + } + + @PostMapping("/importTemplate") + public void importTemplate(HttpServletResponse response) + { + ExcelUtil util = new ExcelUtil(SysUser.class); + util.importTemplateExcel(response, "用户数据"); + } + + /** + * 根据用户编号获取详细信息 + */ + @PreAuthorize("@ss.hasPermi('system:user:query')") + @GetMapping(value = { "/", "/{userId}" }) + public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId) + { + userService.checkUserDataScope(userId); + AjaxResult ajax = AjaxResult.success(); + List roles = roleService.selectRoleAll(); + ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); + ajax.put("posts", postService.selectPostAll()); + if (StringUtils.isNotNull(userId)) + { + SysUser sysUser = userService.selectUserById(userId); + ajax.put(AjaxResult.DATA_TAG, sysUser); + ajax.put("postIds", postService.selectPostListByUserId(userId)); + ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList())); + } + return ajax; + } + + /** + * 新增用户 + */ + @PreAuthorize("@ss.hasPermi('system:user:add')") + @Log(title = "用户管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody SysUser user) + { + if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user))) + { + return error("新增用户'" + user.getUserName() + "'失败,登录账号已存在"); + } + else if (StringUtils.isNotEmpty(user.getPhonenumber()) + && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) + { + return error("新增用户'" + user.getUserName() + "'失败,手机号码已存在"); + } + else if (StringUtils.isNotEmpty(user.getEmail()) + && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) + { + return error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在"); + } + user.setCreateBy(getUsername()); + user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); + return toAjax(userService.insertUser(user)); + } + + /** + * 修改用户 + */ + @PreAuthorize("@ss.hasPermi('system:user:edit')") + @Log(title = "用户管理", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody SysUser user) + { + userService.checkUserAllowed(user); + userService.checkUserDataScope(user.getUserId()); + if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user))) + { + return error("修改用户'" + user.getUserName() + "'失败,登录账号已存在"); + } + else if (StringUtils.isNotEmpty(user.getPhonenumber()) + && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) + { + return error("修改用户'" + user.getUserName() + "'失败,手机号码已存在"); + } + else if (StringUtils.isNotEmpty(user.getEmail()) + && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) + { + return error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在"); + } + user.setUpdateBy(getUsername()); + return toAjax(userService.updateUser(user)); + } + + /** + * 删除用户 + */ + @PreAuthorize("@ss.hasPermi('system:user:remove')") + @Log(title = "用户管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{userIds}") + public AjaxResult remove(@PathVariable Long[] userIds) + { + if (ArrayUtils.contains(userIds, getUserId())) + { + return error("当前用户不能删除"); + } + return toAjax(userService.deleteUserByIds(userIds)); + } + + /** + * 重置密码 + */ + @PreAuthorize("@ss.hasPermi('system:user:resetPwd')") + @Log(title = "用户管理", businessType = BusinessType.UPDATE) + @PutMapping("/resetPwd") + public AjaxResult resetPwd(@RequestBody SysUser user) + { + userService.checkUserAllowed(user); + userService.checkUserDataScope(user.getUserId()); + user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); + user.setUpdateBy(getUsername()); + return toAjax(userService.resetPwd(user)); + } + + /** + * 状态修改 + */ + @PreAuthorize("@ss.hasPermi('system:user:edit')") + @Log(title = "用户管理", businessType = BusinessType.UPDATE) + @PutMapping("/changeStatus") + public AjaxResult changeStatus(@RequestBody SysUser user) + { + userService.checkUserAllowed(user); + userService.checkUserDataScope(user.getUserId()); + user.setUpdateBy(getUsername()); + return toAjax(userService.updateUserStatus(user)); + } + + /** + * 根据用户编号获取授权角色 + */ + @PreAuthorize("@ss.hasPermi('system:user:query')") + @GetMapping("/authRole/{userId}") + public AjaxResult authRole(@PathVariable("userId") Long userId) + { + AjaxResult ajax = AjaxResult.success(); + SysUser user = userService.selectUserById(userId); + List roles = roleService.selectRolesByUserId(userId); + ajax.put("user", user); + ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); + return ajax; + } + + /** + * 用户授权角色 + */ + @PreAuthorize("@ss.hasPermi('system:user:edit')") + @Log(title = "用户管理", businessType = BusinessType.GRANT) + @PutMapping("/authRole") + public AjaxResult insertAuthRole(Long userId, Long[] roleIds) + { + userService.checkUserDataScope(userId); + userService.insertUserAuth(userId, roleIds); + return success(); + } + + /** + * 获取部门树列表 + */ + @PreAuthorize("@ss.hasPermi('system:user:list')") + @GetMapping("/deptTree") + public AjaxResult deptTree(SysDept dept) + { + return success(deptService.selectDeptTreeList(dept)); + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java new file mode 100644 index 0000000..2d0b4f5 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java @@ -0,0 +1,183 @@ +package com.ruoyi.web.controller.tool; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.R; +import com.ruoyi.common.utils.StringUtils; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import io.swagger.annotations.ApiOperation; + +/** + * swagger 用户测试方法 + * + * @author #author# + */ +@Api("用户信息管理") +@RestController +@RequestMapping("/test/user") +public class TestController extends BaseController +{ + private final static Map users = new LinkedHashMap(); + { + users.put(1, new UserEntity(1, "admin", "admin123", "15888888888")); + users.put(2, new UserEntity(2, "ry", "admin123", "15666666666")); + } + + @ApiOperation("获取用户列表") + @GetMapping("/list") + public R> userList() + { + List userList = new ArrayList(users.values()); + return R.ok(userList); + } + + @ApiOperation("获取用户详细") + @ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class) + @GetMapping("/{userId}") + public R getUser(@PathVariable Integer userId) + { + if (!users.isEmpty() && users.containsKey(userId)) + { + return R.ok(users.get(userId)); + } + else + { + return R.fail("用户不存在"); + } + } + + @ApiOperation("新增用户") + @ApiImplicitParams({ + @ApiImplicitParam(name = "userId", value = "用户id", dataType = "Integer", dataTypeClass = Integer.class), + @ApiImplicitParam(name = "username", value = "用户名称", dataType = "String", dataTypeClass = String.class), + @ApiImplicitParam(name = "password", value = "用户密码", dataType = "String", dataTypeClass = String.class), + @ApiImplicitParam(name = "mobile", value = "用户手机", dataType = "String", dataTypeClass = String.class) + }) + @PostMapping("/save") + public R save(UserEntity user) + { + if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId())) + { + return R.fail("用户ID不能为空"); + } + users.put(user.getUserId(), user); + return R.ok(); + } + + @ApiOperation("更新用户") + @PutMapping("/update") + public R update(@RequestBody UserEntity user) + { + if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId())) + { + return R.fail("用户ID不能为空"); + } + if (users.isEmpty() || !users.containsKey(user.getUserId())) + { + return R.fail("用户不存在"); + } + users.remove(user.getUserId()); + users.put(user.getUserId(), user); + return R.ok(); + } + + @ApiOperation("删除用户信息") + @ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class) + @DeleteMapping("/{userId}") + public R delete(@PathVariable Integer userId) + { + if (!users.isEmpty() && users.containsKey(userId)) + { + users.remove(userId); + return R.ok(); + } + else + { + return R.fail("用户不存在"); + } + } +} + +@ApiModel(value = "UserEntity", description = "用户实体") +class UserEntity +{ + @ApiModelProperty("用户ID") + private Integer userId; + + @ApiModelProperty("用户名称") + private String username; + + @ApiModelProperty("用户密码") + private String password; + + @ApiModelProperty("用户手机") + private String mobile; + + public UserEntity() + { + + } + + public UserEntity(Integer userId, String username, String password, String mobile) + { + this.userId = userId; + this.username = username; + this.password = password; + this.mobile = mobile; + } + + public Integer getUserId() + { + return userId; + } + + public void setUserId(Integer userId) + { + this.userId = userId; + } + + public String getUsername() + { + return username; + } + + public void setUsername(String username) + { + this.username = username; + } + + public String getPassword() + { + return password; + } + + public void setPassword(String password) + { + this.password = password; + } + + public String getMobile() + { + return mobile; + } + + public void setMobile(String mobile) + { + this.mobile = mobile; + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java b/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java new file mode 100644 index 0000000..7950a54 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java @@ -0,0 +1,125 @@ +package com.ruoyi.web.core.config; + +import java.util.ArrayList; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import com.ruoyi.common.config.RuoYiConfig; +import io.swagger.annotations.ApiOperation; +import io.swagger.models.auth.In; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.ApiKey; +import springfox.documentation.service.AuthorizationScope; +import springfox.documentation.service.Contact; +import springfox.documentation.service.SecurityReference; +import springfox.documentation.service.SecurityScheme; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spi.service.contexts.SecurityContext; +import springfox.documentation.spring.web.plugins.Docket; + +/** + * Swagger2的接口配置 + * + * @author #author# + */ +@Configuration +public class SwaggerConfig +{ + /** 系统基础配置 */ + @Autowired + private RuoYiConfig ruoyiConfig; + + /** 是否开启swagger */ + @Value("${swagger.enabled}") + private boolean enabled; + + /** 设置请求的统一前缀 */ + @Value("${swagger.pathMapping}") + private String pathMapping; + + /** + * 创建API + */ + @Bean + public Docket createRestApi() + { + return new Docket(DocumentationType.OAS_30) + // 是否启用Swagger + .enable(enabled) + // 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息) + .apiInfo(apiInfo()) + // 设置哪些接口暴露给Swagger展示 + .select() + // 扫描所有有注解的api,用这种方式更灵活 + .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) + // 扫描指定包中的swagger注解 + // .apis(RequestHandlerSelectors.basePackage("com.ruoyi.project.tool.swagger")) + // 扫描所有 .apis(RequestHandlerSelectors.any()) + .paths(PathSelectors.any()) + .build() + /* 设置安全模式,swagger可以设置访问token */ + .securitySchemes(securitySchemes()) + .securityContexts(securityContexts()) + .pathMapping(pathMapping); + } + + /** + * 安全模式,这里指定token通过Authorization头请求头传递 + */ + private List securitySchemes() + { + List apiKeyList = new ArrayList(); + apiKeyList.add(new ApiKey("Authorization", "Authorization", In.HEADER.toValue())); + return apiKeyList; + } + + /** + * 安全上下文 + */ + private List securityContexts() + { + List securityContexts = new ArrayList<>(); + securityContexts.add( + SecurityContext.builder() + .securityReferences(defaultAuth()) + .operationSelector(o -> o.requestMappingPattern().matches("/.*")) + .build()); + return securityContexts; + } + + /** + * 默认的安全上引用 + */ + private List defaultAuth() + { + AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything"); + AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; + authorizationScopes[0] = authorizationScope; + List securityReferences = new ArrayList<>(); + securityReferences.add(new SecurityReference("Authorization", authorizationScopes)); + return securityReferences; + } + + /** + * 添加摘要信息 + */ + private ApiInfo apiInfo() + { + // 用ApiInfoBuilder进行定制 + return new ApiInfoBuilder() + // 设置标题 + .title("标题:管理系统_接口文档") + // 描述 + .description("接口文档") + // 作者信息 + .contact(new Contact(ruoyiConfig.getName(), null, null)) + // 版本 + .version("版本号:" + ruoyiConfig.getVersion()) + .build(); + } +} diff --git a/ruoyi-admin/src/main/resources/META-INF/spring-devtools.properties b/ruoyi-admin/src/main/resources/META-INF/spring-devtools.properties new file mode 100644 index 0000000..2b23f85 --- /dev/null +++ b/ruoyi-admin/src/main/resources/META-INF/spring-devtools.properties @@ -0,0 +1 @@ +restart.include.json=/com.alibaba.fastjson.*.jar \ No newline at end of file diff --git a/ruoyi-admin/src/main/resources/application-druid.yml b/ruoyi-admin/src/main/resources/application-druid.yml new file mode 100644 index 0000000..7cb8fa0 --- /dev/null +++ b/ruoyi-admin/src/main/resources/application-druid.yml @@ -0,0 +1,57 @@ +# 数据源配置 +spring: + datasource: + type: com.alibaba.druid.pool.DruidDataSource + driverClassName: com.mysql.cj.jdbc.Driver + druid: + # 主库数据源 + master: + url: jdbc:mysql://192.168.124.67:3306/dba?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 + username: dba + password: 123456 + # 从库数据源 + slave: + # 从数据源开关/默认关闭 + enabled: false + url: + username: + password: + # 初始连接数 + initialSize: 5 + # 最小连接池数量 + minIdle: 10 + # 最大连接池数量 + maxActive: 20 + # 配置获取连接等待超时的时间 + maxWait: 60000 + # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 + timeBetweenEvictionRunsMillis: 60000 + # 配置一个连接在池中最小生存的时间,单位是毫秒 + minEvictableIdleTimeMillis: 300000 + # 配置一个连接在池中最大生存的时间,单位是毫秒 + maxEvictableIdleTimeMillis: 900000 + # 配置检测连接是否有效 + validationQuery: SELECT 1 FROM DUAL + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + webStatFilter: + enabled: true + statViewServlet: + enabled: true + # 设置白名单,不填则允许所有访问 + allow: + url-pattern: /druid/* + # 控制台管理用户名和密码 + login-username: ruoyi + login-password: 123456 + filter: + stat: + enabled: true + # 慢SQL记录 + log-slow-sql: true + slow-sql-millis: 1000 + merge-sql: true + wall: + config: + multi-statement-allow: true \ No newline at end of file diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml new file mode 100644 index 0000000..b841603 --- /dev/null +++ b/ruoyi-admin/src/main/resources/application.yml @@ -0,0 +1,139 @@ +# 项目相关配置 +ruoyi: + # 名称 + name: #author# + # 版本 + version: 3.8.5 + # 版权年份 + copyrightYear: 2023 + # 实例演示开关 + demoEnabled: true + # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath) + profile: D:/poject/log/uploadPath + # 获取ip地址开关 + addressEnabled: false + # 验证码类型 math 数组计算 char 字符验证 + captchaType: math + +# 开发环境配置 +server: + # 服务器的HTTP端口,默认为8080 + port: 9000 + servlet: + # 应用的访问路径 + context-path: / + tomcat: + # tomcat的URI编码 + uri-encoding: UTF-8 + # 连接数满后的排队数,默认为100 + accept-count: 1000 + threads: + # tomcat最大线程数,默认为200 + max: 800 + # Tomcat启动初始化的线程数,默认值10 + min-spare: 100 + +# 日志配置 +logging: + level: + com.ruoyi: debug + org.springframework: warn + +# 用户配置 +user: + password: + # 密码最大错误次数 + maxRetryCount: 5 + # 密码锁定时间(默认10分钟) + lockTime: 10 + +# Spring配置 +spring: + # 资源信息 + messages: + # 国际化资源文件路径 + basename: i18n/messages + profiles: + active: druid + # 文件上传 + servlet: + multipart: + # 单个文件大小 + max-file-size: 10MB + # 设置总上传的文件大小 + max-request-size: 20MB + # 服务模块 + devtools: + restart: + # 热部署开关 + enabled: true + # redis 配置 + redis: + # 地址 + host: 192.168.124.67 + # 端口,默认为6379 + port: 6379 + # 数据库索引 + database: 0 + # 密码 + password: 123456 + # 连接超时时间 + timeout: 10s + lettuce: + pool: + # 连接池中的最小空闲连接 + min-idle: 0 + # 连接池中的最大空闲连接 + max-idle: 8 + # 连接池的最大数据库连接数 + max-active: 8 + # #连接池最大阻塞等待时间(使用负值表示没有限制) + max-wait: -1ms + +# token配置 +token: + # 令牌自定义标识 + header: Authorization + # 令牌密钥 + secret: abcdefghijklmnopqrstuvwxyz + # 令牌有效期(默认30分钟) + expireTime: 30 + + + +# MyBatis Plus配置 +mybatis-plus: + # 搜索指定包别名 + typeAliasesPackage: com.ruoyi.**.domain,com.ruoyi.**.vo.domain + # 配置mapper的扫描,找到所有的mapper.xml映射文件 + mapperLocations: classpath*:mapper/**/*Mapper.xml + # 加载全局的配置文件 + configLocation: classpath:mybatis/mybatis-config.xml + global-config: + db-config: + logic-delete-field: deleted # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2) + logic-delete-value: UNIX_TIMESTAMP() # 逻辑已删除值(默认为 时间戳) + logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) + + +# PageHelper分页插件 +pagehelper: + helperDialect: mysql + supportMethodsArguments: true + params: count=countSql + +# Swagger配置 +swagger: + # 是否开启swagger + enabled: true + # 请求前缀 + pathMapping: /dev-api + +# 防止XSS攻击 +xss: + # 过滤开关 + enabled: true + # 排除链接(多个用逗号分隔) + excludes: /system/notice + # 匹配链接 + urlPatterns: /system/*,/monitor/*,/tool/* diff --git a/ruoyi-admin/src/main/resources/banner.txt b/ruoyi-admin/src/main/resources/banner.txt new file mode 100644 index 0000000..0931cb8 --- /dev/null +++ b/ruoyi-admin/src/main/resources/banner.txt @@ -0,0 +1,24 @@ +Application Version: ${ruoyi.version} +Spring Boot Version: ${spring-boot.version} +//////////////////////////////////////////////////////////////////// +// _ooOoo_ // +// o8888888o // +// 88" . "88 // +// (| ^_^ |) // +// O\ = /O // +// ____/`---'\____ // +// .' \\| |// `. // +// / \\||| : |||// \ // +// / _||||| -:- |||||- \ // +// | | \\\ - /// | | // +// | \_| ''\---/'' | | // +// \ .-\__ `-` ___/-. / // +// ___`. .' /--.--\ `. . ___ // +// ."" '< `.___\_<|>_/___.' >'"". // +// | | : `- \`.;`\ _ /`;.`/ - ` : | | // +// \ \ `-. \_ __\ /__ _/ .-` / / // +// ========`-.____`-.___\_____/___.-`____.-'======== // +// `=---=' // +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // +// 佛祖保佑 永不宕机 永无BUG // +//////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/ruoyi-admin/src/main/resources/i18n/messages.properties b/ruoyi-admin/src/main/resources/i18n/messages.properties new file mode 100644 index 0000000..4098fc9 --- /dev/null +++ b/ruoyi-admin/src/main/resources/i18n/messages.properties @@ -0,0 +1,37 @@ +#错误消息 +not.null=* 必须填写 +user.jcaptcha.error=验证码错误 +user.jcaptcha.expire=验证码已失效 +user.not.exists=用户不存在/密码错误 +user.password.not.match=用户不存在/密码错误 +user.password.retry.limit.count=密码输入错误{0}次 +user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定{1}分钟 +user.password.delete=对不起,您的账号已被删除 +user.blocked=用户已封禁,请联系管理员 +role.blocked=角色已封禁,请联系管理员 +user.logout.success=退出成功 + +length.not.valid=长度必须在{min}到{max}个字符之间 + +user.username.not.valid=* 2到20个汉字、字母、数字或下划线组成,且必须以非数字开头 +user.password.not.valid=* 5-50个字符 + +user.email.not.valid=邮箱格式错误 +user.mobile.phone.number.not.valid=手机号格式错误 +user.login.success=登录成功 +user.register.success=注册成功 +user.notfound=请重新登录 +user.forcelogout=管理员强制退出,请重新登录 +user.unknown.error=未知错误,请重新登录 + +##文件上传消息 +upload.exceed.maxSize=上传的文件大小超出限制的文件大小!
允许的文件最大大小是:{0}MB! +upload.filename.exceed.length=上传的文件名最长{0}个字符 + +##权限 +no.permission=您没有数据的权限,请联系管理员添加权限 [{0}] +no.create.permission=您没有创建数据的权限,请联系管理员添加权限 [{0}] +no.update.permission=您没有修改数据的权限,请联系管理员添加权限 [{0}] +no.delete.permission=您没有删除数据的权限,请联系管理员添加权限 [{0}] +no.export.permission=您没有导出数据的权限,请联系管理员添加权限 [{0}] +no.view.permission=您没有查看数据的权限,请联系管理员添加权限 [{0}] diff --git a/ruoyi-admin/src/main/resources/logback.xml b/ruoyi-admin/src/main/resources/logback.xml new file mode 100644 index 0000000..bec4598 --- /dev/null +++ b/ruoyi-admin/src/main/resources/logback.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + ${log.pattern} + + + + + + ${log.path}/sys-info.log + + + + ${log.path}/sys-info.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + INFO + + ACCEPT + + DENY + + + + + ${log.path}/sys-error.log + + + + ${log.path}/sys-error.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + ERROR + + ACCEPT + + DENY + + + + + + ${log.path}/sys-user.log + + + ${log.path}/sys-user.%d{yyyy-MM-dd}.log + + 60 + + + ${log.pattern} + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml b/ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml new file mode 100644 index 0000000..ac47c03 --- /dev/null +++ b/ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + diff --git a/ruoyi-business/pom.xml b/ruoyi-business/pom.xml new file mode 100644 index 0000000..db4d1fa --- /dev/null +++ b/ruoyi-business/pom.xml @@ -0,0 +1,28 @@ + + + + ruoyi + com.ruoyi + 3.8.5 + + 4.0.0 + + ruoyi-business + + + business业务模块 + + + + + + + com.ruoyi + ruoyi-common + + + + + \ No newline at end of file diff --git a/ruoyi-business/src/main/java/com/ruoyi/business/controller/BusinessSurveyController.java b/ruoyi-business/src/main/java/com/ruoyi/business/controller/BusinessSurveyController.java new file mode 100644 index 0000000..febed77 --- /dev/null +++ b/ruoyi-business/src/main/java/com/ruoyi/business/controller/BusinessSurveyController.java @@ -0,0 +1,138 @@ +package com.ruoyi.business.controller; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; + +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.ruoyi.business.domain.BusinessTemplate; +import com.ruoyi.business.domain.BusinessTemplateProp; +import com.ruoyi.business.domain.BusinessTemplatePropValue; +import com.ruoyi.business.service.IBusinessTemplatePropService; +import com.ruoyi.business.service.IBusinessTemplateService; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.business.domain.BusinessSurvey; +import com.ruoyi.business.service.IBusinessSurveyService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import java.util.Arrays; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 调查问卷管理Controller + * + * @author ruoyi + * @date 2024-04-01 + */ +@RestController +@RequestMapping("/business/survey") +public class BusinessSurveyController extends BaseController +{ + @Autowired + private IBusinessSurveyService businessSurveyService; + + + /** + * 获取问卷属性 + */ + @GetMapping("/listBySurveyId") + public AjaxResult listBySurveyId(String surveyId) { + return businessSurveyService.listBySurveyId(surveyId); + } + + + + /** + * 查询调查问卷管理列表 + */ + @PreAuthorize("@ss.hasPermi('business:survey:list')") + @GetMapping("/list") + public TableDataInfo list(BusinessSurvey businessSurvey) + { + startPage(); + List list = businessSurveyService.lambdaQuery() + .eq(StringUtils.isNotEmpty(businessSurvey.getTitle()),BusinessSurvey::getTitle,businessSurvey.getTitle()) + .eq(StringUtils.isNotBlank(businessSurvey.getOpen()),BusinessSurvey::getOpen,businessSurvey.getOpen()).list(); + return getDataTable(list); + } + + /** + * 导出调查问卷管理列表 + */ + @PreAuthorize("@ss.hasPermi('business:survey:export')") + @Log(title = "调查问卷管理", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HttpServletResponse response, BusinessSurvey businessSurvey) + { + List list = businessSurveyService.list(); + ExcelUtil util = new ExcelUtil(BusinessSurvey.class); + util.exportExcel(response, list, "调查问卷管理数据"); + } + + /** + * 获取调查问卷管理详细信息 + */ + @PreAuthorize("@ss.hasPermi('business:survey:query')") + @GetMapping(value = "/{id}") + public AjaxResult getInfo(@PathVariable("id") Long id) + { + return success(businessSurveyService.getById(id)); + } + @Autowired + private IBusinessTemplateService businessTemplateService; + /** + * 新增调查问卷管理 + */ + @PreAuthorize("@ss.hasPermi('business:survey:add')") + @Log(title = "调查问卷管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody BusinessSurvey businessSurvey) + { + BusinessTemplate one = businessTemplateService.lambdaQuery().eq(BusinessTemplate::getId, businessSurvey.getTempId()).one(); + businessSurvey.setTempName(one.getTitle()); + return toAjax(businessSurveyService.save(businessSurvey)); + } + + /** + * 修改调查问卷管理 + */ + @PreAuthorize("@ss.hasPermi('business:survey:edit')") + @Log(title = "调查问卷管理", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody BusinessSurvey businessSurvey) + { + BusinessTemplate one = businessTemplateService.lambdaQuery().eq(BusinessTemplate::getId, businessSurvey.getTempId()).one(); + businessSurvey.setTempName(one.getTitle()); + return toAjax(businessSurveyService.updateById(businessSurvey)); + } + + /** + * 删除调查问卷管理 + */ + @PreAuthorize("@ss.hasPermi('business:survey:remove')") + @Log(title = "调查问卷管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public AjaxResult remove(@PathVariable Long[] ids) + { + return toAjax(businessSurveyService.removeByIds(Arrays.asList(ids))); + } +} diff --git a/ruoyi-business/src/main/java/com/ruoyi/business/controller/BusinessTemplateController.java b/ruoyi-business/src/main/java/com/ruoyi/business/controller/BusinessTemplateController.java new file mode 100644 index 0000000..7c3373b --- /dev/null +++ b/ruoyi-business/src/main/java/com/ruoyi/business/controller/BusinessTemplateController.java @@ -0,0 +1,138 @@ +package com.ruoyi.business.controller; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.ruoyi.business.domain.BusinessSurvey; +import com.ruoyi.business.service.IBusinessSurveyService; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.business.domain.BusinessTemplate; +import com.ruoyi.business.service.IBusinessTemplateService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import java.util.Arrays; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 模版管理Controller + * + * @author ruoyi + * @date 2024-03-31 + */ +@RestController +@RequestMapping("/business/template") +public class BusinessTemplateController extends BaseController +{ + @Autowired + private IBusinessTemplateService businessTemplateService; + + /** + * 查询模版管理列表 + */ + @PreAuthorize("@ss.hasPermi('business:template:list')") + @GetMapping("/list") + public TableDataInfo list(BusinessTemplate businessTemplate) + { + startPage(); + LambdaQueryWrapper like = new LambdaQueryWrapper() + .eq(StringUtils.isNotBlank( businessTemplate.getOpen()),BusinessTemplate::getOpen, businessTemplate.getOpen()) + .like(StringUtils.isNotBlank(businessTemplate.getTitle()), BusinessTemplate::getTitle, businessTemplate.getTitle()); + if(businessTemplate.getCreateBy() != null){ + logger.debug("SecurityUtils.getUsername():{}",SecurityUtils.getUsername()); + like.eq(BusinessTemplate::getCreateBy, SecurityUtils.getUsername()); + } + List list = businessTemplateService.list(like); + return getDataTable(list); + } + + /** + * 查询模版管理列表 + */ + @PreAuthorize("@ss.hasPermi('business:template:list')") + @GetMapping("/listAll") + public AjaxResult listAll(BusinessTemplate businessTemplate) + { + List list = businessTemplateService.list( + new LambdaQueryWrapper().eq(BusinessTemplate::getCreateBy,SecurityUtils.getUsername()) + .eq(StringUtils.isNotBlank(businessTemplate.getId()),BusinessTemplate::getId,businessTemplate.getId()) + ); + return AjaxResult.success(list); + } + + /** + * 导出模版管理列表 + */ + @PreAuthorize("@ss.hasPermi('business:template:export')") + @Log(title = "模版管理", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HttpServletResponse response, BusinessTemplate businessTemplate) + { + List list = businessTemplateService.list(); + ExcelUtil util = new ExcelUtil(BusinessTemplate.class); + util.exportExcel(response, list, "模版管理数据"); + } + + /** + * 获取模版管理详细信息 + */ + @PreAuthorize("@ss.hasPermi('business:template:query')") + @GetMapping(value = "/{id}") + public AjaxResult getInfo(@PathVariable("id") Long id) + { + return success(businessTemplateService.getById(id)); + } + + + /** + * 新增模版管理 + */ + @PreAuthorize("@ss.hasPermi('business:template:add')") + @Log(title = "模版管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody BusinessTemplate businessTemplate) + { + return toAjax(businessTemplateService.save(businessTemplate)); + } + + @Autowired + private IBusinessSurveyService businessSurveyService; + /** + * 修改模版管理 + */ + @PreAuthorize("@ss.hasPermi('business:template:edit')") + @Log(title = "模版管理", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody BusinessTemplate businessTemplate) + { + BusinessSurvey businessSurvey = new BusinessSurvey(); + businessSurvey.setTempName(businessTemplate.getTitle()); + businessSurveyService.lambdaUpdate().eq(BusinessSurvey::getTempId, businessTemplate.getId()).update(businessSurvey); + return toAjax(businessTemplateService.updateById(businessTemplate)); + } + + /** + * 删除模版管理 + */ + @PreAuthorize("@ss.hasPermi('business:template:remove')") + @Log(title = "模版管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public AjaxResult remove(@PathVariable Long[] ids) + { + return toAjax(businessTemplateService.removeByIds(Arrays.asList(ids))); + } +} diff --git a/ruoyi-business/src/main/java/com/ruoyi/business/controller/BusinessTemplatePropController.java b/ruoyi-business/src/main/java/com/ruoyi/business/controller/BusinessTemplatePropController.java new file mode 100644 index 0000000..47c35b6 --- /dev/null +++ b/ruoyi-business/src/main/java/com/ruoyi/business/controller/BusinessTemplatePropController.java @@ -0,0 +1,121 @@ +package com.ruoyi.business.controller; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.ruoyi.business.domain.BusinessTemplatePropValue; +import com.ruoyi.business.service.IBusinessTemplatePropValueService; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.business.domain.BusinessTemplateProp; +import com.ruoyi.business.service.IBusinessTemplatePropService; +import com.ruoyi.common.utils.poi.ExcelUtil; + +import java.util.Arrays; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 模版属性Controller + * + * @author ruoyi + * @date 2024-03-31 + */ +@RestController +@RequestMapping("/business/templateProp") +public class BusinessTemplatePropController extends BaseController { + @Autowired + private IBusinessTemplatePropService businessTemplatePropService; + + @Autowired + private IBusinessTemplatePropValueService businessTemplatePropValueService; + + + /** + * 查询模版属性列表 + */ + @PreAuthorize("@ss.hasPermi('business:templateProp:list')") + @GetMapping("/list") + public TableDataInfo list(BusinessTemplateProp businessTemplateProp) { + startPage(); + List list = businessTemplatePropService.list(new LambdaQueryWrapper() + .eq(StringUtils.isNotBlank(businessTemplateProp.getCompType()),BusinessTemplateProp::getCompType,businessTemplateProp.getCompType()) + .eq(StringUtils.isNotBlank(businessTemplateProp.getFieldName()),BusinessTemplateProp::getFieldName,businessTemplateProp.getFieldName()) + .eq(StringUtils.isNotBlank(businessTemplateProp.getId()),BusinessTemplateProp::getId,businessTemplateProp.getId()) + .eq(BusinessTemplateProp::getTempId,businessTemplateProp.getTempId()) + ); + return getDataTable(list); + } + + /** + * 导出模版属性列表 + */ + @PreAuthorize("@ss.hasPermi('business:templateProp:export')") + @Log(title = "模版属性" , businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HttpServletResponse response, BusinessTemplateProp businessTemplateProp) { + List list = businessTemplatePropService.list(); + ExcelUtil util = new ExcelUtil(BusinessTemplateProp.class); + util.exportExcel(response, list, "模版属性数据"); + } + + /** + * 获取模版属性详细信息 + */ + @PreAuthorize("@ss.hasPermi('business:templateProp:query')") + @GetMapping(value = "/{id}") + public AjaxResult getInfo(@PathVariable("id") Long id) { + return success(businessTemplatePropService.getById(id)); + } + + /** + * 新增模版属性 + */ + @PreAuthorize("@ss.hasPermi('business:templateProp:add')") + @Log(title = "模版属性" , businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody BusinessTemplateProp businessTemplateProp) { + return toAjax(businessTemplatePropService.save(businessTemplateProp)); + } + + /** + * 修改模版属性 + */ + @PreAuthorize("@ss.hasPermi('business:templateProp:edit')") + @Log(title = "模版属性" , businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody BusinessTemplateProp businessTemplateProp) { + return toAjax(businessTemplatePropService.updateById(businessTemplateProp)); + } + + /** + * 删除模版属性 + */ + @PreAuthorize("@ss.hasPermi('business:templateProp:remove')") + @Log(title = "模版属性" , businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public AjaxResult remove(@PathVariable Long[] ids) { + return toAjax(businessTemplatePropService.removeByIds(Arrays.asList(ids))); + } +} diff --git a/ruoyi-business/src/main/java/com/ruoyi/business/controller/BusinessTemplatePropValueController.java b/ruoyi-business/src/main/java/com/ruoyi/business/controller/BusinessTemplatePropValueController.java new file mode 100644 index 0000000..73205c8 --- /dev/null +++ b/ruoyi-business/src/main/java/com/ruoyi/business/controller/BusinessTemplatePropValueController.java @@ -0,0 +1,128 @@ +package com.ruoyi.business.controller; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.business.domain.BusinessTemplatePropValue; +import com.ruoyi.business.service.IBusinessTemplatePropValueService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import java.util.Arrays; +import java.util.Map; + +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 模版属性值Controller + * + * @author ruoyi + * @date 2024-03-31 + */ +@RestController +@RequestMapping("/business/templatePropValue") +public class BusinessTemplatePropValueController extends BaseController +{ + @Autowired + private IBusinessTemplatePropValueService businessTemplatePropValueService; + + /** + * 查询模版属性值列表 + */ + @PreAuthorize("@ss.hasPermi('business:templatePropValue:list')") + @GetMapping("/list") + public TableDataInfo list(BusinessTemplatePropValue businessTemplatePropValue) + { + startPage(); + List list = businessTemplatePropValueService.list(); + return getDataTable(list); + } + + /** + * 统计问卷 + */ + @GetMapping("/countGroup") + public AjaxResult countGroup(String surveyId) + { + Object o = businessTemplatePropValueService.countGroup(surveyId); + return AjaxResult.success(o); + } + + /** + * 导出模版属性值列表 + */ + @PreAuthorize("@ss.hasPermi('business:templatePropValue:export')") + @Log(title = "模版属性值", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HttpServletResponse response, BusinessTemplatePropValue businessTemplatePropValue) + { + List list = businessTemplatePropValueService.list(); + ExcelUtil util = new ExcelUtil(BusinessTemplatePropValue.class); + util.exportExcel(response, list, "模版属性值数据"); + } + + /** + * 获取模版属性值详细信息 + */ + @PreAuthorize("@ss.hasPermi('business:templatePropValue:query')") + @GetMapping(value = "/{id}") + public AjaxResult getInfo(@PathVariable("id") Long id) + { + return success(businessTemplatePropValueService.getById(id)); + } + + /** + * 新增模版属性值 + */ + @PreAuthorize("@ss.hasPermi('business:templatePropValue:add')") + @Log(title = "模版属性值", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody BusinessTemplatePropValue businessTemplatePropValue) + { + return toAjax(businessTemplatePropValueService.save(businessTemplatePropValue)); + } + + + /** + * 新增模版属性值 + */ + @Log(title = "模版属性值", businessType = BusinessType.INSERT) + @PostMapping("/addList") + public AjaxResult addList(@RequestBody Map data) + { + return toAjax(businessTemplatePropValueService.addList(data)); + } + + /** + * 修改模版属性值 + */ + @PreAuthorize("@ss.hasPermi('business:templatePropValue:edit')") + @Log(title = "模版属性值", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody BusinessTemplatePropValue businessTemplatePropValue) + { + return toAjax(businessTemplatePropValueService.updateById(businessTemplatePropValue)); + } + + /** + * 删除模版属性值 + */ + @PreAuthorize("@ss.hasPermi('business:templatePropValue:remove')") + @Log(title = "模版属性值", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public AjaxResult remove(@PathVariable Long[] ids) + { + return toAjax(businessTemplatePropValueService.removeByIds(Arrays.asList(ids))); + } +} diff --git a/ruoyi-business/src/main/java/com/ruoyi/business/domain/BusinessSurvey.java b/ruoyi-business/src/main/java/com/ruoyi/business/domain/BusinessSurvey.java new file mode 100644 index 0000000..2d11671 --- /dev/null +++ b/ruoyi-business/src/main/java/com/ruoyi/business/domain/BusinessSurvey.java @@ -0,0 +1,64 @@ +package com.ruoyi.business.domain; + +import lombok.Data; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +import java.util.ArrayList; + +/** + * 调查问卷管理对象 business_survey + * + * @author ruoyi + * @date 2024-04-01 + */ +@Data +public class BusinessSurvey extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + + + /** 问卷名称 */ + @Excel(name = "问卷名称") + private String title; + + + /** 问卷描述 */ + @Excel(name = "问卷描述") + private String context; + + + /** 模板id */ + @Excel(name = "模板id") + private String tempId; + + + /** 模板名称 */ + @Excel(name = "模板名称") + private String tempName; + + + /** 是否开放 */ + @Excel(name = "是否开放") + private String open; + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("title", getTitle()) + .append("context", getContext()) + .append("tempId", getTempId()) + .append("open", getOpen()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("deleted", getDeleted()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/ruoyi-business/src/main/java/com/ruoyi/business/domain/BusinessTemplate.java b/ruoyi-business/src/main/java/com/ruoyi/business/domain/BusinessTemplate.java new file mode 100644 index 0000000..004332e --- /dev/null +++ b/ruoyi-business/src/main/java/com/ruoyi/business/domain/BusinessTemplate.java @@ -0,0 +1,73 @@ +package com.ruoyi.business.domain; + +import lombok.Data; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 模版管理对象 business_template + * + * @author ruoyi + * @date 2024-03-31 + */ +@Data +public class BusinessTemplate extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 标题 */ + @Excel(name = "标题") + private String title; + + + /** 内容 */ + @Excel(name = "内容") + private String context; + + + /** 是否开放 */ + @Excel(name = "是否开放") + private String open; + + + public void setTitle(String title) + { + this.title = title; + } + + public String getTitle() + { + return title; + } + public void setContext(String context) + { + this.context = context; + } + + public String getContext() + { + return context; + } + public void setOpen(String open) + { + this.open = open; + } + + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("title", getTitle()) + .append("context", getContext()) + .append("open", getOpen()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/ruoyi-business/src/main/java/com/ruoyi/business/domain/BusinessTemplateProp.java b/ruoyi-business/src/main/java/com/ruoyi/business/domain/BusinessTemplateProp.java new file mode 100644 index 0000000..b1f8e3a --- /dev/null +++ b/ruoyi-business/src/main/java/com/ruoyi/business/domain/BusinessTemplateProp.java @@ -0,0 +1,182 @@ +package com.ruoyi.business.domain; + +import com.alibaba.fastjson2.JSON; +import com.baomidou.mybatisplus.annotation.TableField; +import lombok.Data; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 模版属性对象 business_template_prop + * + * @author ruoyi + * @date 2024-03-31 + */ +@Data +public class BusinessTemplateProp extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + + /** 标题 */ + @Excel(name = "标题") + private String title; + + + /** 组件类型(0单选框 1多选框) */ + @Excel(name = "组件类型", readConverterExp = "0=单选框,1=多选框") + private String compType; + + + /** 字段名 */ + @Excel(name = "字段名") + private String fieldName; + + + /** 占位提示 */ + @Excel(name = "占位提示") + private String placPrompt; + + + /** 默认值 */ + @Excel(name = "默认值") + private String defaultValue; + + + /** 可选值 */ + @Excel(name = "可选值") + private String optionalValue; + + /** 可选值数组 */ + @Excel(name = "可选值数组") + @TableField(exist = false) + private List> optionalValues = new ArrayList>(); + + /** 是否开放 */ + @Excel(name = "是否开放") + private String open; + + + /** 模版id */ + @Excel(name = "模版id") + private Long tempId; + + /** 排序 */ + @Excel(name = "排序") + private Integer sort; + + public void setTitle(String title) + { + this.title = title; + } + + public String getTitle() + { + return title; + } + public void setCompType(String compType) + { + this.compType = compType; + } + + public String getCompType() + { + return compType; + } + public void setFieldName(String fieldName) + { + this.fieldName = fieldName; + } + + public String getFieldName() + { + return fieldName; + } + public void setPlacPrompt(String placPrompt) + { + this.placPrompt = placPrompt; + } + + public String getPlacPrompt() + { + return placPrompt; + } + public void setDefaultValue(String defaultValue) + { + this.defaultValue = defaultValue; + } + + public String getDefaultValue() + { + return defaultValue; + } + public void setOptionalValue(String optionalValue) + { + if(StringUtils.isNotBlank(optionalValue)){ + String[] split = optionalValue.split("\\|"); + + for (String s : split) { + Map dataMap = new HashMap<>(); + String[] value = s.split(","); + dataMap.put("key",value[0]); + dataMap.put("value",value[1]); + this.optionalValues.add(dataMap); + } + + } + this.optionalValue = optionalValue; + } + + public String getOptionalValue() + { + return optionalValue; + } + public void setOpen(String open) + { + this.open = open; + } + + public String getOpen() + { + return open; + } + public void setTempId(Long tempId) + { + this.tempId = tempId; + } + + public Long getTempId() + { + return tempId; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("title", getTitle()) + .append("compType", getCompType()) + .append("fieldName", getFieldName()) + .append("placPrompt", getPlacPrompt()) + .append("defaultValue", getDefaultValue()) + .append("optionalValue", getOptionalValue()) + .append("open", getOpen()) + .append("tempId", getTempId()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("deleted", getDeleted()) + .append("remark", getRemark()) + .toString(); + } + +} diff --git a/ruoyi-business/src/main/java/com/ruoyi/business/domain/BusinessTemplatePropValue.java b/ruoyi-business/src/main/java/com/ruoyi/business/domain/BusinessTemplatePropValue.java new file mode 100644 index 0000000..6c08563 --- /dev/null +++ b/ruoyi-business/src/main/java/com/ruoyi/business/domain/BusinessTemplatePropValue.java @@ -0,0 +1,111 @@ +package com.ruoyi.business.domain; + +import lombok.Data; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 模版属性值对象 business_template_prop_value + * + * @author ruoyi + * @date 2024-03-31 + */ +@Data +public class BusinessTemplatePropValue extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + + + /** 字段id */ + @Excel(name = "字段id") + private String propId; + + + /** 字段名称 */ + @Excel(name = "字段名称") + private String propName; + + + /** 字段类型 */ + @Excel(name = "字段类型") + private String propType; + + /** 值键 */ + @Excel(name = "值键") + private String valueKey; + + + /** 值描述 */ + @Excel(name = "值描述") + private String valueText; + + + /** 原值对象 */ + @Excel(name = "原值对象") + private String valueSources; + + + /** 试卷id */ + @Excel(name = "试卷id") + private String surveyId; + + + + + + public void setPropId(String propId) + { + this.propId = propId; + } + + public String getPropId() + { + return propId; + } + public void setPropName(String propName) + { + this.propName = propName; + } + + public String getPropName() + { + return propName; + } + public void setValueKey(String valueKey) + { + this.valueKey = valueKey; + } + + public String getValueKey() + { + return valueKey; + } + public void setValueText(String valueText) + { + this.valueText = valueText; + } + + public String getValueText() + { + return valueText; + } + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("id", getId()) + .append("propId", getPropId()) + .append("propName", getPropName()) + .append("valueKey", getValueKey()) + .append("valueText", getValueText()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("deleted", getDeleted()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/ruoyi-business/src/main/java/com/ruoyi/business/mapper/BusinessSurveyMapper.java b/ruoyi-business/src/main/java/com/ruoyi/business/mapper/BusinessSurveyMapper.java new file mode 100644 index 0000000..84296ce --- /dev/null +++ b/ruoyi-business/src/main/java/com/ruoyi/business/mapper/BusinessSurveyMapper.java @@ -0,0 +1,16 @@ +package com.ruoyi.business.mapper; + +import java.util.List; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ruoyi.business.domain.BusinessSurvey; + +/** + * 调查问卷管理Mapper接口 + * + * @author ruoyi + * @date 2024-04-01 + */ +public interface BusinessSurveyMapper extends BaseMapper +{ + +} diff --git a/ruoyi-business/src/main/java/com/ruoyi/business/mapper/BusinessTemplateMapper.java b/ruoyi-business/src/main/java/com/ruoyi/business/mapper/BusinessTemplateMapper.java new file mode 100644 index 0000000..c6c907f --- /dev/null +++ b/ruoyi-business/src/main/java/com/ruoyi/business/mapper/BusinessTemplateMapper.java @@ -0,0 +1,16 @@ +package com.ruoyi.business.mapper; + +import java.util.List; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ruoyi.business.domain.BusinessTemplate; + +/** + * 模版管理Mapper接口 + * + * @author ruoyi + * @date 2024-03-31 + */ +public interface BusinessTemplateMapper extends BaseMapper +{ + +} diff --git a/ruoyi-business/src/main/java/com/ruoyi/business/mapper/BusinessTemplatePropMapper.java b/ruoyi-business/src/main/java/com/ruoyi/business/mapper/BusinessTemplatePropMapper.java new file mode 100644 index 0000000..bc58dab --- /dev/null +++ b/ruoyi-business/src/main/java/com/ruoyi/business/mapper/BusinessTemplatePropMapper.java @@ -0,0 +1,16 @@ +package com.ruoyi.business.mapper; + +import java.util.List; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ruoyi.business.domain.BusinessTemplateProp; + +/** + * 模版属性Mapper接口 + * + * @author ruoyi + * @date 2024-03-31 + */ +public interface BusinessTemplatePropMapper extends BaseMapper +{ + +} diff --git a/ruoyi-business/src/main/java/com/ruoyi/business/mapper/BusinessTemplatePropValueMapper.java b/ruoyi-business/src/main/java/com/ruoyi/business/mapper/BusinessTemplatePropValueMapper.java new file mode 100644 index 0000000..7bf8d14 --- /dev/null +++ b/ruoyi-business/src/main/java/com/ruoyi/business/mapper/BusinessTemplatePropValueMapper.java @@ -0,0 +1,23 @@ +package com.ruoyi.business.mapper; + +import java.util.List; +import java.util.Map; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ruoyi.business.domain.BusinessTemplatePropValue; +import org.apache.ibatis.annotations.Param; + +/** + * 模版属性值Mapper接口 + * + * @author ruoyi + * @date 2024-03-31 + */ +public interface BusinessTemplatePropValueMapper extends BaseMapper +{ + /** + * 获取统计数据 + * @param surveyId + */ + List> countGroup(@Param("surveyId") String surveyId, @Param("propId") String propId); +} diff --git a/ruoyi-business/src/main/java/com/ruoyi/business/service/IBusinessSurveyService.java b/ruoyi-business/src/main/java/com/ruoyi/business/service/IBusinessSurveyService.java new file mode 100644 index 0000000..44df001 --- /dev/null +++ b/ruoyi-business/src/main/java/com/ruoyi/business/service/IBusinessSurveyService.java @@ -0,0 +1,22 @@ +package com.ruoyi.business.service; + +import java.util.List; +import com.ruoyi.business.domain.BusinessSurvey; +import com.baomidou.mybatisplus.extension.service.IService; +import com.ruoyi.common.core.domain.AjaxResult; + +/** + * 调查问卷管理Service接口 + * + * @author ruoyi + * @date 2024-04-01 + */ +public interface IBusinessSurveyService extends IService +{ + + /** + * 根据试卷获取题目 + * @param surveyId + */ + AjaxResult listBySurveyId(String surveyId); +} diff --git a/ruoyi-business/src/main/java/com/ruoyi/business/service/IBusinessTemplatePropService.java b/ruoyi-business/src/main/java/com/ruoyi/business/service/IBusinessTemplatePropService.java new file mode 100644 index 0000000..ca64766 --- /dev/null +++ b/ruoyi-business/src/main/java/com/ruoyi/business/service/IBusinessTemplatePropService.java @@ -0,0 +1,15 @@ +package com.ruoyi.business.service; + +import java.util.List; +import com.ruoyi.business.domain.BusinessTemplateProp; +import com.baomidou.mybatisplus.extension.service.IService; +/** + * 模版属性Service接口 + * + * @author ruoyi + * @date 2024-03-31 + */ +public interface IBusinessTemplatePropService extends IService +{ + +} diff --git a/ruoyi-business/src/main/java/com/ruoyi/business/service/IBusinessTemplatePropValueService.java b/ruoyi-business/src/main/java/com/ruoyi/business/service/IBusinessTemplatePropValueService.java new file mode 100644 index 0000000..702b92a --- /dev/null +++ b/ruoyi-business/src/main/java/com/ruoyi/business/service/IBusinessTemplatePropValueService.java @@ -0,0 +1,28 @@ +package com.ruoyi.business.service; + +import java.util.List; +import java.util.Map; + +import com.ruoyi.business.domain.BusinessTemplatePropValue; +import com.baomidou.mybatisplus.extension.service.IService; +/** + * 模版属性值Service接口 + * + * @author ruoyi + * @date 2024-03-31 + */ +public interface IBusinessTemplatePropValueService extends IService +{ + + /** + *获取统计数据 + * @param tempId + */ + Object countGroup(String tempId); + /** + * 批量写入值 + * @param data + * @return + */ + boolean addList(Map data); +} diff --git a/ruoyi-business/src/main/java/com/ruoyi/business/service/IBusinessTemplateService.java b/ruoyi-business/src/main/java/com/ruoyi/business/service/IBusinessTemplateService.java new file mode 100644 index 0000000..5efca6d --- /dev/null +++ b/ruoyi-business/src/main/java/com/ruoyi/business/service/IBusinessTemplateService.java @@ -0,0 +1,15 @@ +package com.ruoyi.business.service; + +import java.util.List; +import com.ruoyi.business.domain.BusinessTemplate; +import com.baomidou.mybatisplus.extension.service.IService; +/** + * 模版管理Service接口 + * + * @author ruoyi + * @date 2024-03-31 + */ +public interface IBusinessTemplateService extends IService +{ + +} diff --git a/ruoyi-business/src/main/java/com/ruoyi/business/service/impl/BusinessSurveyServiceImpl.java b/ruoyi-business/src/main/java/com/ruoyi/business/service/impl/BusinessSurveyServiceImpl.java new file mode 100644 index 0000000..9bfbd9d --- /dev/null +++ b/ruoyi-business/src/main/java/com/ruoyi/business/service/impl/BusinessSurveyServiceImpl.java @@ -0,0 +1,102 @@ +package com.ruoyi.business.service.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import com.ruoyi.business.domain.BusinessTemplateProp; +import com.ruoyi.business.domain.BusinessTemplatePropValue; +import com.ruoyi.business.mapper.BusinessTemplatePropMapper; +import com.ruoyi.business.mapper.BusinessTemplatePropValueMapper; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.SecurityUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.business.mapper.BusinessSurveyMapper; +import com.ruoyi.business.domain.BusinessSurvey; +import com.ruoyi.business.service.IBusinessSurveyService; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; + +/** + * 调查问卷管理Service业务层处理 + * + * @author ruoyi + * @date 2024-04-01 + */ +@Service +public class BusinessSurveyServiceImpl extends ServiceImpl implements IBusinessSurveyService +{ + @Autowired + private BusinessTemplatePropMapper businessTemplatePropMapper; +@Autowired + private BusinessTemplatePropValueMapper businessTemplatePropValueMapper; + + /** + * 根据试卷获取题目 + * @param surveyId + * @return + */ + @Override + public AjaxResult listBySurveyId(String surveyId) { + BusinessSurvey businessSurvey = baseMapper.selectOne(new LambdaQueryWrapper().eq(BusinessSurvey::getId, surveyId)); + + List list = businessTemplatePropMapper.selectList(new LambdaQueryWrapper() + .eq(BusinessTemplateProp::getTempId, businessSurvey.getTempId()) + .orderByDesc(BusinessTemplateProp::getSort)); + + JSONObject jsonObject = new JSONObject(); + list.forEach(e -> { + BusinessTemplatePropValue one = businessTemplatePropValueMapper.selectOne(new LambdaQueryWrapper() + .eq(BusinessTemplatePropValue::getPropId, e.getId()) + .eq(BusinessTemplatePropValue::getSurveyId, surveyId) + .eq(BusinessTemplatePropValue::getCreateBy, SecurityUtils.getUsername())); + if (e.getCompType().equals("0")) { + jsonObject.put(e.getId(), Optional.ofNullable(one).orElse(new BusinessTemplatePropValue()).getValueSources()); + } + if (e.getCompType().equals("1")) { + String valueSources = Optional.ofNullable(one).orElse(new BusinessTemplatePropValue()).getValueSources(); + if(null != valueSources){ + List collect = Stream.of(valueSources.substring(1, valueSources.length() - 1).split(", ")).collect(Collectors.toList()); + jsonObject.put(e.getId(),collect); + }else{ + jsonObject.put(e.getId(),new ArrayList<>()); + } + } + if (e.getCompType().equals("2")) { + jsonObject.put(e.getId(), Optional.ofNullable(one).orElse(new BusinessTemplatePropValue()).getValueSources()); + } + if (e.getCompType().equals("3")) { + jsonObject.put(e.getId(), Optional.ofNullable(one).orElse(new BusinessTemplatePropValue()).getValueSources()); + } + if (e.getCompType().equals("4")) { + jsonObject.put(e.getId(), Optional.ofNullable(one).orElse(new BusinessTemplatePropValue()).getValueSources()); + } + if (e.getCompType().equals("5")) { + jsonObject.put(e.getId(), Optional.ofNullable(one).orElse(new BusinessTemplatePropValue()).getValueSources()); + } + if (e.getCompType().equals("6")) { + jsonObject.put(e.getId(), Optional.ofNullable(one).orElse(new BusinessTemplatePropValue()).getValueSources()); + } + if (e.getCompType().equals("7")) { + jsonObject.put(e.getId(), Optional.ofNullable(one).orElse(new BusinessTemplatePropValue()).getValueSources()); + } + if (e.getCompType().equals("8")) { + jsonObject.put(e.getId(), Optional.ofNullable(one).orElse(new BusinessTemplatePropValue()).getValueSources()); + } + if (e.getCompType().equals("9")) { + jsonObject.put(e.getId(), Optional.ofNullable(one).orElse(new BusinessTemplatePropValue()).getValueSources() == null ? new JSONArray() : Optional.ofNullable(one).orElse(new BusinessTemplatePropValue()).getValueSources()); + } + }); + AjaxResult success = AjaxResult.success(list); + success.put("form" , jsonObject); + return success; + + } +} diff --git a/ruoyi-business/src/main/java/com/ruoyi/business/service/impl/BusinessTemplatePropServiceImpl.java b/ruoyi-business/src/main/java/com/ruoyi/business/service/impl/BusinessTemplatePropServiceImpl.java new file mode 100644 index 0000000..abb5a99 --- /dev/null +++ b/ruoyi-business/src/main/java/com/ruoyi/business/service/impl/BusinessTemplatePropServiceImpl.java @@ -0,0 +1,27 @@ +package com.ruoyi.business.service.impl; + +import java.util.List; +import com.ruoyi.common.utils.DateUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.business.mapper.BusinessTemplatePropMapper; +import com.ruoyi.business.domain.BusinessTemplateProp; +import com.ruoyi.business.service.IBusinessTemplatePropService; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; + +/** + * 模版属性Service业务层处理 + * + * @author ruoyi + * @date 2024-03-31 + */ +@Service +public class BusinessTemplatePropServiceImpl extends ServiceImpl implements IBusinessTemplatePropService +{ + @Autowired + private BusinessTemplatePropMapper businessTemplatePropMapper; + + +} diff --git a/ruoyi-business/src/main/java/com/ruoyi/business/service/impl/BusinessTemplatePropValueServiceImpl.java b/ruoyi-business/src/main/java/com/ruoyi/business/service/impl/BusinessTemplatePropValueServiceImpl.java new file mode 100644 index 0000000..a673410 --- /dev/null +++ b/ruoyi-business/src/main/java/com/ruoyi/business/service/impl/BusinessTemplatePropValueServiceImpl.java @@ -0,0 +1,149 @@ +package com.ruoyi.business.service.impl; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; + +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import com.ruoyi.business.domain.BusinessSurvey; +import com.ruoyi.business.domain.BusinessTemplate; +import com.ruoyi.business.domain.BusinessTemplateProp; +import com.ruoyi.business.mapper.BusinessSurveyMapper; +import com.ruoyi.business.mapper.BusinessTemplatePropMapper; +import com.ruoyi.business.service.IBusinessSurveyService; +import com.ruoyi.business.service.IBusinessTemplatePropService; +import com.ruoyi.business.service.IBusinessTemplateService; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.business.mapper.BusinessTemplatePropValueMapper; +import com.ruoyi.business.domain.BusinessTemplatePropValue; +import com.ruoyi.business.service.IBusinessTemplatePropValueService; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; + +/** + * 模版属性值Service业务层处理 + * + * @author ruoyi + * @date 2024-03-31 + */ +@Service +public class BusinessTemplatePropValueServiceImpl extends ServiceImpl implements IBusinessTemplatePropValueService { + @Autowired + private BusinessTemplatePropValueMapper businessTemplatePropValueMapper; + + @Autowired + private IBusinessTemplateService businessTemplateService; + + @Autowired + private IBusinessTemplatePropService businessTemplatePropService; + + @Autowired + private IBusinessSurveyService businessSurveyService; + + + /** + * 获取统计数据 + * + * @param surveyId + * @return + */ + @Override + public Object countGroup(String surveyId) { + BusinessSurvey businessSurvey = businessSurveyService.lambdaQuery().eq(BusinessSurvey::getId, surveyId).one(); + + BusinessTemplate businessTemplate = businessTemplateService.lambdaQuery().eq(BusinessTemplate::getId, businessSurvey.getTempId()).one(); + + List businessTemplateProps = businessTemplatePropService.lambdaQuery() + .eq(BusinessTemplateProp::getTempId, businessTemplate.getId()).in(BusinessTemplateProp::getCompType, new String[]{"0" , "1" , "6"}).list(); + + JSONObject map = new JSONObject(); + List> list = new ArrayList<>(); + businessTemplateProps.forEach(e -> { + List> countList = businessTemplatePropValueMapper.countGroup(surveyId, e.getId()); + map.put(e.getTitle(), countList); + }); + + return map; + } + + /** + * 批量写入值 + * + * @param data + * @return + */ + @Override + public boolean addList(Map data) { + + // 试卷id + String surveyId = data.get("surveyId").toString(); + data.remove("surveyId"); + List datas = new ArrayList<>(); + data.forEach((k, v) -> { + BusinessTemplatePropValue businessTemplatePropValue = new BusinessTemplatePropValue(); + BusinessTemplateProp businessTemplateProp = businessTemplatePropService.getById(k); + List businessTemplatePropValues = businessTemplatePropValueMapper.selectList(new LambdaQueryWrapper() + .eq(BusinessTemplatePropValue::getPropId, k).eq(BusinessTemplatePropValue::getCreateBy, SecurityUtils.getUsername())); + + businessTemplatePropValues.forEach(e -> { + if (e.getPropId().equals(k)) { + businessTemplatePropValue.setId(e.getId()); + } + }); + businessTemplatePropValue.setPropName(businessTemplateProp.getFieldName()); + businessTemplatePropValue.setPropType(businessTemplateProp.getCompType()); + businessTemplatePropValue.setPropId(k); + businessTemplatePropValue.setValueKey(v.toString()); + if (businessTemplateProp.getCompType().equals("0")) { + String optionalValue = businessTemplateProp.getOptionalValue(); + String[] split = optionalValue.split("\\|"); + for (String v1 : split) { + String[] v2 = v1.split(","); + if (v2[0].equals(v)) { + businessTemplatePropValue.setValueText(v2[1]); + } + } + businessTemplatePropValue.setValueSources(v.toString()); + } else if (businessTemplateProp.getCompType().equals("1")) { + String optionalValue = businessTemplateProp.getOptionalValue(); + String[] split = optionalValue.split("\\|"); + StringBuilder sb = new StringBuilder(); + + for (String v1 : split) { + String[] v2 = v1.split(","); + if (((ArrayList) v).contains(v2[0])) { + sb.append(v2[1]).append(","); + } + } + businessTemplatePropValue.setValueText(sb.substring(0, sb.length() - 1)); + businessTemplatePropValue.setValueSources(v.toString()); + } else if (businessTemplateProp.getCompType().equals("6")) { + String optionalValue = businessTemplateProp.getOptionalValue(); + String[] split = optionalValue.split("\\|"); + StringBuilder sb = new StringBuilder(); + + for (String v1 : split) { + String[] v2 = v1.split(","); + if (v.equals(v2[0])) { + sb.append(v2[1]).append(","); + } + } + businessTemplatePropValue.setValueText(sb.substring(0, sb.length() - 1)); + businessTemplatePropValue.setValueSources(v.toString()); + } else { + businessTemplatePropValue.setValueText(v.toString()); + businessTemplatePropValue.setValueSources(v.toString()); + } + businessTemplatePropValue.setSurveyId(surveyId); + datas.add(businessTemplatePropValue); + }); + + return saveOrUpdateBatch(datas); + } +} diff --git a/ruoyi-business/src/main/java/com/ruoyi/business/service/impl/BusinessTemplateServiceImpl.java b/ruoyi-business/src/main/java/com/ruoyi/business/service/impl/BusinessTemplateServiceImpl.java new file mode 100644 index 0000000..41294b4 --- /dev/null +++ b/ruoyi-business/src/main/java/com/ruoyi/business/service/impl/BusinessTemplateServiceImpl.java @@ -0,0 +1,27 @@ +package com.ruoyi.business.service.impl; + +import java.util.List; +import com.ruoyi.common.utils.DateUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.business.mapper.BusinessTemplateMapper; +import com.ruoyi.business.domain.BusinessTemplate; +import com.ruoyi.business.service.IBusinessTemplateService; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; + +/** + * 模版管理Service业务层处理 + * + * @author ruoyi + * @date 2024-03-31 + */ +@Service +public class BusinessTemplateServiceImpl extends ServiceImpl implements IBusinessTemplateService +{ + @Autowired + private BusinessTemplateMapper businessTemplateMapper; + + +} diff --git a/ruoyi-business/src/main/resources/mapper/business/BusinessSurveyMapper.xml b/ruoyi-business/src/main/resources/mapper/business/BusinessSurveyMapper.xml new file mode 100644 index 0000000..5acaf12 --- /dev/null +++ b/ruoyi-business/src/main/resources/mapper/business/BusinessSurveyMapper.xml @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + select id, title, context, temp_id, open, create_by, create_time, update_by, update_time, deleted, remark from business_survey + + + + + + + + insert into business_survey + + title, + context, + temp_id, + open, + create_by, + create_time, + update_by, + update_time, + deleted, + remark, + + + #{title}, + #{context}, + #{tempId}, + #{open}, + #{createBy}, + #{createTime}, + #{updateBy}, + #{updateTime}, + #{deleted}, + #{remark}, + + + + + update business_survey + + title = #{title}, + context = #{context}, + temp_id = #{tempId}, + open = #{open}, + create_by = #{createBy}, + create_time = #{createTime}, + update_by = #{updateBy}, + update_time = #{updateTime}, + deleted = #{deleted}, + remark = #{remark}, + + where id = #{id} + + + + delete from business_survey where id = #{id} + + + + delete from business_survey where id in + + #{id} + + + \ No newline at end of file diff --git a/ruoyi-business/src/main/resources/mapper/business/BusinessTemplateMapper.xml b/ruoyi-business/src/main/resources/mapper/business/BusinessTemplateMapper.xml new file mode 100644 index 0000000..9322834 --- /dev/null +++ b/ruoyi-business/src/main/resources/mapper/business/BusinessTemplateMapper.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + select id, title, context, open, create_by, create_time, update_by, update_time, deleted, remark from business_template + + + + + + + + insert into business_template + + title, + context, + open, + create_by, + create_time, + update_by, + update_time, + deleted, + remark, + + + #{title}, + #{context}, + #{open}, + #{createBy}, + #{createTime}, + #{updateBy}, + #{updateTime}, + #{deleted}, + #{remark}, + + + + + update business_template + + title = #{title}, + context = #{context}, + open = #{open}, + create_by = #{createBy}, + create_time = #{createTime}, + update_by = #{updateBy}, + update_time = #{updateTime}, + deleted = #{deleted}, + remark = #{remark}, + + where id = #{id} + + + + delete from business_template where id = #{id} + + + + delete from business_template where id in + + #{id} + + + \ No newline at end of file diff --git a/ruoyi-business/src/main/resources/mapper/business/BusinessTemplatePropMapper.xml b/ruoyi-business/src/main/resources/mapper/business/BusinessTemplatePropMapper.xml new file mode 100644 index 0000000..29ae31b --- /dev/null +++ b/ruoyi-business/src/main/resources/mapper/business/BusinessTemplatePropMapper.xml @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + select id, title, comp_type, field_name, plac_prompt, default_value, optional_value, open, temp_id, create_by, create_time, update_by, update_time, deleted, remark from business_template_prop + + + + + + + + insert into business_template_prop + + title, + comp_type, + field_name, + plac_prompt, + default_value, + optional_value, + open, + temp_id, + create_by, + create_time, + update_by, + update_time, + deleted, + remark, + + + #{title}, + #{compType}, + #{fieldName}, + #{placPrompt}, + #{defaultValue}, + #{optionalValue}, + #{open}, + #{tempId}, + #{createBy}, + #{createTime}, + #{updateBy}, + #{updateTime}, + #{deleted}, + #{remark}, + + + + + update business_template_prop + + title = #{title}, + comp_type = #{compType}, + field_name = #{fieldName}, + plac_prompt = #{placPrompt}, + default_value = #{defaultValue}, + optional_value = #{optionalValue}, + open = #{open}, + temp_id = #{tempId}, + create_by = #{createBy}, + create_time = #{createTime}, + update_by = #{updateBy}, + update_time = #{updateTime}, + deleted = #{deleted}, + remark = #{remark}, + + where id = #{id} + + + + delete from business_template_prop where id = #{id} + + + + delete from business_template_prop where id in + + #{id} + + + \ No newline at end of file diff --git a/ruoyi-business/src/main/resources/mapper/business/BusinessTemplatePropValueMapper.xml b/ruoyi-business/src/main/resources/mapper/business/BusinessTemplatePropValueMapper.xml new file mode 100644 index 0000000..1c39d13 --- /dev/null +++ b/ruoyi-business/src/main/resources/mapper/business/BusinessTemplatePropValueMapper.xml @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + select id, prop_id, prop_name, value_key, value_text, temp_id, create_by, create_time, update_by, update_time, deleted, remark from business_template_prop_value + + + + + + + + + + + insert into business_template_prop_value + + prop_id, + prop_name, + value_key, + value_text, + temp_id, + create_by, + create_time, + update_by, + update_time, + deleted, + remark, + + + #{propId}, + #{propName}, + #{valueKey}, + #{valueText}, + #{tempId}, + #{createBy}, + #{createTime}, + #{updateBy}, + #{updateTime}, + #{deleted}, + #{remark}, + + + + + update business_template_prop_value + + prop_id = #{propId}, + prop_name = #{propName}, + value_key = #{valueKey}, + value_text = #{valueText}, + temp_id = #{tempId}, + create_by = #{createBy}, + create_time = #{createTime}, + update_by = #{updateBy}, + update_time = #{updateTime}, + deleted = #{deleted}, + remark = #{remark}, + + where id = #{id} + + + + delete from business_template_prop_value where id = #{id} + + + + delete from business_template_prop_value where id in + + #{id} + + + \ No newline at end of file diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml new file mode 100644 index 0000000..6eadd0b --- /dev/null +++ b/ruoyi-common/pom.xml @@ -0,0 +1,148 @@ + + + + ruoyi + com.ruoyi + 3.8.5 + + 4.0.0 + + ruoyi-common + + + common通用工具 + + + + + + + org.springframework + spring-context-support + + + + + org.springframework + spring-web + + + + + org.springframework.boot + spring-boot-starter-security + + + + + com.github.pagehelper + pagehelper-spring-boot-starter + + + + + org.springframework.boot + spring-boot-starter-validation + + + + + org.apache.commons + commons-lang3 + + + + + com.fasterxml.jackson.core + jackson-databind + + + + + com.baomidou + dynamic-datasource-spring-boot-starter + 3.5.2 + + + + + com.alibaba.fastjson2 + fastjson2 + + + + + commons-io + commons-io + + + + + commons-fileupload + commons-fileupload + + + + + org.apache.poi + poi-ooxml + + + + + org.yaml + snakeyaml + + + + + io.jsonwebtoken + jjwt + + + + + javax.xml.bind + jaxb-api + + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + + org.apache.commons + commons-pool2 + + + + + eu.bitwalker + UserAgentUtils + + + + + javax.servlet + javax.servlet-api + + + + + com.baomidou + mybatis-plus-boot-starter + 3.4.2 + + + org.projectlombok + lombok + 1.18.10 + + + + \ No newline at end of file diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java new file mode 100644 index 0000000..b58f81b --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java @@ -0,0 +1,19 @@ +package com.ruoyi.common.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 匿名访问不鉴权注解 + * + * @author #author# + */ +@Target({ ElementType.METHOD, ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Anonymous +{ +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java new file mode 100644 index 0000000..c05a69f --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java @@ -0,0 +1,33 @@ +package com.ruoyi.common.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 数据权限过滤注解 + * + * @author #author# + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface DataScope +{ + /** + * 部门表的别名 + */ + public String deptAlias() default ""; + + /** + * 用户表的别名 + */ + public String userAlias() default ""; + + /** + * 权限字符(用于多个角色匹配符合要求的权限)默认根据权限注解@ss获取,多个权限用逗号分隔开来 + */ + public String permission() default ""; +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java new file mode 100644 index 0000000..c1096dc --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java @@ -0,0 +1,28 @@ +package com.ruoyi.common.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import com.ruoyi.common.enums.DataSourceType; + +/** + * 自定义多数据源切换注解 + * + * 优先级:先方法,后类,如果方法覆盖了类上的数据源类型,以方法的为准,否则以类上的为准 + * + * @author #author# + */ +@Target({ ElementType.METHOD, ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +public @interface DataSource +{ + /** + * 切换数据源名称 + */ + public DataSourceType value() default DataSourceType.MASTER; +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java new file mode 100644 index 0000000..be51417 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java @@ -0,0 +1,187 @@ +package com.ruoyi.common.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.math.BigDecimal; +import org.apache.poi.ss.usermodel.HorizontalAlignment; +import org.apache.poi.ss.usermodel.IndexedColors; +import com.ruoyi.common.utils.poi.ExcelHandlerAdapter; + +/** + * 自定义导出Excel数据注解 + * + * @author #author# + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface Excel +{ + /** + * 导出时在excel中排序 + */ + public int sort() default Integer.MAX_VALUE; + + /** + * 导出到Excel中的名字. + */ + public String name() default ""; + + /** + * 日期格式, 如: yyyy-MM-dd + */ + public String dateFormat() default ""; + + /** + * 如果是字典类型,请设置字典的type值 (如: sys_user_sex) + */ + public String dictType() default ""; + + /** + * 读取内容转表达式 (如: 0=男,1=女,2=未知) + */ + public String readConverterExp() default ""; + + /** + * 分隔符,读取字符串组内容 + */ + public String separator() default ","; + + /** + * BigDecimal 精度 默认:-1(默认不开启BigDecimal格式化) + */ + public int scale() default -1; + + /** + * BigDecimal 舍入规则 默认:BigDecimal.ROUND_HALF_EVEN + */ + public int roundingMode() default BigDecimal.ROUND_HALF_EVEN; + + /** + * 导出时在excel中每个列的高度 单位为字符 + */ + public double height() default 14; + + /** + * 导出时在excel中每个列的宽 单位为字符 + */ + public double width() default 16; + + /** + * 文字后缀,如% 90 变成90% + */ + public String suffix() default ""; + + /** + * 当值为空时,字段的默认值 + */ + public String defaultValue() default ""; + + /** + * 提示信息 + */ + public String prompt() default ""; + + /** + * 设置只能选择不能输入的列内容. + */ + public String[] combo() default {}; + + /** + * 是否需要纵向合并单元格,应对需求:含有list集合单元格) + */ + public boolean needMerge() default false; + + /** + * 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写. + */ + public boolean isExport() default true; + + /** + * 另一个类中的属性名称,支持多级获取,以小数点隔开 + */ + public String targetAttr() default ""; + + /** + * 是否自动统计数据,在最后追加一行统计数据总和 + */ + public boolean isStatistics() default false; + + /** + * 导出类型(0数字 1字符串 2图片) + */ + public ColumnType cellType() default ColumnType.STRING; + + /** + * 导出列头背景色 + */ + public IndexedColors headerBackgroundColor() default IndexedColors.GREY_50_PERCENT; + + /** + * 导出列头字体颜色 + */ + public IndexedColors headerColor() default IndexedColors.WHITE; + + /** + * 导出单元格背景色 + */ + public IndexedColors backgroundColor() default IndexedColors.WHITE; + + /** + * 导出单元格字体颜色 + */ + public IndexedColors color() default IndexedColors.BLACK; + + /** + * 导出字段对齐方式 + */ + public HorizontalAlignment align() default HorizontalAlignment.CENTER; + + /** + * 自定义数据处理器 + */ + public Class handler() default ExcelHandlerAdapter.class; + + /** + * 自定义数据处理器参数 + */ + public String[] args() default {}; + + /** + * 字段类型(0:导出导入;1:仅导出;2:仅导入) + */ + Type type() default Type.ALL; + + public enum Type + { + ALL(0), EXPORT(1), IMPORT(2); + private final int value; + + Type(int value) + { + this.value = value; + } + + public int value() + { + return this.value; + } + } + + public enum ColumnType + { + NUMERIC(0), STRING(1), IMAGE(2); + private final int value; + + ColumnType(int value) + { + this.value = value; + } + + public int value() + { + return this.value; + } + } +} \ No newline at end of file diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excels.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excels.java new file mode 100644 index 0000000..512d59a --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excels.java @@ -0,0 +1,18 @@ +package com.ruoyi.common.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Excel注解集 + * + * @author #author# + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Excels +{ + public Excel[] value(); +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java new file mode 100644 index 0000000..e7a126e --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java @@ -0,0 +1,46 @@ +package com.ruoyi.common.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.enums.OperatorType; + +/** + * 自定义操作日志记录注解 + * + * @author #author# + * + */ +@Target({ ElementType.PARAMETER, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Log +{ + /** + * 模块 + */ + public String title() default ""; + + /** + * 功能 + */ + public BusinessType businessType() default BusinessType.OTHER; + + /** + * 操作人类别 + */ + public OperatorType operatorType() default OperatorType.MANAGE; + + /** + * 是否保存请求的参数 + */ + public boolean isSaveRequestData() default true; + + /** + * 是否保存响应的参数 + */ + public boolean isSaveResponseData() default true; +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java new file mode 100644 index 0000000..ec2c4e5 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java @@ -0,0 +1,40 @@ +package com.ruoyi.common.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.enums.LimitType; + +/** + * 限流注解 + * + * @author #author# + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface RateLimiter +{ + /** + * 限流key + */ + public String key() default CacheConstants.RATE_LIMIT_KEY; + + /** + * 限流时间,单位秒 + */ + public int time() default 60; + + /** + * 限流次数 + */ + public int count() default 100; + + /** + * 限流类型 + */ + public LimitType limitType() default LimitType.DEFAULT; +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java new file mode 100644 index 0000000..c2babc5 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java @@ -0,0 +1,31 @@ +package com.ruoyi.common.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 自定义注解防止表单重复提交 + * + * @author #author# + * + */ +@Inherited +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface RepeatSubmit +{ + /** + * 间隔时间(ms),小于此时间视为重复提交 + */ + public int interval() default 5000; + + /** + * 提示消息 + */ + public String message() default "不允许重复提交,请稍候再试"; +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java new file mode 100644 index 0000000..c33156d --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java @@ -0,0 +1,135 @@ +package com.ruoyi.common.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * 读取项目相关配置 + * + * @author #author# + */ +@Component +@ConfigurationProperties(prefix = "ruoyi") +public class RuoYiConfig +{ + /** 项目名称 */ + private String name; + + /** 版本 */ + private String version; + + /** 版权年份 */ + private String copyrightYear; + + /** 实例演示开关 */ + private boolean demoEnabled; + + /** 上传路径 */ + private static String profile; + + /** 获取地址开关 */ + private static boolean addressEnabled; + + /** 验证码类型 */ + private static String captchaType; + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public String getVersion() + { + return version; + } + + public void setVersion(String version) + { + this.version = version; + } + + public String getCopyrightYear() + { + return copyrightYear; + } + + public void setCopyrightYear(String copyrightYear) + { + this.copyrightYear = copyrightYear; + } + + public boolean isDemoEnabled() + { + return demoEnabled; + } + + public void setDemoEnabled(boolean demoEnabled) + { + this.demoEnabled = demoEnabled; + } + + public static String getProfile() + { + return profile; + } + + public void setProfile(String profile) + { + RuoYiConfig.profile = profile; + } + + public static boolean isAddressEnabled() + { + return addressEnabled; + } + + public void setAddressEnabled(boolean addressEnabled) + { + RuoYiConfig.addressEnabled = addressEnabled; + } + + public static String getCaptchaType() { + return captchaType; + } + + public void setCaptchaType(String captchaType) { + RuoYiConfig.captchaType = captchaType; + } + + /** + * 获取导入上传路径 + */ + public static String getImportPath() + { + return getProfile() + "/import"; + } + + /** + * 获取头像上传路径 + */ + public static String getAvatarPath() + { + return getProfile() + "/avatar"; + } + + /** + * 获取下载路径 + */ + public static String getDownloadPath() + { + return getProfile() + "/download/"; + } + + /** + * 获取上传路径 + */ + public static String getUploadPath() + { + return getProfile() + "/upload"; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java new file mode 100644 index 0000000..990670d --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java @@ -0,0 +1,44 @@ +package com.ruoyi.common.constant; + +/** + * 缓存的key 常量 + * + * @author #author# + */ +public class CacheConstants +{ + /** + * 登录用户 redis key + */ + public static final String LOGIN_TOKEN_KEY = "login_tokens:"; + + /** + * 验证码 redis key + */ + public static final String CAPTCHA_CODE_KEY = "captcha_codes:"; + + /** + * 参数管理 cache key + */ + public static final String SYS_CONFIG_KEY = "sys_config:"; + + /** + * 字典管理 cache key + */ + public static final String SYS_DICT_KEY = "sys_dict:"; + + /** + * 防重提交 redis key + */ + public static final String REPEAT_SUBMIT_KEY = "repeat_submit:"; + + /** + * 限流 redis key + */ + public static final String RATE_LIMIT_KEY = "rate_limit:"; + + /** + * 登录账户密码错误次数 redis key + */ + public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt:"; +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java new file mode 100644 index 0000000..1dfeef8 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java @@ -0,0 +1,142 @@ +package com.ruoyi.common.constant; + +import io.jsonwebtoken.Claims; + +/** + * 通用常量信息 + * + * @author #author# + */ +public class Constants +{ + /** + * UTF-8 字符集 + */ + public static final String UTF8 = "UTF-8"; + + /** + * GBK 字符集 + */ + public static final String GBK = "GBK"; + + /** + * www主域 + */ + public static final String WWW = "www."; + + /** + * http请求 + */ + public static final String HTTP = "http://"; + + /** + * https请求 + */ + public static final String HTTPS = "https://"; + + /** + * 通用成功标识 + */ + public static final String SUCCESS = "0"; + + /** + * 通用失败标识 + */ + public static final String FAIL = "1"; + + /** + * 登录成功 + */ + public static final String LOGIN_SUCCESS = "Success"; + + /** + * 注销 + */ + public static final String LOGOUT = "Logout"; + + /** + * 注册 + */ + public static final String REGISTER = "Register"; + + /** + * 登录失败 + */ + public static final String LOGIN_FAIL = "Error"; + + /** + * 验证码有效期(分钟) + */ + public static final Integer CAPTCHA_EXPIRATION = 2; + + /** + * 令牌 + */ + public static final String TOKEN = "token"; + + /** + * 令牌前缀 + */ + public static final String TOKEN_PREFIX = "Bearer "; + + /** + * 令牌前缀 + */ + public static final String LOGIN_USER_KEY = "login_user_key"; + + /** + * 用户ID + */ + public static final String JWT_USERID = "userid"; + + /** + * 用户名称 + */ + public static final String JWT_USERNAME = Claims.SUBJECT; + + /** + * 用户头像 + */ + public static final String JWT_AVATAR = "avatar"; + + /** + * 创建时间 + */ + public static final String JWT_CREATED = "created"; + + /** + * 用户权限 + */ + public static final String JWT_AUTHORITIES = "authorities"; + + /** + * 资源映射路径 前缀 + */ + public static final String RESOURCE_PREFIX = "/profile"; + + /** + * RMI 远程方法调用 + */ + public static final String LOOKUP_RMI = "rmi:"; + + /** + * LDAP 远程方法调用 + */ + public static final String LOOKUP_LDAP = "ldap:"; + + /** + * LDAPS 远程方法调用 + */ + public static final String LOOKUP_LDAPS = "ldaps:"; + + /** + * 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加) + */ + public static final String[] JOB_WHITELIST_STR = { "com.ruoyi" }; + + /** + * 定时任务违规的字符 + */ + public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml", + "org.springframework", "org.apache", "com.ruoyi.common.utils.file", "com.ruoyi.common.config" }; +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java new file mode 100644 index 0000000..fac4a44 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java @@ -0,0 +1,117 @@ +package com.ruoyi.common.constant; + +/** + * 代码生成通用常量 + * + * @author #author# + */ +public class GenConstants +{ + /** 单表(增删改查) */ + public static final String TPL_CRUD = "crud"; + + /** 树表(增删改查) */ + public static final String TPL_TREE = "tree"; + + /** 主子表(增删改查) */ + public static final String TPL_SUB = "sub"; + + /** 树编码字段 */ + public static final String TREE_CODE = "treeCode"; + + /** 树父编码字段 */ + public static final String TREE_PARENT_CODE = "treeParentCode"; + + /** 树名称字段 */ + public static final String TREE_NAME = "treeName"; + + /** 上级菜单ID字段 */ + public static final String PARENT_MENU_ID = "parentMenuId"; + + /** 上级菜单名称字段 */ + public static final String PARENT_MENU_NAME = "parentMenuName"; + + /** 数据库字符串类型 */ + public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2" }; + + /** 数据库文本类型 */ + public static final String[] COLUMNTYPE_TEXT = { "tinytext", "text", "mediumtext", "longtext" }; + + /** 数据库时间类型 */ + public static final String[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp" }; + + /** 数据库数字类型 */ + public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer", + "bit", "bigint", "float", "double", "decimal" }; + + /** 页面不需要编辑字段 */ + public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" }; + + /** 页面不需要显示的列表字段 */ + public static final String[] COLUMNNAME_NOT_LIST = { "id", "create_by", "create_time", "del_flag", "update_by", + "update_time" }; + + /** 页面不需要查询字段 */ + public static final String[] COLUMNNAME_NOT_QUERY = { "id", "create_by", "create_time", "del_flag", "update_by", + "update_time", "remark" }; + + /** Entity基类字段 */ + public static final String[] BASE_ENTITY = { "createBy", "createTime", "updateBy", "updateTime", "remark" }; + + /** Tree基类字段 */ + public static final String[] TREE_ENTITY = { "parentName", "parentId", "orderNum", "ancestors", "children" }; + + /** 文本框 */ + public static final String HTML_INPUT = "input"; + + /** 文本域 */ + public static final String HTML_TEXTAREA = "textarea"; + + /** 下拉框 */ + public static final String HTML_SELECT = "select"; + + /** 单选框 */ + public static final String HTML_RADIO = "radio"; + + /** 复选框 */ + public static final String HTML_CHECKBOX = "checkbox"; + + /** 日期控件 */ + public static final String HTML_DATETIME = "datetime"; + + /** 图片上传控件 */ + public static final String HTML_IMAGE_UPLOAD = "imageUpload"; + + /** 文件上传控件 */ + public static final String HTML_FILE_UPLOAD = "fileUpload"; + + /** 富文本控件 */ + public static final String HTML_EDITOR = "editor"; + + /** 字符串类型 */ + public static final String TYPE_STRING = "String"; + + /** 整型 */ + public static final String TYPE_INTEGER = "Integer"; + + /** 长整型 */ + public static final String TYPE_LONG = "Long"; + + /** 浮点型 */ + public static final String TYPE_DOUBLE = "Double"; + + /** 高精度计算类型 */ + public static final String TYPE_BIGDECIMAL = "BigDecimal"; + + /** 时间类型 */ + public static final String TYPE_DATE = "Date"; + + /** 模糊查询 */ + public static final String QUERY_LIKE = "LIKE"; + + /** 相等查询 */ + public static final String QUERY_EQ = "EQ"; + + /** 需要 */ + public static final String REQUIRE = "1"; +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java new file mode 100644 index 0000000..77d016c --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java @@ -0,0 +1,94 @@ +package com.ruoyi.common.constant; + +/** + * 返回状态码 + * + * @author #author# + */ +public class HttpStatus +{ + /** + * 操作成功 + */ + public static final int SUCCESS = 200; + + /** + * 对象创建成功 + */ + public static final int CREATED = 201; + + /** + * 请求已经被接受 + */ + public static final int ACCEPTED = 202; + + /** + * 操作已经执行成功,但是没有返回数据 + */ + public static final int NO_CONTENT = 204; + + /** + * 资源已被移除 + */ + public static final int MOVED_PERM = 301; + + /** + * 重定向 + */ + public static final int SEE_OTHER = 303; + + /** + * 资源没有被修改 + */ + public static final int NOT_MODIFIED = 304; + + /** + * 参数列表错误(缺少,格式不匹配) + */ + public static final int BAD_REQUEST = 400; + + /** + * 未授权 + */ + public static final int UNAUTHORIZED = 401; + + /** + * 访问受限,授权过期 + */ + public static final int FORBIDDEN = 403; + + /** + * 资源,服务未找到 + */ + public static final int NOT_FOUND = 404; + + /** + * 不允许的http方法 + */ + public static final int BAD_METHOD = 405; + + /** + * 资源冲突,或者资源被锁 + */ + public static final int CONFLICT = 409; + + /** + * 不支持的数据,媒体类型 + */ + public static final int UNSUPPORTED_TYPE = 415; + + /** + * 系统内部错误 + */ + public static final int ERROR = 500; + + /** + * 接口未实现 + */ + public static final int NOT_IMPLEMENTED = 501; + + /** + * 系统警告消息 + */ + public static final int WARN = 601; +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java new file mode 100644 index 0000000..bc608c4 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java @@ -0,0 +1,50 @@ +package com.ruoyi.common.constant; + +/** + * 任务调度通用常量 + * + * @author #author# + */ +public class ScheduleConstants +{ + public static final String TASK_CLASS_NAME = "TASK_CLASS_NAME"; + + /** 执行目标key */ + public static final String TASK_PROPERTIES = "TASK_PROPERTIES"; + + /** 默认 */ + public static final String MISFIRE_DEFAULT = "0"; + + /** 立即触发执行 */ + public static final String MISFIRE_IGNORE_MISFIRES = "1"; + + /** 触发一次执行 */ + public static final String MISFIRE_FIRE_AND_PROCEED = "2"; + + /** 不触发立即执行 */ + public static final String MISFIRE_DO_NOTHING = "3"; + + public enum Status + { + /** + * 正常 + */ + NORMAL("0"), + /** + * 暂停 + */ + PAUSE("1"); + + private String value; + + private Status(String value) + { + this.value = value; + } + + public String getValue() + { + return value; + } + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java new file mode 100644 index 0000000..0f9f99b --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java @@ -0,0 +1,78 @@ +package com.ruoyi.common.constant; + +/** + * 用户常量信息 + * + * @author #author# + */ +public class UserConstants +{ + /** + * 平台内系统用户的唯一标志 + */ + public static final String SYS_USER = "SYS_USER"; + + /** 正常状态 */ + public static final String NORMAL = "0"; + + /** 异常状态 */ + public static final String EXCEPTION = "1"; + + /** 用户封禁状态 */ + public static final String USER_DISABLE = "1"; + + /** 角色封禁状态 */ + public static final String ROLE_DISABLE = "1"; + + /** 部门正常状态 */ + public static final String DEPT_NORMAL = "0"; + + /** 部门停用状态 */ + public static final String DEPT_DISABLE = "1"; + + /** 字典正常状态 */ + public static final String DICT_NORMAL = "0"; + + /** 是否为系统默认(是) */ + public static final String YES = "Y"; + + /** 是否菜单外链(是) */ + public static final String YES_FRAME = "0"; + + /** 是否菜单外链(否) */ + public static final String NO_FRAME = "1"; + + /** 菜单类型(目录) */ + public static final String TYPE_DIR = "M"; + + /** 菜单类型(菜单) */ + public static final String TYPE_MENU = "C"; + + /** 菜单类型(按钮) */ + public static final String TYPE_BUTTON = "F"; + + /** Layout组件标识 */ + public final static String LAYOUT = "Layout"; + + /** ParentView组件标识 */ + public final static String PARENT_VIEW = "ParentView"; + + /** InnerLink组件标识 */ + public final static String INNER_LINK = "InnerLink"; + + /** 校验返回结果码 */ + public final static String UNIQUE = "0"; + public final static String NOT_UNIQUE = "1"; + + /** + * 用户名长度限制 + */ + public static final int USERNAME_MIN_LENGTH = 2; + public static final int USERNAME_MAX_LENGTH = 20; + + /** + * 密码长度限制 + */ + public static final int PASSWORD_MIN_LENGTH = 5; + public static final int PASSWORD_MAX_LENGTH = 20; +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java new file mode 100644 index 0000000..6854a2b --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java @@ -0,0 +1,202 @@ +package com.ruoyi.common.core.controller; + +import java.beans.PropertyEditorSupport; +import java.util.Date; +import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.WebDataBinder; +import org.springframework.web.bind.annotation.InitBinder; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.ruoyi.common.constant.HttpStatus; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.core.page.PageDomain; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.core.page.TableSupport; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.PageUtils; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.sql.SqlUtil; + +/** + * web层通用数据处理 + * + * @author #author# + */ +public class BaseController +{ + protected final Logger logger = LoggerFactory.getLogger(this.getClass()); + + /** + * 将前台传递过来的日期格式的字符串,自动转化为Date类型 + */ + @InitBinder + public void initBinder(WebDataBinder binder) + { + // Date 类型转换 + binder.registerCustomEditor(Date.class, new PropertyEditorSupport() + { + @Override + public void setAsText(String text) + { + setValue(DateUtils.parseDate(text)); + } + }); + } + + /** + * 设置请求分页数据 + */ + protected void startPage() + { + PageUtils.startPage(); + } + + /** + * 设置请求排序数据 + */ + protected void startOrderBy() + { + PageDomain pageDomain = TableSupport.buildPageRequest(); + if (StringUtils.isNotEmpty(pageDomain.getOrderBy())) + { + String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy()); + PageHelper.orderBy(orderBy); + } + } + + /** + * 清理分页的线程变量 + */ + protected void clearPage() + { + PageUtils.clearPage(); + } + + /** + * 响应请求分页数据 + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + protected TableDataInfo getDataTable(List list) + { + TableDataInfo rspData = new TableDataInfo(); + rspData.setCode(HttpStatus.SUCCESS); + rspData.setMsg("查询成功"); + rspData.setRows(list); + rspData.setTotal(new PageInfo(list).getTotal()); + return rspData; + } + + /** + * 返回成功 + */ + public AjaxResult success() + { + return AjaxResult.success(); + } + + /** + * 返回失败消息 + */ + public AjaxResult error() + { + return AjaxResult.error(); + } + + /** + * 返回成功消息 + */ + public AjaxResult success(String message) + { + return AjaxResult.success(message); + } + + /** + * 返回成功消息 + */ + public AjaxResult success(Object data) + { + return AjaxResult.success(data); + } + + /** + * 返回失败消息 + */ + public AjaxResult error(String message) + { + return AjaxResult.error(message); + } + + /** + * 返回警告消息 + */ + public AjaxResult warn(String message) + { + return AjaxResult.warn(message); + } + + /** + * 响应返回结果 + * + * @param rows 影响行数 + * @return 操作结果 + */ + protected AjaxResult toAjax(int rows) + { + return rows > 0 ? AjaxResult.success() : AjaxResult.error(); + } + + /** + * 响应返回结果 + * + * @param result 结果 + * @return 操作结果 + */ + protected AjaxResult toAjax(boolean result) + { + return result ? success() : error(); + } + + /** + * 页面跳转 + */ + public String redirect(String url) + { + return StringUtils.format("redirect:{}", url); + } + + /** + * 获取用户缓存信息 + */ + public LoginUser getLoginUser() + { + return SecurityUtils.getLoginUser(); + } + + /** + * 获取登录用户id + */ + public Long getUserId() + { + return getLoginUser().getUserId(); + } + + /** + * 获取登录部门id + */ + public Long getDeptId() + { + return getLoginUser().getDeptId(); + } + + /** + * 获取登录用户名 + */ + public String getUsername() + { + return getLoginUser().getUsername(); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java new file mode 100644 index 0000000..9823008 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java @@ -0,0 +1,185 @@ +package com.ruoyi.common.core.domain; + +import java.util.HashMap; +import com.ruoyi.common.constant.HttpStatus; +import com.ruoyi.common.utils.StringUtils; + +/** + * 操作消息提醒 + * + * @author #author# + */ +public class AjaxResult extends HashMap +{ + private static final long serialVersionUID = 1L; + + /** 状态码 */ + public static final String CODE_TAG = "code"; + + /** 返回内容 */ + public static final String MSG_TAG = "msg"; + + /** 数据对象 */ + public static final String DATA_TAG = "data"; + + /** + * 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。 + */ + public AjaxResult() + { + } + + /** + * 初始化一个新创建的 AjaxResult 对象 + * + * @param code 状态码 + * @param msg 返回内容 + */ + public AjaxResult(int code, String msg) + { + super.put(CODE_TAG, code); + super.put(MSG_TAG, msg); + } + + /** + * 初始化一个新创建的 AjaxResult 对象 + * + * @param code 状态码 + * @param msg 返回内容 + * @param data 数据对象 + */ + public AjaxResult(int code, String msg, Object data) + { + super.put(CODE_TAG, code); + super.put(MSG_TAG, msg); + if (StringUtils.isNotNull(data)) + { + super.put(DATA_TAG, data); + } + } + + /** + * 返回成功消息 + * + * @return 成功消息 + */ + public static AjaxResult success() + { + return AjaxResult.success("操作成功"); + } + + /** + * 返回成功数据 + * + * @return 成功消息 + */ + public static AjaxResult success(Object data) + { + return AjaxResult.success("操作成功", data); + } + + /** + * 返回成功消息 + * + * @param msg 返回内容 + * @return 成功消息 + */ + public static AjaxResult success(String msg) + { + return AjaxResult.success(msg, null); + } + + /** + * 返回成功消息 + * + * @param msg 返回内容 + * @param data 数据对象 + * @return 成功消息 + */ + public static AjaxResult success(String msg, Object data) + { + return new AjaxResult(HttpStatus.SUCCESS, msg, data); + } + + /** + * 返回警告消息 + * + * @param msg 返回内容 + * @return 警告消息 + */ + public static AjaxResult warn(String msg) + { + return AjaxResult.warn(msg, null); + } + + /** + * 返回警告消息 + * + * @param msg 返回内容 + * @param data 数据对象 + * @return 警告消息 + */ + public static AjaxResult warn(String msg, Object data) + { + return new AjaxResult(HttpStatus.WARN, msg, data); + } + + /** + * 返回错误消息 + * + * @return 错误消息 + */ + public static AjaxResult error() + { + return AjaxResult.error("操作失败"); + } + + /** + * 返回错误消息 + * + * @param msg 返回内容 + * @return 错误消息 + */ + public static AjaxResult error(String msg) + { + return AjaxResult.error(msg, null); + } + + /** + * 返回错误消息 + * + * @param msg 返回内容 + * @param data 数据对象 + * @return 错误消息 + */ + public static AjaxResult error(String msg, Object data) + { + return new AjaxResult(HttpStatus.ERROR, msg, data); + } + + /** + * 返回错误消息 + * + * @param code 状态码 + * @param msg 返回内容 + * @return 错误消息 + */ + public static AjaxResult error(int code, String msg) + { + return new AjaxResult(code, msg, null); + } + + /** + * 方便链式调用 + * + * @param key 键 + * @param value 值 + * @return 数据对象 + */ + @Override + public AjaxResult put(String key, Object value) + { + super.put(key, value); + return this; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java new file mode 100644 index 0000000..181fd64 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java @@ -0,0 +1,152 @@ +package com.ruoyi.common.core.domain; + +import java.io.Serializable; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.ruoyi.common.annotation.Excel; + +/** + * Entity基类 + * + * @author #author# + */ +public class BaseEntity implements Serializable +{ + private static final long serialVersionUID = 1L; + + /** 主键 */ + private String id; + + /** 搜索值 */ + @JsonIgnore + @TableField(exist = false) + private String searchValue; + + /** 创建者 */ + @TableField(fill = FieldFill.INSERT) + private String createBy; + + /** 创建时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(fill = FieldFill.INSERT) + private Date createTime; + + /** 更新者 */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + /** 更新时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @TableField(fill = FieldFill.INSERT_UPDATE) + private Date updateTime; + + /** 是否删除 */ + @Excel(name = "是否删除") + @TableField(fill = FieldFill.INSERT) + private Long deleted; + + /** 备注 */ + private String remark; + + /** 请求参数 */ + @JsonInclude(JsonInclude.Include.NON_EMPTY) + @TableField(exist = false) + private Map params; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getSearchValue() + { + return searchValue; + } + + public void setSearchValue(String searchValue) + { + this.searchValue = searchValue; + } + + public String getCreateBy() + { + return createBy; + } + + public void setCreateBy(String createBy) + { + this.createBy = createBy; + } + + public Date getCreateTime() + { + return createTime; + } + + public void setCreateTime(Date createTime) + { + this.createTime = createTime; + } + + public String getUpdateBy() + { + return updateBy; + } + + public void setUpdateBy(String updateBy) + { + this.updateBy = updateBy; + } + + public Date getUpdateTime() + { + return updateTime; + } + + public void setUpdateTime(Date updateTime) + { + this.updateTime = updateTime; + } + + public String getRemark() + { + return remark; + } + + public void setRemark(String remark) + { + this.remark = remark; + } + + public Long getDeleted() { + return deleted; + } + + public void setDeleted(Long deleted) { + this.deleted = deleted; + } + + public Map getParams() + { + if (params == null) + { + params = new HashMap<>(); + } + return params; + } + + public void setParams(Map params) + { + this.params = params; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java new file mode 100644 index 0000000..4bd24a1 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java @@ -0,0 +1,115 @@ +package com.ruoyi.common.core.domain; + +import java.io.Serializable; +import com.ruoyi.common.constant.HttpStatus; + +/** + * 响应信息主体 + * + * @author #author# + */ +public class R implements Serializable +{ + private static final long serialVersionUID = 1L; + + /** 成功 */ + public static final int SUCCESS = HttpStatus.SUCCESS; + + /** 失败 */ + public static final int FAIL = HttpStatus.ERROR; + + private int code; + + private String msg; + + private T data; + + public static R ok() + { + return restResult(null, SUCCESS, "操作成功"); + } + + public static R ok(T data) + { + return restResult(data, SUCCESS, "操作成功"); + } + + public static R ok(T data, String msg) + { + return restResult(data, SUCCESS, msg); + } + + public static R fail() + { + return restResult(null, FAIL, "操作失败"); + } + + public static R fail(String msg) + { + return restResult(null, FAIL, msg); + } + + public static R fail(T data) + { + return restResult(data, FAIL, "操作失败"); + } + + public static R fail(T data, String msg) + { + return restResult(data, FAIL, msg); + } + + public static R fail(int code, String msg) + { + return restResult(null, code, msg); + } + + private static R restResult(T data, int code, String msg) + { + R apiResult = new R<>(); + apiResult.setCode(code); + apiResult.setData(data); + apiResult.setMsg(msg); + return apiResult; + } + + public int getCode() + { + return code; + } + + public void setCode(int code) + { + this.code = code; + } + + public String getMsg() + { + return msg; + } + + public void setMsg(String msg) + { + this.msg = msg; + } + + public T getData() + { + return data; + } + + public void setData(T data) + { + this.data = data; + } + + public static Boolean isError(R ret) + { + return !isSuccess(ret); + } + + public static Boolean isSuccess(R ret) + { + return R.SUCCESS == ret.getCode(); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java new file mode 100644 index 0000000..be2ee71 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java @@ -0,0 +1,79 @@ +package com.ruoyi.common.core.domain; + +import java.util.ArrayList; +import java.util.List; + +/** + * Tree基类 + * + * @author #author# + */ +public class TreeEntity extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 父菜单名称 */ + private String parentName; + + /** 父菜单ID */ + private Long parentId; + + /** 显示顺序 */ + private Integer orderNum; + + /** 祖级列表 */ + private String ancestors; + + /** 子部门 */ + private List children = new ArrayList<>(); + + public String getParentName() + { + return parentName; + } + + public void setParentName(String parentName) + { + this.parentName = parentName; + } + + public Long getParentId() + { + return parentId; + } + + public void setParentId(Long parentId) + { + this.parentId = parentId; + } + + public Integer getOrderNum() + { + return orderNum; + } + + public void setOrderNum(Integer orderNum) + { + this.orderNum = orderNum; + } + + public String getAncestors() + { + return ancestors; + } + + public void setAncestors(String ancestors) + { + this.ancestors = ancestors; + } + + public List getChildren() + { + return children; + } + + public void setChildren(List children) + { + this.children = children; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java new file mode 100644 index 0000000..c7a8f6c --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java @@ -0,0 +1,77 @@ +package com.ruoyi.common.core.domain; + +import java.io.Serializable; +import java.util.List; +import java.util.stream.Collectors; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.ruoyi.common.core.domain.entity.SysDept; +import com.ruoyi.common.core.domain.entity.SysMenu; + +/** + * Treeselect树结构实体类 + * + * @author #author# + */ +public class TreeSelect implements Serializable +{ + private static final long serialVersionUID = 1L; + + /** 节点ID */ + private Long id; + + /** 节点名称 */ + private String label; + + /** 子节点 */ + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private List children; + + public TreeSelect() + { + + } + + public TreeSelect(SysDept dept) + { + this.id = dept.getDeptId(); + this.label = dept.getDeptName(); + this.children = dept.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList()); + } + + public TreeSelect(SysMenu menu) + { + this.id = menu.getMenuId(); + this.label = menu.getMenuName(); + this.children = menu.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList()); + } + + public Long getId() + { + return id; + } + + public void setId(Long id) + { + this.id = id; + } + + public String getLabel() + { + return label; + } + + public void setLabel(String label) + { + this.label = label; + } + + public List getChildren() + { + return children; + } + + public void setChildren(List children) + { + this.children = children; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java new file mode 100644 index 0000000..015daa3 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java @@ -0,0 +1,203 @@ +package com.ruoyi.common.core.domain.entity; + +import java.util.ArrayList; +import java.util.List; +import javax.validation.constraints.Email; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 部门表 sys_dept + * + * @author #author# + */ +public class SysDept extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 部门ID */ + private Long deptId; + + /** 父部门ID */ + private Long parentId; + + /** 祖级列表 */ + private String ancestors; + + /** 部门名称 */ + private String deptName; + + /** 显示顺序 */ + private Integer orderNum; + + /** 负责人 */ + private String leader; + + /** 联系电话 */ + private String phone; + + /** 邮箱 */ + private String email; + + /** 部门状态:0正常,1停用 */ + private String status; + + /** 删除标志(0代表存在 2代表删除) */ + private String delFlag; + + /** 父部门名称 */ + private String parentName; + + /** 子部门 */ + private List children = new ArrayList(); + + public Long getDeptId() + { + return deptId; + } + + public void setDeptId(Long deptId) + { + this.deptId = deptId; + } + + public Long getParentId() + { + return parentId; + } + + public void setParentId(Long parentId) + { + this.parentId = parentId; + } + + public String getAncestors() + { + return ancestors; + } + + public void setAncestors(String ancestors) + { + this.ancestors = ancestors; + } + + @NotBlank(message = "部门名称不能为空") + @Size(min = 0, max = 30, message = "部门名称长度不能超过30个字符") + public String getDeptName() + { + return deptName; + } + + public void setDeptName(String deptName) + { + this.deptName = deptName; + } + + @NotNull(message = "显示顺序不能为空") + public Integer getOrderNum() + { + return orderNum; + } + + public void setOrderNum(Integer orderNum) + { + this.orderNum = orderNum; + } + + public String getLeader() + { + return leader; + } + + public void setLeader(String leader) + { + this.leader = leader; + } + + @Size(min = 0, max = 11, message = "联系电话长度不能超过11个字符") + public String getPhone() + { + return phone; + } + + public void setPhone(String phone) + { + this.phone = phone; + } + + @Email(message = "邮箱格式不正确") + @Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符") + public String getEmail() + { + return email; + } + + public void setEmail(String email) + { + this.email = email; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + public String getDelFlag() + { + return delFlag; + } + + public void setDelFlag(String delFlag) + { + this.delFlag = delFlag; + } + + public String getParentName() + { + return parentName; + } + + public void setParentName(String parentName) + { + this.parentName = parentName; + } + + public List getChildren() + { + return children; + } + + public void setChildren(List children) + { + this.children = children; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("deptId", getDeptId()) + .append("parentId", getParentId()) + .append("ancestors", getAncestors()) + .append("deptName", getDeptName()) + .append("orderNum", getOrderNum()) + .append("leader", getLeader()) + .append("phone", getPhone()) + .append("email", getEmail()) + .append("status", getStatus()) + .append("delFlag", getDelFlag()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .toString(); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java new file mode 100644 index 0000000..db584c5 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java @@ -0,0 +1,176 @@ +package com.ruoyi.common.core.domain.entity; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; +import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 字典数据表 sys_dict_data + * + * @author #author# + */ +public class SysDictData extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 字典编码 */ + @Excel(name = "字典编码", cellType = ColumnType.NUMERIC) + private Long dictCode; + + /** 字典排序 */ + @Excel(name = "字典排序", cellType = ColumnType.NUMERIC) + private Long dictSort; + + /** 字典标签 */ + @Excel(name = "字典标签") + private String dictLabel; + + /** 字典键值 */ + @Excel(name = "字典键值") + private String dictValue; + + /** 字典类型 */ + @Excel(name = "字典类型") + private String dictType; + + /** 样式属性(其他样式扩展) */ + private String cssClass; + + /** 表格字典样式 */ + private String listClass; + + /** 是否默认(Y是 N否) */ + @Excel(name = "是否默认", readConverterExp = "Y=是,N=否") + private String isDefault; + + /** 状态(0正常 1停用) */ + @Excel(name = "状态", readConverterExp = "0=正常,1=停用") + private String status; + + public Long getDictCode() + { + return dictCode; + } + + public void setDictCode(Long dictCode) + { + this.dictCode = dictCode; + } + + public Long getDictSort() + { + return dictSort; + } + + public void setDictSort(Long dictSort) + { + this.dictSort = dictSort; + } + + @NotBlank(message = "字典标签不能为空") + @Size(min = 0, max = 100, message = "字典标签长度不能超过100个字符") + public String getDictLabel() + { + return dictLabel; + } + + public void setDictLabel(String dictLabel) + { + this.dictLabel = dictLabel; + } + + @NotBlank(message = "字典键值不能为空") + @Size(min = 0, max = 100, message = "字典键值长度不能超过100个字符") + public String getDictValue() + { + return dictValue; + } + + public void setDictValue(String dictValue) + { + this.dictValue = dictValue; + } + + @NotBlank(message = "字典类型不能为空") + @Size(min = 0, max = 100, message = "字典类型长度不能超过100个字符") + public String getDictType() + { + return dictType; + } + + public void setDictType(String dictType) + { + this.dictType = dictType; + } + + @Size(min = 0, max = 100, message = "样式属性长度不能超过100个字符") + public String getCssClass() + { + return cssClass; + } + + public void setCssClass(String cssClass) + { + this.cssClass = cssClass; + } + + public String getListClass() + { + return listClass; + } + + public void setListClass(String listClass) + { + this.listClass = listClass; + } + + public boolean getDefault() + { + return UserConstants.YES.equals(this.isDefault); + } + + public String getIsDefault() + { + return isDefault; + } + + public void setIsDefault(String isDefault) + { + this.isDefault = isDefault; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("dictCode", getDictCode()) + .append("dictSort", getDictSort()) + .append("dictLabel", getDictLabel()) + .append("dictValue", getDictValue()) + .append("dictType", getDictType()) + .append("cssClass", getCssClass()) + .append("listClass", getListClass()) + .append("isDefault", getIsDefault()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java new file mode 100644 index 0000000..e1c3686 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java @@ -0,0 +1,96 @@ +package com.ruoyi.common.core.domain.entity; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 字典类型表 sys_dict_type + * + * @author #author# + */ +public class SysDictType extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 字典主键 */ + @Excel(name = "字典主键", cellType = ColumnType.NUMERIC) + private Long dictId; + + /** 字典名称 */ + @Excel(name = "字典名称") + private String dictName; + + /** 字典类型 */ + @Excel(name = "字典类型") + private String dictType; + + /** 状态(0正常 1停用) */ + @Excel(name = "状态", readConverterExp = "0=正常,1=停用") + private String status; + + public Long getDictId() + { + return dictId; + } + + public void setDictId(Long dictId) + { + this.dictId = dictId; + } + + @NotBlank(message = "字典名称不能为空") + @Size(min = 0, max = 100, message = "字典类型名称长度不能超过100个字符") + public String getDictName() + { + return dictName; + } + + public void setDictName(String dictName) + { + this.dictName = dictName; + } + + @NotBlank(message = "字典类型不能为空") + @Size(min = 0, max = 100, message = "字典类型类型长度不能超过100个字符") + @Pattern(regexp = "^[a-z][a-z0-9_]*$", message = "字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)") + public String getDictType() + { + return dictType; + } + + public void setDictType(String dictType) + { + this.dictType = dictType; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("dictId", getDictId()) + .append("dictName", getDictName()) + .append("dictType", getDictType()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java new file mode 100644 index 0000000..fae0ee6 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java @@ -0,0 +1,259 @@ +package com.ruoyi.common.core.domain.entity; + +import java.util.ArrayList; +import java.util.List; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 菜单权限表 sys_menu + * + * @author #author# + */ +public class SysMenu extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 菜单ID */ + private Long menuId; + + /** 菜单名称 */ + private String menuName; + + /** 父菜单名称 */ + private String parentName; + + /** 父菜单ID */ + private Long parentId; + + /** 显示顺序 */ + private Integer orderNum; + + /** 路由地址 */ + private String path; + + /** 组件路径 */ + private String component; + + /** 路由参数 */ + private String query; + + /** 是否为外链(0是 1否) */ + private String isFrame; + + /** 是否缓存(0缓存 1不缓存) */ + private String isCache; + + /** 类型(M目录 C菜单 F按钮) */ + private String menuType; + + /** 显示状态(0显示 1隐藏) */ + private String visible; + + /** 菜单状态(0正常 1停用) */ + private String status; + + /** 权限字符串 */ + private String perms; + + /** 菜单图标 */ + private String icon; + + /** 子菜单 */ + private List children = new ArrayList(); + + public Long getMenuId() + { + return menuId; + } + + public void setMenuId(Long menuId) + { + this.menuId = menuId; + } + + @NotBlank(message = "菜单名称不能为空") + @Size(min = 0, max = 50, message = "菜单名称长度不能超过50个字符") + public String getMenuName() + { + return menuName; + } + + public void setMenuName(String menuName) + { + this.menuName = menuName; + } + + public String getParentName() + { + return parentName; + } + + public void setParentName(String parentName) + { + this.parentName = parentName; + } + + public Long getParentId() + { + return parentId; + } + + public void setParentId(Long parentId) + { + this.parentId = parentId; + } + + @NotNull(message = "显示顺序不能为空") + public Integer getOrderNum() + { + return orderNum; + } + + public void setOrderNum(Integer orderNum) + { + this.orderNum = orderNum; + } + + @Size(min = 0, max = 200, message = "路由地址不能超过200个字符") + public String getPath() + { + return path; + } + + public void setPath(String path) + { + this.path = path; + } + + @Size(min = 0, max = 200, message = "组件路径不能超过255个字符") + public String getComponent() + { + return component; + } + + public void setComponent(String component) + { + this.component = component; + } + + public String getQuery() + { + return query; + } + + public void setQuery(String query) + { + this.query = query; + } + + public String getIsFrame() + { + return isFrame; + } + + public void setIsFrame(String isFrame) + { + this.isFrame = isFrame; + } + + public String getIsCache() + { + return isCache; + } + + public void setIsCache(String isCache) + { + this.isCache = isCache; + } + + @NotBlank(message = "菜单类型不能为空") + public String getMenuType() + { + return menuType; + } + + public void setMenuType(String menuType) + { + this.menuType = menuType; + } + + public String getVisible() + { + return visible; + } + + public void setVisible(String visible) + { + this.visible = visible; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + @Size(min = 0, max = 100, message = "权限标识长度不能超过100个字符") + public String getPerms() + { + return perms; + } + + public void setPerms(String perms) + { + this.perms = perms; + } + + public String getIcon() + { + return icon; + } + + public void setIcon(String icon) + { + this.icon = icon; + } + + public List getChildren() + { + return children; + } + + public void setChildren(List children) + { + this.children = children; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("menuId", getMenuId()) + .append("menuName", getMenuName()) + .append("parentId", getParentId()) + .append("orderNum", getOrderNum()) + .append("path", getPath()) + .append("component", getComponent()) + .append("isFrame", getIsFrame()) + .append("IsCache", getIsCache()) + .append("menuType", getMenuType()) + .append("visible", getVisible()) + .append("status ", getStatus()) + .append("perms", getPerms()) + .append("icon", getIcon()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java new file mode 100644 index 0000000..5cac2a1 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java @@ -0,0 +1,241 @@ +package com.ruoyi.common.core.domain.entity; + +import java.util.Set; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 角色表 sys_role + * + * @author #author# + */ +public class SysRole extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 角色ID */ + @Excel(name = "角色序号", cellType = ColumnType.NUMERIC) + private Long roleId; + + /** 角色名称 */ + @Excel(name = "角色名称") + private String roleName; + + /** 角色权限 */ + @Excel(name = "角色权限") + private String roleKey; + + /** 角色排序 */ + @Excel(name = "角色排序") + private Integer roleSort; + + /** 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限) */ + @Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限,5=仅本人数据权限") + private String dataScope; + + /** 菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示) */ + private boolean menuCheckStrictly; + + /** 部门树选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示 ) */ + private boolean deptCheckStrictly; + + /** 角色状态(0正常 1停用) */ + @Excel(name = "角色状态", readConverterExp = "0=正常,1=停用") + private String status; + + /** 删除标志(0代表存在 2代表删除) */ + private String delFlag; + + /** 用户是否存在此角色标识 默认不存在 */ + private boolean flag = false; + + /** 菜单组 */ + private Long[] menuIds; + + /** 部门组(数据权限) */ + private Long[] deptIds; + + /** 角色菜单权限 */ + private Set permissions; + + public SysRole() + { + + } + + public SysRole(Long roleId) + { + this.roleId = roleId; + } + + public Long getRoleId() + { + return roleId; + } + + public void setRoleId(Long roleId) + { + this.roleId = roleId; + } + + public boolean isAdmin() + { + return isAdmin(this.roleId); + } + + public static boolean isAdmin(Long roleId) + { + return roleId != null && 1L == roleId; + } + + @NotBlank(message = "角色名称不能为空") + @Size(min = 0, max = 30, message = "角色名称长度不能超过30个字符") + public String getRoleName() + { + return roleName; + } + + public void setRoleName(String roleName) + { + this.roleName = roleName; + } + + @NotBlank(message = "权限字符不能为空") + @Size(min = 0, max = 100, message = "权限字符长度不能超过100个字符") + public String getRoleKey() + { + return roleKey; + } + + public void setRoleKey(String roleKey) + { + this.roleKey = roleKey; + } + + @NotNull(message = "显示顺序不能为空") + public Integer getRoleSort() + { + return roleSort; + } + + public void setRoleSort(Integer roleSort) + { + this.roleSort = roleSort; + } + + public String getDataScope() + { + return dataScope; + } + + public void setDataScope(String dataScope) + { + this.dataScope = dataScope; + } + + public boolean isMenuCheckStrictly() + { + return menuCheckStrictly; + } + + public void setMenuCheckStrictly(boolean menuCheckStrictly) + { + this.menuCheckStrictly = menuCheckStrictly; + } + + public boolean isDeptCheckStrictly() + { + return deptCheckStrictly; + } + + public void setDeptCheckStrictly(boolean deptCheckStrictly) + { + this.deptCheckStrictly = deptCheckStrictly; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + public String getDelFlag() + { + return delFlag; + } + + public void setDelFlag(String delFlag) + { + this.delFlag = delFlag; + } + + public boolean isFlag() + { + return flag; + } + + public void setFlag(boolean flag) + { + this.flag = flag; + } + + public Long[] getMenuIds() + { + return menuIds; + } + + public void setMenuIds(Long[] menuIds) + { + this.menuIds = menuIds; + } + + public Long[] getDeptIds() + { + return deptIds; + } + + public void setDeptIds(Long[] deptIds) + { + this.deptIds = deptIds; + } + + public Set getPermissions() + { + return permissions; + } + + public void setPermissions(Set permissions) + { + this.permissions = permissions; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("roleId", getRoleId()) + .append("roleName", getRoleName()) + .append("roleKey", getRoleKey()) + .append("roleSort", getRoleSort()) + .append("dataScope", getDataScope()) + .append("menuCheckStrictly", isMenuCheckStrictly()) + .append("deptCheckStrictly", isDeptCheckStrictly()) + .append("status", getStatus()) + .append("delFlag", getDelFlag()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java new file mode 100644 index 0000000..7d868e8 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java @@ -0,0 +1,324 @@ +package com.ruoyi.common.core.domain.entity; + +import java.util.Date; +import java.util.List; +import javax.validation.constraints.*; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; +import com.ruoyi.common.annotation.Excel.Type; +import com.ruoyi.common.annotation.Excels; +import com.ruoyi.common.core.domain.BaseEntity; +import com.ruoyi.common.xss.Xss; + +/** + * 用户对象 sys_user + * + * @author #author# + */ +public class SysUser extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 用户ID */ + @Excel(name = "用户序号", cellType = ColumnType.NUMERIC, prompt = "用户编号") + private Long userId; + + /** 部门ID */ + @Excel(name = "部门编号", type = Type.IMPORT) + private Long deptId; + + /** 用户账号 */ + @Excel(name = "登录名称") + private String userName; + + /** 用户昵称 */ + @Excel(name = "用户名称") + private String nickName; + + /** 用户邮箱 */ + @Excel(name = "用户邮箱") + private String email; + + /** 手机号码 */ + @Excel(name = "手机号码") + private String phonenumber; + + /** 用户性别 */ + @Excel(name = "用户性别", readConverterExp = "0=男,1=女,2=未知") + private String sex; + + /** 用户头像 */ + private String avatar; + + /** 密码 */ + private String password; + + /** 帐号状态(0正常 1停用) */ + @Excel(name = "帐号状态", readConverterExp = "0=正常,1=停用") + private String status; + + /** 删除标志(0代表存在 2代表删除) */ + private String delFlag; + + /** 最后登录IP */ + @Excel(name = "最后登录IP", type = Type.EXPORT) + private String loginIp; + + /** 最后登录时间 */ + @Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT) + private Date loginDate; + + /** 部门对象 */ + @Excels({ + @Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT), + @Excel(name = "部门负责人", targetAttr = "leader", type = Type.EXPORT) + }) + private SysDept dept; + + /** 角色对象 */ + private List roles; + + /** 角色组 */ + private Long[] roleIds; + + /** 岗位组 */ + private Long[] postIds; + + /** 角色ID */ + private Long roleId; + + public SysUser() + { + + } + + public SysUser(Long userId) + { + this.userId = userId; + } + + public Long getUserId() + { + return userId; + } + + public void setUserId(Long userId) + { + this.userId = userId; + } + + public boolean isAdmin() + { + return isAdmin(this.userId); + } + + public static boolean isAdmin(Long userId) + { + return userId != null && 1L == userId; + } + + public Long getDeptId() + { + return deptId; + } + + public void setDeptId(Long deptId) + { + this.deptId = deptId; + } + + @Xss(message = "用户昵称不能包含脚本字符") + @Size(min = 0, max = 30, message = "用户昵称长度不能超过30个字符") + public String getNickName() + { + return nickName; + } + + public void setNickName(String nickName) + { + this.nickName = nickName; + } + + @Xss(message = "用户账号不能包含脚本字符") + @NotBlank(message = "用户账号不能为空") + @Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符") + public String getUserName() + { + return userName; + } + + public void setUserName(String userName) + { + this.userName = userName; + } + + @Email(message = "邮箱格式不正确") + @Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符") + public String getEmail() + { + return email; + } + + public void setEmail(String email) + { + this.email = email; + } + + @Size(min = 0, max = 11, message = "手机号码长度不能超过11个字符") + public String getPhonenumber() + { + return phonenumber; + } + + public void setPhonenumber(String phonenumber) + { + this.phonenumber = phonenumber; + } + + public String getSex() + { + return sex; + } + + public void setSex(String sex) + { + this.sex = sex; + } + + public String getAvatar() + { + return avatar; + } + + public void setAvatar(String avatar) + { + this.avatar = avatar; + } + + public String getPassword() + { + return password; + } + + public void setPassword(String password) + { + this.password = password; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + public String getDelFlag() + { + return delFlag; + } + + public void setDelFlag(String delFlag) + { + this.delFlag = delFlag; + } + + public String getLoginIp() + { + return loginIp; + } + + public void setLoginIp(String loginIp) + { + this.loginIp = loginIp; + } + + public Date getLoginDate() + { + return loginDate; + } + + public void setLoginDate(Date loginDate) + { + this.loginDate = loginDate; + } + + public SysDept getDept() + { + return dept; + } + + public void setDept(SysDept dept) + { + this.dept = dept; + } + + public List getRoles() + { + return roles; + } + + public void setRoles(List roles) + { + this.roles = roles; + } + + public Long[] getRoleIds() + { + return roleIds; + } + + public void setRoleIds(Long[] roleIds) + { + this.roleIds = roleIds; + } + + public Long[] getPostIds() + { + return postIds; + } + + public void setPostIds(Long[] postIds) + { + this.postIds = postIds; + } + + public Long getRoleId() + { + return roleId; + } + + public void setRoleId(Long roleId) + { + this.roleId = roleId; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("userId", getUserId()) + .append("deptId", getDeptId()) + .append("userName", getUserName()) + .append("nickName", getNickName()) + .append("email", getEmail()) + .append("phonenumber", getPhonenumber()) + .append("sex", getSex()) + .append("avatar", getAvatar()) + .append("password", getPassword()) + .append("status", getStatus()) + .append("delFlag", getDelFlag()) + .append("loginIp", getLoginIp()) + .append("loginDate", getLoginDate()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .append("dept", getDept()) + .toString(); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java new file mode 100644 index 0000000..a8651bb --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java @@ -0,0 +1,69 @@ +package com.ruoyi.common.core.domain.model; + +/** + * 用户登录对象 + * + * @author #author# + */ +public class LoginBody +{ + /** + * 用户名 + */ + private String username; + + /** + * 用户密码 + */ + private String password; + + /** + * 验证码 + */ + private String code; + + /** + * 唯一标识 + */ + private String uuid; + + public String getUsername() + { + return username; + } + + public void setUsername(String username) + { + this.username = username; + } + + public String getPassword() + { + return password; + } + + public void setPassword(String password) + { + this.password = password; + } + + public String getCode() + { + return code; + } + + public void setCode(String code) + { + this.code = code; + } + + public String getUuid() + { + return uuid; + } + + public void setUuid(String uuid) + { + this.uuid = uuid; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java new file mode 100644 index 0000000..26feb5f --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java @@ -0,0 +1,266 @@ +package com.ruoyi.common.core.domain.model; + +import java.util.Collection; +import java.util.Set; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import com.alibaba.fastjson2.annotation.JSONField; +import com.ruoyi.common.core.domain.entity.SysUser; + +/** + * 登录用户身份权限 + * + * @author #author# + */ +public class LoginUser implements UserDetails +{ + private static final long serialVersionUID = 1L; + + /** + * 用户ID + */ + private Long userId; + + /** + * 部门ID + */ + private Long deptId; + + /** + * 用户唯一标识 + */ + private String token; + + /** + * 登录时间 + */ + private Long loginTime; + + /** + * 过期时间 + */ + private Long expireTime; + + /** + * 登录IP地址 + */ + private String ipaddr; + + /** + * 登录地点 + */ + private String loginLocation; + + /** + * 浏览器类型 + */ + private String browser; + + /** + * 操作系统 + */ + private String os; + + /** + * 权限列表 + */ + private Set permissions; + + /** + * 用户信息 + */ + private SysUser user; + + public Long getUserId() + { + return userId; + } + + public void setUserId(Long userId) + { + this.userId = userId; + } + + public Long getDeptId() + { + return deptId; + } + + public void setDeptId(Long deptId) + { + this.deptId = deptId; + } + + public String getToken() + { + return token; + } + + public void setToken(String token) + { + this.token = token; + } + + public LoginUser() + { + } + + public LoginUser(SysUser user, Set permissions) + { + this.user = user; + this.permissions = permissions; + } + + public LoginUser(Long userId, Long deptId, SysUser user, Set permissions) + { + this.userId = userId; + this.deptId = deptId; + this.user = user; + this.permissions = permissions; + } + + @JSONField(serialize = false) + @Override + public String getPassword() + { + return user.getPassword(); + } + + @Override + public String getUsername() + { + return user.getUserName(); + } + + /** + * 账户是否未过期,过期无法验证 + */ + @JSONField(serialize = false) + @Override + public boolean isAccountNonExpired() + { + return true; + } + + /** + * 指定用户是否解锁,锁定的用户无法进行身份验证 + * + * @return + */ + @JSONField(serialize = false) + @Override + public boolean isAccountNonLocked() + { + return true; + } + + /** + * 指示是否已过期的用户的凭据(密码),过期的凭据防止认证 + * + * @return + */ + @JSONField(serialize = false) + @Override + public boolean isCredentialsNonExpired() + { + return true; + } + + /** + * 是否可用 ,禁用的用户不能身份验证 + * + * @return + */ + @JSONField(serialize = false) + @Override + public boolean isEnabled() + { + return true; + } + + public Long getLoginTime() + { + return loginTime; + } + + public void setLoginTime(Long loginTime) + { + this.loginTime = loginTime; + } + + public String getIpaddr() + { + return ipaddr; + } + + public void setIpaddr(String ipaddr) + { + this.ipaddr = ipaddr; + } + + public String getLoginLocation() + { + return loginLocation; + } + + public void setLoginLocation(String loginLocation) + { + this.loginLocation = loginLocation; + } + + public String getBrowser() + { + return browser; + } + + public void setBrowser(String browser) + { + this.browser = browser; + } + + public String getOs() + { + return os; + } + + public void setOs(String os) + { + this.os = os; + } + + public Long getExpireTime() + { + return expireTime; + } + + public void setExpireTime(Long expireTime) + { + this.expireTime = expireTime; + } + + public Set getPermissions() + { + return permissions; + } + + public void setPermissions(Set permissions) + { + this.permissions = permissions; + } + + public SysUser getUser() + { + return user; + } + + public void setUser(SysUser user) + { + this.user = user; + } + + @Override + public Collection getAuthorities() + { + return null; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java new file mode 100644 index 0000000..9ef3065 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java @@ -0,0 +1,11 @@ +package com.ruoyi.common.core.domain.model; + +/** + * 用户注册对象 + * + * @author #author# + */ +public class RegisterBody extends LoginBody +{ + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java new file mode 100644 index 0000000..ad02385 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java @@ -0,0 +1,101 @@ +package com.ruoyi.common.core.page; + +import com.ruoyi.common.utils.StringUtils; + +/** + * 分页数据 + * + * @author #author# + */ +public class PageDomain +{ + /** 当前记录起始索引 */ + private Integer pageNum; + + /** 每页显示记录数 */ + private Integer pageSize; + + /** 排序列 */ + private String orderByColumn; + + /** 排序的方向desc或者asc */ + private String isAsc = "asc"; + + /** 分页参数合理化 */ + private Boolean reasonable = true; + + public String getOrderBy() + { + if (StringUtils.isEmpty(orderByColumn)) + { + return ""; + } + return StringUtils.toUnderScoreCase(orderByColumn) + " " + isAsc; + } + + public Integer getPageNum() + { + return pageNum; + } + + public void setPageNum(Integer pageNum) + { + this.pageNum = pageNum; + } + + public Integer getPageSize() + { + return pageSize; + } + + public void setPageSize(Integer pageSize) + { + this.pageSize = pageSize; + } + + public String getOrderByColumn() + { + return orderByColumn; + } + + public void setOrderByColumn(String orderByColumn) + { + this.orderByColumn = orderByColumn; + } + + public String getIsAsc() + { + return isAsc; + } + + public void setIsAsc(String isAsc) + { + if (StringUtils.isNotEmpty(isAsc)) + { + // 兼容前端排序类型 + if ("ascending".equals(isAsc)) + { + isAsc = "asc"; + } + else if ("descending".equals(isAsc)) + { + isAsc = "desc"; + } + this.isAsc = isAsc; + } + } + + public Boolean getReasonable() + { + if (StringUtils.isNull(reasonable)) + { + return Boolean.TRUE; + } + return reasonable; + } + + public void setReasonable(Boolean reasonable) + { + this.reasonable = reasonable; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java new file mode 100644 index 0000000..b2a3541 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java @@ -0,0 +1,85 @@ +package com.ruoyi.common.core.page; + +import java.io.Serializable; +import java.util.List; + +/** + * 表格分页数据对象 + * + * @author #author# + */ +public class TableDataInfo implements Serializable +{ + private static final long serialVersionUID = 1L; + + /** 总记录数 */ + private long total; + + /** 列表数据 */ + private List rows; + + /** 消息状态码 */ + private int code; + + /** 消息内容 */ + private String msg; + + /** + * 表格数据对象 + */ + public TableDataInfo() + { + } + + /** + * 分页 + * + * @param list 列表数据 + * @param total 总记录数 + */ + public TableDataInfo(List list, int total) + { + this.rows = list; + this.total = total; + } + + public long getTotal() + { + return total; + } + + public void setTotal(long total) + { + this.total = total; + } + + public List getRows() + { + return rows; + } + + public void setRows(List rows) + { + this.rows = rows; + } + + public int getCode() + { + return code; + } + + public void setCode(int code) + { + this.code = code; + } + + public String getMsg() + { + return msg; + } + + public void setMsg(String msg) + { + this.msg = msg; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java new file mode 100644 index 0000000..af9b257 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java @@ -0,0 +1,56 @@ +package com.ruoyi.common.core.page; + +import com.ruoyi.common.core.text.Convert; +import com.ruoyi.common.utils.ServletUtils; + +/** + * 表格数据处理 + * + * @author #author# + */ +public class TableSupport +{ + /** + * 当前记录起始索引 + */ + public static final String PAGE_NUM = "pageNum"; + + /** + * 每页显示记录数 + */ + public static final String PAGE_SIZE = "pageSize"; + + /** + * 排序列 + */ + public static final String ORDER_BY_COLUMN = "orderByColumn"; + + /** + * 排序的方向 "desc" 或者 "asc". + */ + public static final String IS_ASC = "isAsc"; + + /** + * 分页参数合理化 + */ + public static final String REASONABLE = "reasonable"; + + /** + * 封装分页对象 + */ + public static PageDomain getPageDomain() + { + PageDomain pageDomain = new PageDomain(); + pageDomain.setPageNum(Convert.toInt(ServletUtils.getParameter(PAGE_NUM), 1)); + pageDomain.setPageSize(Convert.toInt(ServletUtils.getParameter(PAGE_SIZE), 10)); + pageDomain.setOrderByColumn(ServletUtils.getParameter(ORDER_BY_COLUMN)); + pageDomain.setIsAsc(ServletUtils.getParameter(IS_ASC)); + pageDomain.setReasonable(ServletUtils.getParameterToBool(REASONABLE)); + return pageDomain; + } + + public static PageDomain buildPageRequest() + { + return getPageDomain(); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java new file mode 100644 index 0000000..fd6062f --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java @@ -0,0 +1,268 @@ +package com.ruoyi.common.core.redis; + +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.BoundSetOperations; +import org.springframework.data.redis.core.HashOperations; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.ValueOperations; +import org.springframework.stereotype.Component; + +/** + * spring redis 工具类 + * + * @author #author# + **/ +@SuppressWarnings(value = { "unchecked", "rawtypes" }) +@Component +public class RedisCache +{ + @Autowired + public RedisTemplate redisTemplate; + + /** + * 缓存基本的对象,Integer、String、实体类等 + * + * @param key 缓存的键值 + * @param value 缓存的值 + */ + public void setCacheObject(final String key, final T value) + { + redisTemplate.opsForValue().set(key, value); + } + + /** + * 缓存基本的对象,Integer、String、实体类等 + * + * @param key 缓存的键值 + * @param value 缓存的值 + * @param timeout 时间 + * @param timeUnit 时间颗粒度 + */ + public void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) + { + redisTemplate.opsForValue().set(key, value, timeout, timeUnit); + } + + /** + * 设置有效时间 + * + * @param key Redis键 + * @param timeout 超时时间 + * @return true=设置成功;false=设置失败 + */ + public boolean expire(final String key, final long timeout) + { + return expire(key, timeout, TimeUnit.SECONDS); + } + + /** + * 设置有效时间 + * + * @param key Redis键 + * @param timeout 超时时间 + * @param unit 时间单位 + * @return true=设置成功;false=设置失败 + */ + public boolean expire(final String key, final long timeout, final TimeUnit unit) + { + return redisTemplate.expire(key, timeout, unit); + } + + /** + * 获取有效时间 + * + * @param key Redis键 + * @return 有效时间 + */ + public long getExpire(final String key) + { + return redisTemplate.getExpire(key); + } + + /** + * 判断 key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public Boolean hasKey(String key) + { + return redisTemplate.hasKey(key); + } + + /** + * 获得缓存的基本对象。 + * + * @param key 缓存键值 + * @return 缓存键值对应的数据 + */ + public T getCacheObject(final String key) + { + ValueOperations operation = redisTemplate.opsForValue(); + return operation.get(key); + } + + /** + * 删除单个对象 + * + * @param key + */ + public boolean deleteObject(final String key) + { + return redisTemplate.delete(key); + } + + /** + * 删除集合对象 + * + * @param collection 多个对象 + * @return + */ + public boolean deleteObject(final Collection collection) + { + return redisTemplate.delete(collection) > 0; + } + + /** + * 缓存List数据 + * + * @param key 缓存的键值 + * @param dataList 待缓存的List数据 + * @return 缓存的对象 + */ + public long setCacheList(final String key, final List dataList) + { + Long count = redisTemplate.opsForList().rightPushAll(key, dataList); + return count == null ? 0 : count; + } + + /** + * 获得缓存的list对象 + * + * @param key 缓存的键值 + * @return 缓存键值对应的数据 + */ + public List getCacheList(final String key) + { + return redisTemplate.opsForList().range(key, 0, -1); + } + + /** + * 缓存Set + * + * @param key 缓存键值 + * @param dataSet 缓存的数据 + * @return 缓存数据的对象 + */ + public BoundSetOperations setCacheSet(final String key, final Set dataSet) + { + BoundSetOperations setOperation = redisTemplate.boundSetOps(key); + Iterator it = dataSet.iterator(); + while (it.hasNext()) + { + setOperation.add(it.next()); + } + return setOperation; + } + + /** + * 获得缓存的set + * + * @param key + * @return + */ + public Set getCacheSet(final String key) + { + return redisTemplate.opsForSet().members(key); + } + + /** + * 缓存Map + * + * @param key + * @param dataMap + */ + public void setCacheMap(final String key, final Map dataMap) + { + if (dataMap != null) { + redisTemplate.opsForHash().putAll(key, dataMap); + } + } + + /** + * 获得缓存的Map + * + * @param key + * @return + */ + public Map getCacheMap(final String key) + { + return redisTemplate.opsForHash().entries(key); + } + + /** + * 往Hash中存入数据 + * + * @param key Redis键 + * @param hKey Hash键 + * @param value 值 + */ + public void setCacheMapValue(final String key, final String hKey, final T value) + { + redisTemplate.opsForHash().put(key, hKey, value); + } + + /** + * 获取Hash中的数据 + * + * @param key Redis键 + * @param hKey Hash键 + * @return Hash中的对象 + */ + public T getCacheMapValue(final String key, final String hKey) + { + HashOperations opsForHash = redisTemplate.opsForHash(); + return opsForHash.get(key, hKey); + } + + /** + * 获取多个Hash中的数据 + * + * @param key Redis键 + * @param hKeys Hash键集合 + * @return Hash对象集合 + */ + public List getMultiCacheMapValue(final String key, final Collection hKeys) + { + return redisTemplate.opsForHash().multiGet(key, hKeys); + } + + /** + * 删除Hash中的某条数据 + * + * @param key Redis键 + * @param hKey Hash键 + * @return 是否成功 + */ + public boolean deleteCacheMapValue(final String key, final String hKey) + { + return redisTemplate.opsForHash().delete(key, hKey) > 0; + } + + /** + * 获得缓存的基本对象列表 + * + * @param pattern 字符串前缀 + * @return 对象列表 + */ + public Collection keys(final String pattern) + { + return redisTemplate.keys(pattern); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/text/CharsetKit.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/CharsetKit.java new file mode 100644 index 0000000..8220fe7 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/CharsetKit.java @@ -0,0 +1,86 @@ +package com.ruoyi.common.core.text; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import com.ruoyi.common.utils.StringUtils; + +/** + * 字符集工具类 + * + * @author #author# + */ +public class CharsetKit +{ + /** ISO-8859-1 */ + public static final String ISO_8859_1 = "ISO-8859-1"; + /** UTF-8 */ + public static final String UTF_8 = "UTF-8"; + /** GBK */ + public static final String GBK = "GBK"; + + /** ISO-8859-1 */ + public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1); + /** UTF-8 */ + public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8); + /** GBK */ + public static final Charset CHARSET_GBK = Charset.forName(GBK); + + /** + * 转换为Charset对象 + * + * @param charset 字符集,为空则返回默认字符集 + * @return Charset + */ + public static Charset charset(String charset) + { + return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset); + } + + /** + * 转换字符串的字符集编码 + * + * @param source 字符串 + * @param srcCharset 源字符集,默认ISO-8859-1 + * @param destCharset 目标字符集,默认UTF-8 + * @return 转换后的字符集 + */ + public static String convert(String source, String srcCharset, String destCharset) + { + return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset)); + } + + /** + * 转换字符串的字符集编码 + * + * @param source 字符串 + * @param srcCharset 源字符集,默认ISO-8859-1 + * @param destCharset 目标字符集,默认UTF-8 + * @return 转换后的字符集 + */ + public static String convert(String source, Charset srcCharset, Charset destCharset) + { + if (null == srcCharset) + { + srcCharset = StandardCharsets.ISO_8859_1; + } + + if (null == destCharset) + { + destCharset = StandardCharsets.UTF_8; + } + + if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset)) + { + return source; + } + return new String(source.getBytes(srcCharset), destCharset); + } + + /** + * @return 系统字符集编码 + */ + public static String systemCharset() + { + return Charset.defaultCharset().name(); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java new file mode 100644 index 0000000..453e659 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java @@ -0,0 +1,1000 @@ +package com.ruoyi.common.core.text; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.text.NumberFormat; +import java.util.Set; +import com.ruoyi.common.utils.StringUtils; +import org.apache.commons.lang3.ArrayUtils; + +/** + * 类型转换器 + * + * @author #author# + */ +public class Convert +{ + /** + * 转换为字符串
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static String toStr(Object value, String defaultValue) + { + if (null == value) + { + return defaultValue; + } + if (value instanceof String) + { + return (String) value; + } + return value.toString(); + } + + /** + * 转换为字符串
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static String toStr(Object value) + { + return toStr(value, null); + } + + /** + * 转换为字符
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Character toChar(Object value, Character defaultValue) + { + if (null == value) + { + return defaultValue; + } + if (value instanceof Character) + { + return (Character) value; + } + + final String valueStr = toStr(value, null); + return StringUtils.isEmpty(valueStr) ? defaultValue : valueStr.charAt(0); + } + + /** + * 转换为字符
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Character toChar(Object value) + { + return toChar(value, null); + } + + /** + * 转换为byte
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Byte toByte(Object value, Byte defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Byte) + { + return (Byte) value; + } + if (value instanceof Number) + { + return ((Number) value).byteValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Byte.parseByte(valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为byte
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Byte toByte(Object value) + { + return toByte(value, null); + } + + /** + * 转换为Short
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Short toShort(Object value, Short defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Short) + { + return (Short) value; + } + if (value instanceof Number) + { + return ((Number) value).shortValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Short.parseShort(valueStr.trim()); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为Short
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Short toShort(Object value) + { + return toShort(value, null); + } + + /** + * 转换为Number
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Number toNumber(Object value, Number defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Number) + { + return (Number) value; + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return NumberFormat.getInstance().parse(valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为Number
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Number toNumber(Object value) + { + return toNumber(value, null); + } + + /** + * 转换为int
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Integer toInt(Object value, Integer defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Integer) + { + return (Integer) value; + } + if (value instanceof Number) + { + return ((Number) value).intValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Integer.parseInt(valueStr.trim()); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为int
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Integer toInt(Object value) + { + return toInt(value, null); + } + + /** + * 转换为Integer数组
+ * + * @param str 被转换的值 + * @return 结果 + */ + public static Integer[] toIntArray(String str) + { + return toIntArray(",", str); + } + + /** + * 转换为Long数组
+ * + * @param str 被转换的值 + * @return 结果 + */ + public static Long[] toLongArray(String str) + { + return toLongArray(",", str); + } + + /** + * 转换为Integer数组
+ * + * @param split 分隔符 + * @param split 被转换的值 + * @return 结果 + */ + public static Integer[] toIntArray(String split, String str) + { + if (StringUtils.isEmpty(str)) + { + return new Integer[] {}; + } + String[] arr = str.split(split); + final Integer[] ints = new Integer[arr.length]; + for (int i = 0; i < arr.length; i++) + { + final Integer v = toInt(arr[i], 0); + ints[i] = v; + } + return ints; + } + + /** + * 转换为Long数组
+ * + * @param split 分隔符 + * @param str 被转换的值 + * @return 结果 + */ + public static Long[] toLongArray(String split, String str) + { + if (StringUtils.isEmpty(str)) + { + return new Long[] {}; + } + String[] arr = str.split(split); + final Long[] longs = new Long[arr.length]; + for (int i = 0; i < arr.length; i++) + { + final Long v = toLong(arr[i], null); + longs[i] = v; + } + return longs; + } + + /** + * 转换为String数组
+ * + * @param str 被转换的值 + * @return 结果 + */ + public static String[] toStrArray(String str) + { + return toStrArray(",", str); + } + + /** + * 转换为String数组
+ * + * @param split 分隔符 + * @param split 被转换的值 + * @return 结果 + */ + public static String[] toStrArray(String split, String str) + { + return str.split(split); + } + + /** + * 转换为long
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Long toLong(Object value, Long defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Long) + { + return (Long) value; + } + if (value instanceof Number) + { + return ((Number) value).longValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + // 支持科学计数法 + return new BigDecimal(valueStr.trim()).longValue(); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为long
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Long toLong(Object value) + { + return toLong(value, null); + } + + /** + * 转换为double
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Double toDouble(Object value, Double defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Double) + { + return (Double) value; + } + if (value instanceof Number) + { + return ((Number) value).doubleValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + // 支持科学计数法 + return new BigDecimal(valueStr.trim()).doubleValue(); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为double
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Double toDouble(Object value) + { + return toDouble(value, null); + } + + /** + * 转换为Float
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Float toFloat(Object value, Float defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Float) + { + return (Float) value; + } + if (value instanceof Number) + { + return ((Number) value).floatValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Float.parseFloat(valueStr.trim()); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为Float
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Float toFloat(Object value) + { + return toFloat(value, null); + } + + /** + * 转换为boolean
+ * String支持的值为:true、false、yes、ok、no,1,0 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static Boolean toBool(Object value, Boolean defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof Boolean) + { + return (Boolean) value; + } + String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + valueStr = valueStr.trim().toLowerCase(); + switch (valueStr) + { + case "true": + case "yes": + case "ok": + case "1": + return true; + case "false": + case "no": + case "0": + return false; + default: + return defaultValue; + } + } + + /** + * 转换为boolean
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static Boolean toBool(Object value) + { + return toBool(value, null); + } + + /** + * 转换为Enum对象
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * + * @param clazz Enum的Class + * @param value 值 + * @param defaultValue 默认值 + * @return Enum + */ + public static > E toEnum(Class clazz, Object value, E defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (clazz.isAssignableFrom(value.getClass())) + { + @SuppressWarnings("unchecked") + E myE = (E) value; + return myE; + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return Enum.valueOf(clazz, valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为Enum对象
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * + * @param clazz Enum的Class + * @param value 值 + * @return Enum + */ + public static > E toEnum(Class clazz, Object value) + { + return toEnum(clazz, value, null); + } + + /** + * 转换为BigInteger
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static BigInteger toBigInteger(Object value, BigInteger defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof BigInteger) + { + return (BigInteger) value; + } + if (value instanceof Long) + { + return BigInteger.valueOf((Long) value); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return new BigInteger(valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为BigInteger
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static BigInteger toBigInteger(Object value) + { + return toBigInteger(value, null); + } + + /** + * 转换为BigDecimal
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * @return 结果 + */ + public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue) + { + if (value == null) + { + return defaultValue; + } + if (value instanceof BigDecimal) + { + return (BigDecimal) value; + } + if (value instanceof Long) + { + return new BigDecimal((Long) value); + } + if (value instanceof Double) + { + return BigDecimal.valueOf((Double) value); + } + if (value instanceof Integer) + { + return new BigDecimal((Integer) value); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) + { + return defaultValue; + } + try + { + return new BigDecimal(valueStr); + } + catch (Exception e) + { + return defaultValue; + } + } + + /** + * 转换为BigDecimal
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @return 结果 + */ + public static BigDecimal toBigDecimal(Object value) + { + return toBigDecimal(value, null); + } + + /** + * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 + * + * @param obj 对象 + * @return 字符串 + */ + public static String utf8Str(Object obj) + { + return str(obj, CharsetKit.CHARSET_UTF_8); + } + + /** + * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 + * + * @param obj 对象 + * @param charsetName 字符集 + * @return 字符串 + */ + public static String str(Object obj, String charsetName) + { + return str(obj, Charset.forName(charsetName)); + } + + /** + * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 + * + * @param obj 对象 + * @param charset 字符集 + * @return 字符串 + */ + public static String str(Object obj, Charset charset) + { + if (null == obj) + { + return null; + } + + if (obj instanceof String) + { + return (String) obj; + } + else if (obj instanceof byte[]) + { + return str((byte[]) obj, charset); + } + else if (obj instanceof Byte[]) + { + byte[] bytes = ArrayUtils.toPrimitive((Byte[]) obj); + return str(bytes, charset); + } + else if (obj instanceof ByteBuffer) + { + return str((ByteBuffer) obj, charset); + } + return obj.toString(); + } + + /** + * 将byte数组转为字符串 + * + * @param bytes byte数组 + * @param charset 字符集 + * @return 字符串 + */ + public static String str(byte[] bytes, String charset) + { + return str(bytes, StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset)); + } + + /** + * 解码字节码 + * + * @param data 字符串 + * @param charset 字符集,如果此字段为空,则解码的结果取决于平台 + * @return 解码后的字符串 + */ + public static String str(byte[] data, Charset charset) + { + if (data == null) + { + return null; + } + + if (null == charset) + { + return new String(data); + } + return new String(data, charset); + } + + /** + * 将编码的byteBuffer数据转换为字符串 + * + * @param data 数据 + * @param charset 字符集,如果为空使用当前系统字符集 + * @return 字符串 + */ + public static String str(ByteBuffer data, String charset) + { + if (data == null) + { + return null; + } + + return str(data, Charset.forName(charset)); + } + + /** + * 将编码的byteBuffer数据转换为字符串 + * + * @param data 数据 + * @param charset 字符集,如果为空使用当前系统字符集 + * @return 字符串 + */ + public static String str(ByteBuffer data, Charset charset) + { + if (null == charset) + { + charset = Charset.defaultCharset(); + } + return charset.decode(data).toString(); + } + + // ----------------------------------------------------------------------- 全角半角转换 + /** + * 半角转全角 + * + * @param input String. + * @return 全角字符串. + */ + public static String toSBC(String input) + { + return toSBC(input, null); + } + + /** + * 半角转全角 + * + * @param input String + * @param notConvertSet 不替换的字符集合 + * @return 全角字符串. + */ + public static String toSBC(String input, Set notConvertSet) + { + char[] c = input.toCharArray(); + for (int i = 0; i < c.length; i++) + { + if (null != notConvertSet && notConvertSet.contains(c[i])) + { + // 跳过不替换的字符 + continue; + } + + if (c[i] == ' ') + { + c[i] = '\u3000'; + } + else if (c[i] < '\177') + { + c[i] = (char) (c[i] + 65248); + + } + } + return new String(c); + } + + /** + * 全角转半角 + * + * @param input String. + * @return 半角字符串 + */ + public static String toDBC(String input) + { + return toDBC(input, null); + } + + /** + * 替换全角为半角 + * + * @param text 文本 + * @param notConvertSet 不替换的字符集合 + * @return 替换后的字符 + */ + public static String toDBC(String text, Set notConvertSet) + { + char[] c = text.toCharArray(); + for (int i = 0; i < c.length; i++) + { + if (null != notConvertSet && notConvertSet.contains(c[i])) + { + // 跳过不替换的字符 + continue; + } + + if (c[i] == '\u3000') + { + c[i] = ' '; + } + else if (c[i] > '\uFF00' && c[i] < '\uFF5F') + { + c[i] = (char) (c[i] - 65248); + } + } + String returnString = new String(c); + + return returnString; + } + + /** + * 数字金额大写转换 先写个完整的然后将如零拾替换成零 + * + * @param n 数字 + * @return 中文大写数字 + */ + public static String digitUppercase(double n) + { + String[] fraction = { "角", "分" }; + String[] digit = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" }; + String[][] unit = { { "元", "万", "亿" }, { "", "拾", "佰", "仟" } }; + + String head = n < 0 ? "负" : ""; + n = Math.abs(n); + + String s = ""; + for (int i = 0; i < fraction.length; i++) + { + s += (digit[(int) (Math.floor(n * 10 * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", ""); + } + if (s.length() < 1) + { + s = "整"; + } + int integerPart = (int) Math.floor(n); + + for (int i = 0; i < unit[0].length && integerPart > 0; i++) + { + String p = ""; + for (int j = 0; j < unit[1].length && n > 0; j++) + { + p = digit[integerPart % 10] + unit[1][j] + p; + integerPart = integerPart / 10; + } + s = p.replaceAll("(零.)*零$", "").replaceAll("^$", "零") + unit[0][i] + s; + } + return head + s.replaceAll("(零.)*零元", "元").replaceFirst("(零.)+", "").replaceAll("(零.)+", "零").replaceAll("^整$", "零元整"); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java new file mode 100644 index 0000000..f0e83be --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java @@ -0,0 +1,92 @@ +package com.ruoyi.common.core.text; + +import com.ruoyi.common.utils.StringUtils; + +/** + * 字符串格式化 + * + * @author #author# + */ +public class StrFormatter +{ + public static final String EMPTY_JSON = "{}"; + public static final char C_BACKSLASH = '\\'; + public static final char C_DELIM_START = '{'; + public static final char C_DELIM_END = '}'; + + /** + * 格式化字符串
+ * 此方法只是简单将占位符 {} 按照顺序替换为参数
+ * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可
+ * 例:
+ * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b
+ * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a
+ * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b
+ * + * @param strPattern 字符串模板 + * @param argArray 参数列表 + * @return 结果 + */ + public static String format(final String strPattern, final Object... argArray) + { + if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray)) + { + return strPattern; + } + final int strPatternLength = strPattern.length(); + + // 初始化定义好的长度以获得更好的性能 + StringBuilder sbuf = new StringBuilder(strPatternLength + 50); + + int handledPosition = 0; + int delimIndex;// 占位符所在位置 + for (int argIndex = 0; argIndex < argArray.length; argIndex++) + { + delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition); + if (delimIndex == -1) + { + if (handledPosition == 0) + { + return strPattern; + } + else + { // 字符串模板剩余部分不再包含占位符,加入剩余部分后返回结果 + sbuf.append(strPattern, handledPosition, strPatternLength); + return sbuf.toString(); + } + } + else + { + if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH) + { + if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH) + { + // 转义符之前还有一个转义符,占位符依旧有效 + sbuf.append(strPattern, handledPosition, delimIndex - 1); + sbuf.append(Convert.utf8Str(argArray[argIndex])); + handledPosition = delimIndex + 2; + } + else + { + // 占位符被转义 + argIndex--; + sbuf.append(strPattern, handledPosition, delimIndex - 1); + sbuf.append(C_DELIM_START); + handledPosition = delimIndex + 1; + } + } + else + { + // 正常占位符 + sbuf.append(strPattern, handledPosition, delimIndex); + sbuf.append(Convert.utf8Str(argArray[argIndex])); + handledPosition = delimIndex + 2; + } + } + } + // 加入最后一个占位符后所有的字符 + sbuf.append(strPattern, handledPosition, strPattern.length()); + + return sbuf.toString(); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java new file mode 100644 index 0000000..3cdeb10 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java @@ -0,0 +1,20 @@ +package com.ruoyi.common.enums; + +/** + * 操作状态 + * + * @author #author# + * + */ +public enum BusinessStatus +{ + /** + * 成功 + */ + SUCCESS, + + /** + * 失败 + */ + FAIL, +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java new file mode 100644 index 0000000..00a017d --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java @@ -0,0 +1,59 @@ +package com.ruoyi.common.enums; + +/** + * 业务操作类型 + * + * @author #author# + */ +public enum BusinessType +{ + /** + * 其它 + */ + OTHER, + + /** + * 新增 + */ + INSERT, + + /** + * 修改 + */ + UPDATE, + + /** + * 删除 + */ + DELETE, + + /** + * 授权 + */ + GRANT, + + /** + * 导出 + */ + EXPORT, + + /** + * 导入 + */ + IMPORT, + + /** + * 强退 + */ + FORCE, + + /** + * 生成代码 + */ + GENCODE, + + /** + * 清空数据 + */ + CLEAN, +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java new file mode 100644 index 0000000..afc2106 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java @@ -0,0 +1,19 @@ +package com.ruoyi.common.enums; + +/** + * 数据源 + * + * @author #author# + */ +public enum DataSourceType +{ + /** + * 主库 + */ + MASTER, + + /** + * 从库 + */ + SLAVE +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java new file mode 100644 index 0000000..6daa2dd --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java @@ -0,0 +1,36 @@ +package com.ruoyi.common.enums; + +import java.util.HashMap; +import java.util.Map; +import org.springframework.lang.Nullable; + +/** + * 请求方式 + * + * @author #author# + */ +public enum HttpMethod +{ + GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE; + + private static final Map mappings = new HashMap<>(16); + + static + { + for (HttpMethod httpMethod : values()) + { + mappings.put(httpMethod.name(), httpMethod); + } + } + + @Nullable + public static HttpMethod resolve(@Nullable String method) + { + return (method != null ? mappings.get(method) : null); + } + + public boolean matches(String method) + { + return (this == resolve(method)); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/LimitType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/LimitType.java new file mode 100644 index 0000000..cde04fd --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/LimitType.java @@ -0,0 +1,20 @@ +package com.ruoyi.common.enums; + +/** + * 限流类型 + * + * @author #author# + */ + +public enum LimitType +{ + /** + * 默认策略全局限流 + */ + DEFAULT, + + /** + * 根据请求者IP进行限流 + */ + IP +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java new file mode 100644 index 0000000..588e03d --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java @@ -0,0 +1,24 @@ +package com.ruoyi.common.enums; + +/** + * 操作人类别 + * + * @author #author# + */ +public enum OperatorType +{ + /** + * 其它 + */ + OTHER, + + /** + * 后台用户 + */ + MANAGE, + + /** + * 手机端用户 + */ + MOBILE +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/UserStatus.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/UserStatus.java new file mode 100644 index 0000000..ad15be2 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/UserStatus.java @@ -0,0 +1,30 @@ +package com.ruoyi.common.enums; + +/** + * 用户状态 + * + * @author #author# + */ +public enum UserStatus +{ + OK("0", "正常"), DISABLE("1", "停用"), DELETED("2", "删除"); + + private final String code; + private final String info; + + UserStatus(String code, String info) + { + this.code = code; + this.info = info; + } + + public String getCode() + { + return code; + } + + public String getInfo() + { + return info; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java new file mode 100644 index 0000000..25842fd --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java @@ -0,0 +1,15 @@ +package com.ruoyi.common.exception; + +/** + * 演示模式异常 + * + * @author #author# + */ +public class DemoModeException extends RuntimeException +{ + private static final long serialVersionUID = 1L; + + public DemoModeException() + { + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java new file mode 100644 index 0000000..76f0982 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java @@ -0,0 +1,58 @@ +package com.ruoyi.common.exception; + +/** + * 全局异常 + * + * @author #author# + */ +public class GlobalException extends RuntimeException +{ + private static final long serialVersionUID = 1L; + + /** + * 错误提示 + */ + private String message; + + /** + * 错误明细,内部调试错误 + * + * 和 {@link CommonResult#getDetailMessage()} 一致的设计 + */ + private String detailMessage; + + /** + * 空构造方法,避免反序列化问题 + */ + public GlobalException() + { + } + + public GlobalException(String message) + { + this.message = message; + } + + public String getDetailMessage() + { + return detailMessage; + } + + public GlobalException setDetailMessage(String detailMessage) + { + this.detailMessage = detailMessage; + return this; + } + + @Override + public String getMessage() + { + return message; + } + + public GlobalException setMessage(String message) + { + this.message = message; + return this; + } +} \ No newline at end of file diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java new file mode 100644 index 0000000..4ac42e8 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java @@ -0,0 +1,74 @@ +package com.ruoyi.common.exception; + +/** + * 业务异常 + * + * @author #author# + */ +public final class ServiceException extends RuntimeException +{ + private static final long serialVersionUID = 1L; + + /** + * 错误码 + */ + private Integer code; + + /** + * 错误提示 + */ + private String message; + + /** + * 错误明细,内部调试错误 + * + * 和 {@link CommonResult#getDetailMessage()} 一致的设计 + */ + private String detailMessage; + + /** + * 空构造方法,避免反序列化问题 + */ + public ServiceException() + { + } + + public ServiceException(String message) + { + this.message = message; + } + + public ServiceException(String message, Integer code) + { + this.message = message; + this.code = code; + } + + public String getDetailMessage() + { + return detailMessage; + } + + @Override + public String getMessage() + { + return message; + } + + public Integer getCode() + { + return code; + } + + public ServiceException setMessage(String message) + { + this.message = message; + return this; + } + + public ServiceException setDetailMessage(String detailMessage) + { + this.detailMessage = detailMessage; + return this; + } +} \ No newline at end of file diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/UtilException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/UtilException.java new file mode 100644 index 0000000..5ca412d --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/UtilException.java @@ -0,0 +1,26 @@ +package com.ruoyi.common.exception; + +/** + * 工具类异常 + * + * @author #author# + */ +public class UtilException extends RuntimeException +{ + private static final long serialVersionUID = 8247610319171014183L; + + public UtilException(Throwable e) + { + super(e.getMessage(), e); + } + + public UtilException(String message) + { + super(message); + } + + public UtilException(String message, Throwable throwable) + { + super(message, throwable); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java new file mode 100644 index 0000000..3f8220a --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java @@ -0,0 +1,97 @@ +package com.ruoyi.common.exception.base; + +import com.ruoyi.common.utils.MessageUtils; +import com.ruoyi.common.utils.StringUtils; + +/** + * 基础异常 + * + * @author #author# + */ +public class BaseException extends RuntimeException +{ + private static final long serialVersionUID = 1L; + + /** + * 所属模块 + */ + private String module; + + /** + * 错误码 + */ + private String code; + + /** + * 错误码对应的参数 + */ + private Object[] args; + + /** + * 错误消息 + */ + private String defaultMessage; + + public BaseException(String module, String code, Object[] args, String defaultMessage) + { + this.module = module; + this.code = code; + this.args = args; + this.defaultMessage = defaultMessage; + } + + public BaseException(String module, String code, Object[] args) + { + this(module, code, args, null); + } + + public BaseException(String module, String defaultMessage) + { + this(module, null, null, defaultMessage); + } + + public BaseException(String code, Object[] args) + { + this(null, code, args, null); + } + + public BaseException(String defaultMessage) + { + this(null, null, null, defaultMessage); + } + + @Override + public String getMessage() + { + String message = null; + if (!StringUtils.isEmpty(code)) + { + message = MessageUtils.message(code, args); + } + if (message == null) + { + message = defaultMessage; + } + return message; + } + + public String getModule() + { + return module; + } + + public String getCode() + { + return code; + } + + public Object[] getArgs() + { + return args; + } + + public String getDefaultMessage() + { + return defaultMessage; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileException.java new file mode 100644 index 0000000..c682535 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileException.java @@ -0,0 +1,19 @@ +package com.ruoyi.common.exception.file; + +import com.ruoyi.common.exception.base.BaseException; + +/** + * 文件信息异常类 + * + * @author #author# + */ +public class FileException extends BaseException +{ + private static final long serialVersionUID = 1L; + + public FileException(String code, Object[] args) + { + super("file", code, args, null); + } + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java new file mode 100644 index 0000000..b0dcf3a --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java @@ -0,0 +1,16 @@ +package com.ruoyi.common.exception.file; + +/** + * 文件名称超长限制异常类 + * + * @author #author# + */ +public class FileNameLengthLimitExceededException extends FileException +{ + private static final long serialVersionUID = 1L; + + public FileNameLengthLimitExceededException(int defaultFileNameLength) + { + super("upload.filename.exceed.length", new Object[] { defaultFileNameLength }); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java new file mode 100644 index 0000000..69f2e2e --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java @@ -0,0 +1,16 @@ +package com.ruoyi.common.exception.file; + +/** + * 文件名大小限制异常类 + * + * @author #author# + */ +public class FileSizeLimitExceededException extends FileException +{ + private static final long serialVersionUID = 1L; + + public FileSizeLimitExceededException(long defaultMaxSize) + { + super("upload.exceed.maxSize", new Object[] { defaultMaxSize }); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java new file mode 100644 index 0000000..7047bb6 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java @@ -0,0 +1,81 @@ +package com.ruoyi.common.exception.file; + +import java.util.Arrays; +import org.apache.commons.fileupload.FileUploadException; + +/** + * 文件上传 误异常类 + * + * @author #author# + */ +public class InvalidExtensionException extends FileUploadException +{ + private static final long serialVersionUID = 1L; + + private String[] allowedExtension; + private String extension; + private String filename; + + public InvalidExtensionException(String[] allowedExtension, String extension, String filename) + { + super("文件[" + filename + "]后缀[" + extension + "]不正确,请上传" + Arrays.toString(allowedExtension) + "格式"); + this.allowedExtension = allowedExtension; + this.extension = extension; + this.filename = filename; + } + + public String[] getAllowedExtension() + { + return allowedExtension; + } + + public String getExtension() + { + return extension; + } + + public String getFilename() + { + return filename; + } + + public static class InvalidImageExtensionException extends InvalidExtensionException + { + private static final long serialVersionUID = 1L; + + public InvalidImageExtensionException(String[] allowedExtension, String extension, String filename) + { + super(allowedExtension, extension, filename); + } + } + + public static class InvalidFlashExtensionException extends InvalidExtensionException + { + private static final long serialVersionUID = 1L; + + public InvalidFlashExtensionException(String[] allowedExtension, String extension, String filename) + { + super(allowedExtension, extension, filename); + } + } + + public static class InvalidMediaExtensionException extends InvalidExtensionException + { + private static final long serialVersionUID = 1L; + + public InvalidMediaExtensionException(String[] allowedExtension, String extension, String filename) + { + super(allowedExtension, extension, filename); + } + } + + public static class InvalidVideoExtensionException extends InvalidExtensionException + { + private static final long serialVersionUID = 1L; + + public InvalidVideoExtensionException(String[] allowedExtension, String extension, String filename) + { + super(allowedExtension, extension, filename); + } + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java new file mode 100644 index 0000000..defd070 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java @@ -0,0 +1,34 @@ +package com.ruoyi.common.exception.job; + +/** + * 计划策略异常 + * + * @author #author# + */ +public class TaskException extends Exception +{ + private static final long serialVersionUID = 1L; + + private Code code; + + public TaskException(String msg, Code code) + { + this(msg, code, null); + } + + public TaskException(String msg, Code code, Exception nestedEx) + { + super(msg, nestedEx); + this.code = code; + } + + public Code getCode() + { + return code; + } + + public enum Code + { + TASK_EXISTS, NO_TASK_EXISTS, TASK_ALREADY_STARTED, UNKNOWN, CONFIG_ERROR, TASK_NODE_NOT_AVAILABLE + } +} \ No newline at end of file diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java new file mode 100644 index 0000000..a2cc1e5 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java @@ -0,0 +1,16 @@ +package com.ruoyi.common.exception.user; + +/** + * 验证码错误异常类 + * + * @author #author# + */ +public class CaptchaException extends UserException +{ + private static final long serialVersionUID = 1L; + + public CaptchaException() + { + super("user.jcaptcha.error", null); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java new file mode 100644 index 0000000..9c32525 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java @@ -0,0 +1,16 @@ +package com.ruoyi.common.exception.user; + +/** + * 验证码失效异常类 + * + * @author #author# + */ +public class CaptchaExpireException extends UserException +{ + private static final long serialVersionUID = 1L; + + public CaptchaExpireException() + { + super("user.jcaptcha.expire", null); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java new file mode 100644 index 0000000..011d087 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java @@ -0,0 +1,18 @@ +package com.ruoyi.common.exception.user; + +import com.ruoyi.common.exception.base.BaseException; + +/** + * 用户信息异常类 + * + * @author #author# + */ +public class UserException extends BaseException +{ + private static final long serialVersionUID = 1L; + + public UserException(String code, Object[] args) + { + super("user", code, args, null); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java new file mode 100644 index 0000000..061c019 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java @@ -0,0 +1,16 @@ +package com.ruoyi.common.exception.user; + +/** + * 用户密码不正确或不符合规范异常类 + * + * @author #author# + */ +public class UserPasswordNotMatchException extends UserException +{ + private static final long serialVersionUID = 1L; + + public UserPasswordNotMatchException() + { + super("user.password.not.match", null); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java new file mode 100644 index 0000000..8bd1d6f --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java @@ -0,0 +1,16 @@ +package com.ruoyi.common.exception.user; + +/** + * 用户错误最大次数异常类 + * + * @author #author# + */ +public class UserPasswordRetryLimitExceedException extends UserException +{ + private static final long serialVersionUID = 1L; + + public UserPasswordRetryLimitExceedException(int retryLimitCount, int lockTime) + { + super("user.password.retry.limit.exceed", new Object[] { retryLimitCount, lockTime }); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/filter/PropertyPreExcludeFilter.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/PropertyPreExcludeFilter.java new file mode 100644 index 0000000..b01e78a --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/filter/PropertyPreExcludeFilter.java @@ -0,0 +1,24 @@ +package com.ruoyi.common.filter; + +import com.alibaba.fastjson2.filter.SimplePropertyPreFilter; + +/** + * 排除JSON敏感属性 + * + * @author #author# + */ +public class PropertyPreExcludeFilter extends SimplePropertyPreFilter +{ + public PropertyPreExcludeFilter() + { + } + + public PropertyPreExcludeFilter addExcludes(String... filters) + { + for (int i = 0; i < filters.length; i++) + { + this.getExcludes().add(filters[i]); + } + return this; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java new file mode 100644 index 0000000..e5bdab0 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java @@ -0,0 +1,52 @@ +package com.ruoyi.common.filter; + +import java.io.IOException; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import org.springframework.http.MediaType; +import com.ruoyi.common.utils.StringUtils; + +/** + * Repeatable 过滤器 + * + * @author #author# + */ +public class RepeatableFilter implements Filter +{ + @Override + public void init(FilterConfig filterConfig) throws ServletException + { + + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException + { + ServletRequest requestWrapper = null; + if (request instanceof HttpServletRequest + && StringUtils.startsWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE)) + { + requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response); + } + if (null == requestWrapper) + { + chain.doFilter(request, response); + } + else + { + chain.doFilter(requestWrapper, response); + } + } + + @Override + public void destroy() + { + + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java new file mode 100644 index 0000000..9f7bdb2 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java @@ -0,0 +1,76 @@ +package com.ruoyi.common.filter; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import com.ruoyi.common.utils.http.HttpHelper; +import com.ruoyi.common.constant.Constants; + +/** + * 构建可重复读取inputStream的request + * + * @author #author# + */ +public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper +{ + private final byte[] body; + + public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException + { + super(request); + request.setCharacterEncoding(Constants.UTF8); + response.setCharacterEncoding(Constants.UTF8); + + body = HttpHelper.getBodyString(request).getBytes(Constants.UTF8); + } + + @Override + public BufferedReader getReader() throws IOException + { + return new BufferedReader(new InputStreamReader(getInputStream())); + } + + @Override + public ServletInputStream getInputStream() throws IOException + { + final ByteArrayInputStream bais = new ByteArrayInputStream(body); + return new ServletInputStream() + { + @Override + public int read() throws IOException + { + return bais.read(); + } + + @Override + public int available() throws IOException + { + return body.length; + } + + @Override + public boolean isFinished() + { + return false; + } + + @Override + public boolean isReady() + { + return false; + } + + @Override + public void setReadListener(ReadListener readListener) + { + + } + }; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java new file mode 100644 index 0000000..e3c587c --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java @@ -0,0 +1,75 @@ +package com.ruoyi.common.filter; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.enums.HttpMethod; + +/** + * 防止XSS攻击的过滤器 + * + * @author #author# + */ +public class XssFilter implements Filter +{ + /** + * 排除链接 + */ + public List excludes = new ArrayList<>(); + + @Override + public void init(FilterConfig filterConfig) throws ServletException + { + String tempExcludes = filterConfig.getInitParameter("excludes"); + if (StringUtils.isNotEmpty(tempExcludes)) + { + String[] url = tempExcludes.split(","); + for (int i = 0; url != null && i < url.length; i++) + { + excludes.add(url[i]); + } + } + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException + { + HttpServletRequest req = (HttpServletRequest) request; + HttpServletResponse resp = (HttpServletResponse) response; + if (handleExcludeURL(req, resp)) + { + chain.doFilter(request, response); + return; + } + XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request); + chain.doFilter(xssRequest, response); + } + + private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response) + { + String url = request.getServletPath(); + String method = request.getMethod(); + // GET DELETE 不过滤 + if (method == null || HttpMethod.GET.matches(method) || HttpMethod.DELETE.matches(method)) + { + return true; + } + return StringUtils.matches(url, excludes); + } + + @Override + public void destroy() + { + + } +} \ No newline at end of file diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java new file mode 100644 index 0000000..ad183e7 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java @@ -0,0 +1,111 @@ +package com.ruoyi.common.filter; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import org.apache.commons.io.IOUtils; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.html.EscapeUtil; + +/** + * XSS过滤处理 + * + * @author #author# + */ +public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper +{ + /** + * @param request + */ + public XssHttpServletRequestWrapper(HttpServletRequest request) + { + super(request); + } + + @Override + public String[] getParameterValues(String name) + { + String[] values = super.getParameterValues(name); + if (values != null) + { + int length = values.length; + String[] escapesValues = new String[length]; + for (int i = 0; i < length; i++) + { + // 防xss攻击和过滤前后空格 + escapesValues[i] = EscapeUtil.clean(values[i]).trim(); + } + return escapesValues; + } + return super.getParameterValues(name); + } + + @Override + public ServletInputStream getInputStream() throws IOException + { + // 非json类型,直接返回 + if (!isJsonRequest()) + { + return super.getInputStream(); + } + + // 为空,直接返回 + String json = IOUtils.toString(super.getInputStream(), "utf-8"); + if (StringUtils.isEmpty(json)) + { + return super.getInputStream(); + } + + // xss过滤 + json = EscapeUtil.clean(json).trim(); + byte[] jsonBytes = json.getBytes("utf-8"); + final ByteArrayInputStream bis = new ByteArrayInputStream(jsonBytes); + return new ServletInputStream() + { + @Override + public boolean isFinished() + { + return true; + } + + @Override + public boolean isReady() + { + return true; + } + + @Override + public int available() throws IOException + { + return jsonBytes.length; + } + + @Override + public void setReadListener(ReadListener readListener) + { + } + + @Override + public int read() throws IOException + { + return bis.read(); + } + }; + } + + /** + * 是否是Json请求 + * + * @param request + */ + public boolean isJsonRequest() + { + String header = super.getHeader(HttpHeaders.CONTENT_TYPE); + return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE); + } +} \ No newline at end of file diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/handler/MyMetaObjectHandler.java b/ruoyi-common/src/main/java/com/ruoyi/common/handler/MyMetaObjectHandler.java new file mode 100644 index 0000000..1d0368c --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/handler/MyMetaObjectHandler.java @@ -0,0 +1,52 @@ +package com.ruoyi.common.handler; + +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; + +import lombok.extern.slf4j.Slf4j; +import org.apache.ibatis.reflection.MetaObject; +import org.springframework.stereotype.Component; + +import java.util.Date; + +/** + * mybatisplus 填充器 + */ +@Slf4j +@Component +public class MyMetaObjectHandler implements MetaObjectHandler { + + @Override + public void insertFill(MetaObject metaObject) { + log.info("start insert fill ...."); + Object createBy = metaObject.getValue("createBy"); +// String uuid = UUID.randomUUID().toString(); +// this.strictInsertFill(metaObject, "id", String.class, uuid); // 起始版本 3.3.0(推荐使用) + if (StringUtils.isNull(createBy) || createBy.equals("")) { + this.strictInsertFill(metaObject, "createBy", String.class, SecurityUtils.getUsername()); // 起始版本 3.3.0(推荐使用) + } + this.strictInsertFill(metaObject, "createTime", Date.class, DateUtils.getNowDate()); // 起始版本 3.3.0(推荐使用) + this.strictInsertFill(metaObject, "deleted", Long.class, 0L); // 起始版本 3.3.0(推荐使用) + + // 或者 +// this.strictInsertFill(metaObject, "createTime", () -> LocalDateTime.now(), LocalDateTime.class); // 起始版本 3.3.3(推荐) + // 或者 +// this.fillStrategy(metaObject, "createTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug) + } + + @Override + public void updateFill(MetaObject metaObject) { + log.info("start update fill ...."); + Object updateBy = metaObject.getValue("updateBy"); + if (StringUtils.isNull(updateBy) || updateBy.equals("")) { + this.strictInsertFill(metaObject, "updateBy", String.class, SecurityUtils.getUsername()); + } + this.strictUpdateFill(metaObject, "updateTime", Date.class, DateUtils.getNowDate()); // 起始版本 3.3.0(推荐) + // 或者 +// this.strictUpdateFill(metaObject, "updateTime", () -> LocalDateTime.now(), LocalDateTime.class); // 起始版本 3.3.3(推荐) + // 或者 +// this.fillStrategy(metaObject, "updateTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug) + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java new file mode 100644 index 0000000..2d8fe39 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java @@ -0,0 +1,114 @@ +package com.ruoyi.common.utils; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +/** + * 精确的浮点数运算 + * + * @author #author# + */ +public class Arith +{ + + /** 默认除法运算精度 */ + private static final int DEF_DIV_SCALE = 10; + + /** 这个类不能实例化 */ + private Arith() + { + } + + /** + * 提供精确的加法运算。 + * @param v1 被加数 + * @param v2 加数 + * @return 两个参数的和 + */ + public static double add(double v1, double v2) + { + BigDecimal b1 = new BigDecimal(Double.toString(v1)); + BigDecimal b2 = new BigDecimal(Double.toString(v2)); + return b1.add(b2).doubleValue(); + } + + /** + * 提供精确的减法运算。 + * @param v1 被减数 + * @param v2 减数 + * @return 两个参数的差 + */ + public static double sub(double v1, double v2) + { + BigDecimal b1 = new BigDecimal(Double.toString(v1)); + BigDecimal b2 = new BigDecimal(Double.toString(v2)); + return b1.subtract(b2).doubleValue(); + } + + /** + * 提供精确的乘法运算。 + * @param v1 被乘数 + * @param v2 乘数 + * @return 两个参数的积 + */ + public static double mul(double v1, double v2) + { + BigDecimal b1 = new BigDecimal(Double.toString(v1)); + BigDecimal b2 = new BigDecimal(Double.toString(v2)); + return b1.multiply(b2).doubleValue(); + } + + /** + * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 + * 小数点以后10位,以后的数字四舍五入。 + * @param v1 被除数 + * @param v2 除数 + * @return 两个参数的商 + */ + public static double div(double v1, double v2) + { + return div(v1, v2, DEF_DIV_SCALE); + } + + /** + * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 + * 定精度,以后的数字四舍五入。 + * @param v1 被除数 + * @param v2 除数 + * @param scale 表示表示需要精确到小数点以后几位。 + * @return 两个参数的商 + */ + public static double div(double v1, double v2, int scale) + { + if (scale < 0) + { + throw new IllegalArgumentException( + "The scale must be a positive integer or zero"); + } + BigDecimal b1 = new BigDecimal(Double.toString(v1)); + BigDecimal b2 = new BigDecimal(Double.toString(v2)); + if (b1.compareTo(BigDecimal.ZERO) == 0) + { + return BigDecimal.ZERO.doubleValue(); + } + return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue(); + } + + /** + * 提供精确的小数位四舍五入处理。 + * @param v 需要四舍五入的数字 + * @param scale 小数点后保留几位 + * @return 四舍五入后的结果 + */ + public static double round(double v, int scale) + { + if (scale < 0) + { + throw new IllegalArgumentException( + "The scale must be a positive integer or zero"); + } + BigDecimal b = new BigDecimal(Double.toString(v)); + BigDecimal one = BigDecimal.ONE; + return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue(); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java new file mode 100644 index 0000000..0b85e7d --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java @@ -0,0 +1,187 @@ +package com.ruoyi.common.utils; + +import java.lang.management.ManagementFactory; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.Date; +import org.apache.commons.lang3.time.DateFormatUtils; + +/** + * 时间工具类 + * + * @author #author# + */ +public class DateUtils extends org.apache.commons.lang3.time.DateUtils +{ + public static String YYYY = "yyyy"; + + public static String YYYY_MM = "yyyy-MM"; + + public static String YYYY_MM_DD = "yyyy-MM-dd"; + + public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss"; + + public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; + + private static String[] parsePatterns = { + "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", + "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM", + "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"}; + + /** + * 获取当前Date型日期 + * + * @return Date() 当前日期 + */ + public static Date getNowDate() + { + return new Date(); + } + + /** + * 获取当前日期, 默认格式为yyyy-MM-dd + * + * @return String + */ + public static String getDate() + { + return dateTimeNow(YYYY_MM_DD); + } + + public static final String getTime() + { + return dateTimeNow(YYYY_MM_DD_HH_MM_SS); + } + + public static final String dateTimeNow() + { + return dateTimeNow(YYYYMMDDHHMMSS); + } + + public static final String dateTimeNow(final String format) + { + return parseDateToStr(format, new Date()); + } + + public static final String dateTime(final Date date) + { + return parseDateToStr(YYYY_MM_DD, date); + } + + public static final String parseDateToStr(final String format, final Date date) + { + return new SimpleDateFormat(format).format(date); + } + + public static final Date dateTime(final String format, final String ts) + { + try + { + return new SimpleDateFormat(format).parse(ts); + } + catch (ParseException e) + { + throw new RuntimeException(e); + } + } + + /** + * 日期路径 即年/月/日 如2018/08/08 + */ + public static final String datePath() + { + Date now = new Date(); + return DateFormatUtils.format(now, "yyyy/MM/dd"); + } + + /** + * 日期路径 即年/月/日 如20180808 + */ + public static final String dateTime() + { + Date now = new Date(); + return DateFormatUtils.format(now, "yyyyMMdd"); + } + + /** + * 日期型字符串转化为日期 格式 + */ + public static Date parseDate(Object str) + { + if (str == null) + { + return null; + } + try + { + return parseDate(str.toString(), parsePatterns); + } + catch (ParseException e) + { + return null; + } + } + + /** + * 获取服务器启动时间 + */ + public static Date getServerStartDate() + { + long time = ManagementFactory.getRuntimeMXBean().getStartTime(); + return new Date(time); + } + + /** + * 计算相差天数 + */ + public static int differentDaysByMillisecond(Date date1, Date date2) + { + return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24))); + } + + /** + * 计算两个时间差 + */ + public static String getDatePoor(Date endDate, Date nowDate) + { + long nd = 1000 * 24 * 60 * 60; + long nh = 1000 * 60 * 60; + long nm = 1000 * 60; + // long ns = 1000; + // 获得两个时间的毫秒时间差异 + long diff = endDate.getTime() - nowDate.getTime(); + // 计算差多少天 + long day = diff / nd; + // 计算差多少小时 + long hour = diff % nd / nh; + // 计算差多少分钟 + long min = diff % nd % nh / nm; + // 计算差多少秒//输出结果 + // long sec = diff % nd % nh % nm / ns; + return day + "天" + hour + "小时" + min + "分钟"; + } + + /** + * 增加 LocalDateTime ==> Date + */ + public static Date toDate(LocalDateTime temporalAccessor) + { + ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault()); + return Date.from(zdt.toInstant()); + } + + /** + * 增加 LocalDate ==> Date + */ + public static Date toDate(LocalDate temporalAccessor) + { + LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0)); + ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault()); + return Date.from(zdt.toInstant()); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java new file mode 100644 index 0000000..87e6d5d --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java @@ -0,0 +1,186 @@ +package com.ruoyi.common.utils; + +import java.util.Collection; +import java.util.List; +import com.alibaba.fastjson2.JSONArray; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.core.domain.entity.SysDictData; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.utils.spring.SpringUtils; + +/** + * 字典工具类 + * + * @author #author# + */ +public class DictUtils +{ + /** + * 分隔符 + */ + public static final String SEPARATOR = ","; + + /** + * 设置字典缓存 + * + * @param key 参数键 + * @param dictDatas 字典数据列表 + */ + public static void setDictCache(String key, List dictDatas) + { + SpringUtils.getBean(RedisCache.class).setCacheObject(getCacheKey(key), dictDatas); + } + + /** + * 获取字典缓存 + * + * @param key 参数键 + * @return dictDatas 字典数据列表 + */ + public static List getDictCache(String key) + { + JSONArray arrayCache = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key)); + if (StringUtils.isNotNull(arrayCache)) + { + return arrayCache.toList(SysDictData.class); + } + return null; + } + + /** + * 根据字典类型和字典值获取字典标签 + * + * @param dictType 字典类型 + * @param dictValue 字典值 + * @return 字典标签 + */ + public static String getDictLabel(String dictType, String dictValue) + { + return getDictLabel(dictType, dictValue, SEPARATOR); + } + + /** + * 根据字典类型和字典标签获取字典值 + * + * @param dictType 字典类型 + * @param dictLabel 字典标签 + * @return 字典值 + */ + public static String getDictValue(String dictType, String dictLabel) + { + return getDictValue(dictType, dictLabel, SEPARATOR); + } + + /** + * 根据字典类型和字典值获取字典标签 + * + * @param dictType 字典类型 + * @param dictValue 字典值 + * @param separator 分隔符 + * @return 字典标签 + */ + public static String getDictLabel(String dictType, String dictValue, String separator) + { + StringBuilder propertyString = new StringBuilder(); + List datas = getDictCache(dictType); + + if (StringUtils.isNotNull(datas)) + { + if (StringUtils.containsAny(separator, dictValue)) + { + for (SysDictData dict : datas) + { + for (String value : dictValue.split(separator)) + { + if (value.equals(dict.getDictValue())) + { + propertyString.append(dict.getDictLabel()).append(separator); + break; + } + } + } + } + else + { + for (SysDictData dict : datas) + { + if (dictValue.equals(dict.getDictValue())) + { + return dict.getDictLabel(); + } + } + } + } + return StringUtils.stripEnd(propertyString.toString(), separator); + } + + /** + * 根据字典类型和字典标签获取字典值 + * + * @param dictType 字典类型 + * @param dictLabel 字典标签 + * @param separator 分隔符 + * @return 字典值 + */ + public static String getDictValue(String dictType, String dictLabel, String separator) + { + StringBuilder propertyString = new StringBuilder(); + List datas = getDictCache(dictType); + + if (StringUtils.containsAny(separator, dictLabel) && StringUtils.isNotEmpty(datas)) + { + for (SysDictData dict : datas) + { + for (String label : dictLabel.split(separator)) + { + if (label.equals(dict.getDictLabel())) + { + propertyString.append(dict.getDictValue()).append(separator); + break; + } + } + } + } + else + { + for (SysDictData dict : datas) + { + if (dictLabel.equals(dict.getDictLabel())) + { + return dict.getDictValue(); + } + } + } + return StringUtils.stripEnd(propertyString.toString(), separator); + } + + /** + * 删除指定字典缓存 + * + * @param key 字典键 + */ + public static void removeDictCache(String key) + { + SpringUtils.getBean(RedisCache.class).deleteObject(getCacheKey(key)); + } + + /** + * 清空字典缓存 + */ + public static void clearDictCache() + { + Collection keys = SpringUtils.getBean(RedisCache.class).keys(CacheConstants.SYS_DICT_KEY + "*"); + SpringUtils.getBean(RedisCache.class).deleteObject(keys); + } + + /** + * 设置cache key + * + * @param configKey 参数键 + * @return 缓存键key + */ + public static String getCacheKey(String configKey) + { + return CacheConstants.SYS_DICT_KEY + configKey; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java new file mode 100644 index 0000000..d58c5b1 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java @@ -0,0 +1,39 @@ +package com.ruoyi.common.utils; + +import java.io.PrintWriter; +import java.io.StringWriter; +import org.apache.commons.lang3.exception.ExceptionUtils; + +/** + * 错误信息处理类。 + * + * @author #author# + */ +public class ExceptionUtil +{ + /** + * 获取exception的详细错误信息。 + */ + public static String getExceptionMessage(Throwable e) + { + StringWriter sw = new StringWriter(); + e.printStackTrace(new PrintWriter(sw, true)); + return sw.toString(); + } + + public static String getRootErrorMessage(Exception e) + { + Throwable root = ExceptionUtils.getRootCause(e); + root = (root == null ? e : root); + if (root == null) + { + return ""; + } + String msg = root.getMessage(); + if (msg == null) + { + return "null"; + } + return StringUtils.defaultString(msg); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/LogUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/LogUtils.java new file mode 100644 index 0000000..8b55b37 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/LogUtils.java @@ -0,0 +1,18 @@ +package com.ruoyi.common.utils; + +/** + * 处理并记录日志文件 + * + * @author #author# + */ +public class LogUtils +{ + public static String getBlock(Object msg) + { + if (msg == null) + { + msg = ""; + } + return "[" + msg.toString() + "]"; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java new file mode 100644 index 0000000..f286b05 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java @@ -0,0 +1,26 @@ +package com.ruoyi.common.utils; + +import org.springframework.context.MessageSource; +import org.springframework.context.i18n.LocaleContextHolder; +import com.ruoyi.common.utils.spring.SpringUtils; + +/** + * 获取i18n资源文件 + * + * @author #author# + */ +public class MessageUtils +{ + /** + * 根据消息键和参数 获取消息 委托给spring messageSource + * + * @param code 消息键 + * @param args 参数 + * @return 获取国际化翻译值 + */ + public static String message(String code, Object... args) + { + MessageSource messageSource = SpringUtils.getBean(MessageSource.class); + return messageSource.getMessage(code, args, LocaleContextHolder.getLocale()); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java new file mode 100644 index 0000000..30f5010 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java @@ -0,0 +1,35 @@ +package com.ruoyi.common.utils; + +import com.github.pagehelper.PageHelper; +import com.ruoyi.common.core.page.PageDomain; +import com.ruoyi.common.core.page.TableSupport; +import com.ruoyi.common.utils.sql.SqlUtil; + +/** + * 分页工具类 + * + * @author #author# + */ +public class PageUtils extends PageHelper +{ + /** + * 设置请求分页数据 + */ + public static void startPage() + { + PageDomain pageDomain = TableSupport.buildPageRequest(); + Integer pageNum = pageDomain.getPageNum(); + Integer pageSize = pageDomain.getPageSize(); + String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy()); + Boolean reasonable = pageDomain.getReasonable(); + PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable); + } + + /** + * 清理分页的线程变量 + */ + public static void clearPage() + { + PageHelper.clearPage(); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java new file mode 100644 index 0000000..d60c7ad --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java @@ -0,0 +1,120 @@ +package com.ruoyi.common.utils; + +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import com.ruoyi.common.constant.HttpStatus; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.exception.ServiceException; + +/** + * 安全服务工具类 + * + * @author #author# + */ +public class SecurityUtils +{ + /** + * 用户ID + **/ + public static Long getUserId() + { + try + { + return getLoginUser().getUserId(); + } + catch (Exception e) + { + throw new ServiceException("获取用户ID异常", HttpStatus.UNAUTHORIZED); + } + } + + /** + * 获取部门ID + **/ + public static Long getDeptId() + { + try + { + return getLoginUser().getDeptId(); + } + catch (Exception e) + { + throw new ServiceException("获取部门ID异常", HttpStatus.UNAUTHORIZED); + } + } + + /** + * 获取用户账户 + **/ + public static String getUsername() + { + try + { + return getLoginUser().getUsername(); + } + catch (Exception e) + { + throw new ServiceException("获取用户账户异常", HttpStatus.UNAUTHORIZED); + } + } + + /** + * 获取用户 + **/ + public static LoginUser getLoginUser() + { + try + { + return (LoginUser) getAuthentication().getPrincipal(); + } + catch (Exception e) + { + throw new ServiceException("获取用户信息异常", HttpStatus.UNAUTHORIZED); + } + } + + /** + * 获取Authentication + */ + public static Authentication getAuthentication() + { + return SecurityContextHolder.getContext().getAuthentication(); + } + + /** + * 生成BCryptPasswordEncoder密码 + * + * @param password 密码 + * @return 加密字符串 + */ + public static String encryptPassword(String password) + { + BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + return passwordEncoder.encode(password); + } + + /** + * 判断密码是否相同 + * + * @param rawPassword 真实密码 + * @param encodedPassword 加密后字符 + * @return 结果 + */ + public static boolean matchesPassword(String rawPassword, String encodedPassword) + { + BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + return passwordEncoder.matches(rawPassword, encodedPassword); + } + + /** + * 是否为管理员 + * + * @param userId 用户ID + * @return 结果 + */ + public static boolean isAdmin(Long userId) + { + return userId != null && 1L == userId; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java new file mode 100644 index 0000000..12da09c --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java @@ -0,0 +1,218 @@ +package com.ruoyi.common.utils; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import javax.servlet.ServletRequest; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.text.Convert; + +/** + * 客户端工具类 + * + * @author #author# + */ +public class ServletUtils +{ + /** + * 获取String参数 + */ + public static String getParameter(String name) + { + return getRequest().getParameter(name); + } + + /** + * 获取String参数 + */ + public static String getParameter(String name, String defaultValue) + { + return Convert.toStr(getRequest().getParameter(name), defaultValue); + } + + /** + * 获取Integer参数 + */ + public static Integer getParameterToInt(String name) + { + return Convert.toInt(getRequest().getParameter(name)); + } + + /** + * 获取Integer参数 + */ + public static Integer getParameterToInt(String name, Integer defaultValue) + { + return Convert.toInt(getRequest().getParameter(name), defaultValue); + } + + /** + * 获取Boolean参数 + */ + public static Boolean getParameterToBool(String name) + { + return Convert.toBool(getRequest().getParameter(name)); + } + + /** + * 获取Boolean参数 + */ + public static Boolean getParameterToBool(String name, Boolean defaultValue) + { + return Convert.toBool(getRequest().getParameter(name), defaultValue); + } + + /** + * 获得所有请求参数 + * + * @param request 请求对象{@link ServletRequest} + * @return Map + */ + public static Map getParams(ServletRequest request) + { + final Map map = request.getParameterMap(); + return Collections.unmodifiableMap(map); + } + + /** + * 获得所有请求参数 + * + * @param request 请求对象{@link ServletRequest} + * @return Map + */ + public static Map getParamMap(ServletRequest request) + { + Map params = new HashMap<>(); + for (Map.Entry entry : getParams(request).entrySet()) + { + params.put(entry.getKey(), StringUtils.join(entry.getValue(), ",")); + } + return params; + } + + /** + * 获取request + */ + public static HttpServletRequest getRequest() + { + return getRequestAttributes().getRequest(); + } + + /** + * 获取response + */ + public static HttpServletResponse getResponse() + { + return getRequestAttributes().getResponse(); + } + + /** + * 获取session + */ + public static HttpSession getSession() + { + return getRequest().getSession(); + } + + public static ServletRequestAttributes getRequestAttributes() + { + RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); + return (ServletRequestAttributes) attributes; + } + + /** + * 将字符串渲染到客户端 + * + * @param response 渲染对象 + * @param string 待渲染的字符串 + */ + public static void renderString(HttpServletResponse response, String string) + { + try + { + response.setStatus(200); + response.setContentType("application/json"); + response.setCharacterEncoding("utf-8"); + response.getWriter().print(string); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + + /** + * 是否是Ajax异步请求 + * + * @param request + */ + public static boolean isAjaxRequest(HttpServletRequest request) + { + String accept = request.getHeader("accept"); + if (accept != null && accept.contains("application/json")) + { + return true; + } + + String xRequestedWith = request.getHeader("X-Requested-With"); + if (xRequestedWith != null && xRequestedWith.contains("XMLHttpRequest")) + { + return true; + } + + String uri = request.getRequestURI(); + if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml")) + { + return true; + } + + String ajax = request.getParameter("__ajax"); + return StringUtils.inStringIgnoreCase(ajax, "json", "xml"); + } + + /** + * 内容编码 + * + * @param str 内容 + * @return 编码后的内容 + */ + public static String urlEncode(String str) + { + try + { + return URLEncoder.encode(str, Constants.UTF8); + } + catch (UnsupportedEncodingException e) + { + return StringUtils.EMPTY; + } + } + + /** + * 内容解码 + * + * @param str 内容 + * @return 解码后的内容 + */ + public static String urlDecode(String str) + { + try + { + return URLDecoder.decode(str, Constants.UTF8); + } + catch (UnsupportedEncodingException e) + { + return StringUtils.EMPTY; + } + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java new file mode 100644 index 0000000..dcc4974 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java @@ -0,0 +1,614 @@ +package com.ruoyi.common.utils; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.springframework.util.AntPathMatcher; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.text.StrFormatter; + +/** + * 字符串工具类 + * + * @author #author# + */ +public class StringUtils extends org.apache.commons.lang3.StringUtils +{ + /** 空字符串 */ + private static final String NULLSTR = ""; + + /** 下划线 */ + private static final char SEPARATOR = '_'; + + /** + * 获取参数不为空值 + * + * @param value defaultValue 要判断的value + * @return value 返回值 + */ + public static T nvl(T value, T defaultValue) + { + return value != null ? value : defaultValue; + } + + /** + * * 判断一个Collection是否为空, 包含List,Set,Queue + * + * @param coll 要判断的Collection + * @return true:为空 false:非空 + */ + public static boolean isEmpty(Collection coll) + { + return isNull(coll) || coll.isEmpty(); + } + + /** + * * 判断一个Collection是否非空,包含List,Set,Queue + * + * @param coll 要判断的Collection + * @return true:非空 false:空 + */ + public static boolean isNotEmpty(Collection coll) + { + return !isEmpty(coll); + } + + /** + * * 判断一个对象数组是否为空 + * + * @param objects 要判断的对象数组 + ** @return true:为空 false:非空 + */ + public static boolean isEmpty(Object[] objects) + { + return isNull(objects) || (objects.length == 0); + } + + /** + * * 判断一个对象数组是否非空 + * + * @param objects 要判断的对象数组 + * @return true:非空 false:空 + */ + public static boolean isNotEmpty(Object[] objects) + { + return !isEmpty(objects); + } + + /** + * * 判断一个Map是否为空 + * + * @param map 要判断的Map + * @return true:为空 false:非空 + */ + public static boolean isEmpty(Map map) + { + return isNull(map) || map.isEmpty(); + } + + /** + * * 判断一个Map是否为空 + * + * @param map 要判断的Map + * @return true:非空 false:空 + */ + public static boolean isNotEmpty(Map map) + { + return !isEmpty(map); + } + + /** + * * 判断一个字符串是否为空串 + * + * @param str String + * @return true:为空 false:非空 + */ + public static boolean isEmpty(String str) + { + return isNull(str) || NULLSTR.equals(str.trim()); + } + + /** + * * 判断一个字符串是否为非空串 + * + * @param str String + * @return true:非空串 false:空串 + */ + public static boolean isNotEmpty(String str) + { + return !isEmpty(str); + } + + /** + * * 判断一个对象是否为空 + * + * @param object Object + * @return true:为空 false:非空 + */ + public static boolean isNull(Object object) + { + return object == null; + } + + /** + * * 判断一个对象是否非空 + * + * @param object Object + * @return true:非空 false:空 + */ + public static boolean isNotNull(Object object) + { + return !isNull(object); + } + + /** + * * 判断一个对象是否是数组类型(Java基本型别的数组) + * + * @param object 对象 + * @return true:是数组 false:不是数组 + */ + public static boolean isArray(Object object) + { + return isNotNull(object) && object.getClass().isArray(); + } + + /** + * 去空格 + */ + public static String trim(String str) + { + return (str == null ? "" : str.trim()); + } + + /** + * 截取字符串 + * + * @param str 字符串 + * @param start 开始 + * @return 结果 + */ + public static String substring(final String str, int start) + { + if (str == null) + { + return NULLSTR; + } + + if (start < 0) + { + start = str.length() + start; + } + + if (start < 0) + { + start = 0; + } + if (start > str.length()) + { + return NULLSTR; + } + + return str.substring(start); + } + + /** + * 截取字符串 + * + * @param str 字符串 + * @param start 开始 + * @param end 结束 + * @return 结果 + */ + public static String substring(final String str, int start, int end) + { + if (str == null) + { + return NULLSTR; + } + + if (end < 0) + { + end = str.length() + end; + } + if (start < 0) + { + start = str.length() + start; + } + + if (end > str.length()) + { + end = str.length(); + } + + if (start > end) + { + return NULLSTR; + } + + if (start < 0) + { + start = 0; + } + if (end < 0) + { + end = 0; + } + + return str.substring(start, end); + } + + /** + * 格式化文本, {} 表示占位符
+ * 此方法只是简单将占位符 {} 按照顺序替换为参数
+ * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可
+ * 例:
+ * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b
+ * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a
+ * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b
+ * + * @param template 文本模板,被替换的部分用 {} 表示 + * @param params 参数值 + * @return 格式化后的文本 + */ + public static String format(String template, Object... params) + { + if (isEmpty(params) || isEmpty(template)) + { + return template; + } + return StrFormatter.format(template, params); + } + + /** + * 是否为http(s)://开头 + * + * @param link 链接 + * @return 结果 + */ + public static boolean ishttp(String link) + { + return StringUtils.startsWithAny(link, Constants.HTTP, Constants.HTTPS); + } + + /** + * 字符串转set + * + * @param str 字符串 + * @param sep 分隔符 + * @return set集合 + */ + public static final Set str2Set(String str, String sep) + { + return new HashSet(str2List(str, sep, true, false)); + } + + /** + * 字符串转list + * + * @param str 字符串 + * @param sep 分隔符 + * @param filterBlank 过滤纯空白 + * @param trim 去掉首尾空白 + * @return list集合 + */ + public static final List str2List(String str, String sep, boolean filterBlank, boolean trim) + { + List list = new ArrayList(); + if (StringUtils.isEmpty(str)) + { + return list; + } + + // 过滤空白字符串 + if (filterBlank && StringUtils.isBlank(str)) + { + return list; + } + String[] split = str.split(sep); + for (String string : split) + { + if (filterBlank && StringUtils.isBlank(string)) + { + continue; + } + if (trim) + { + string = string.trim(); + } + list.add(string); + } + + return list; + } + + /** + * 判断给定的set列表中是否包含数组array 判断给定的数组array中是否包含给定的元素value + * + * @param set 给定的集合 + * @param array 给定的数组 + * @return boolean 结果 + */ + public static boolean containsAny(Collection collection, String... array) + { + if (isEmpty(collection) || isEmpty(array)) + { + return false; + } + else + { + for (String str : array) + { + if (collection.contains(str)) + { + return true; + } + } + return false; + } + } + + /** + * 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写 + * + * @param cs 指定字符串 + * @param searchCharSequences 需要检查的字符串数组 + * @return 是否包含任意一个字符串 + */ + public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences) + { + if (isEmpty(cs) || isEmpty(searchCharSequences)) + { + return false; + } + for (CharSequence testStr : searchCharSequences) + { + if (containsIgnoreCase(cs, testStr)) + { + return true; + } + } + return false; + } + + /** + * 驼峰转下划线命名 + */ + public static String toUnderScoreCase(String str) + { + if (str == null) + { + return null; + } + StringBuilder sb = new StringBuilder(); + // 前置字符是否大写 + boolean preCharIsUpperCase = true; + // 当前字符是否大写 + boolean curreCharIsUpperCase = true; + // 下一字符是否大写 + boolean nexteCharIsUpperCase = true; + for (int i = 0; i < str.length(); i++) + { + char c = str.charAt(i); + if (i > 0) + { + preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1)); + } + else + { + preCharIsUpperCase = false; + } + + curreCharIsUpperCase = Character.isUpperCase(c); + + if (i < (str.length() - 1)) + { + nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1)); + } + + if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase) + { + sb.append(SEPARATOR); + } + else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase) + { + sb.append(SEPARATOR); + } + sb.append(Character.toLowerCase(c)); + } + + return sb.toString(); + } + + /** + * 是否包含字符串 + * + * @param str 验证字符串 + * @param strs 字符串组 + * @return 包含返回true + */ + public static boolean inStringIgnoreCase(String str, String... strs) + { + if (str != null && strs != null) + { + for (String s : strs) + { + if (str.equalsIgnoreCase(trim(s))) + { + return true; + } + } + } + return false; + } + + /** + * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld + * + * @param name 转换前的下划线大写方式命名的字符串 + * @return 转换后的驼峰式命名的字符串 + */ + public static String convertToCamelCase(String name) + { + StringBuilder result = new StringBuilder(); + // 快速检查 + if (name == null || name.isEmpty()) + { + // 没必要转换 + return ""; + } + else if (!name.contains("_")) + { + // 不含下划线,仅将首字母大写 + return name.substring(0, 1).toUpperCase() + name.substring(1); + } + // 用下划线将原始字符串分割 + String[] camels = name.split("_"); + for (String camel : camels) + { + // 跳过原始字符串中开头、结尾的下换线或双重下划线 + if (camel.isEmpty()) + { + continue; + } + // 首字母大写 + result.append(camel.substring(0, 1).toUpperCase()); + result.append(camel.substring(1).toLowerCase()); + } + return result.toString(); + } + + /** + * 驼峰式命名法 + * 例如:user_name->userName + */ + public static String toCamelCase(String s) + { + if (s == null) + { + return null; + } + if (s.indexOf(SEPARATOR) == -1) + { + return s; + } + s = s.toLowerCase(); + StringBuilder sb = new StringBuilder(s.length()); + boolean upperCase = false; + for (int i = 0; i < s.length(); i++) + { + char c = s.charAt(i); + + if (c == SEPARATOR) + { + upperCase = true; + } + else if (upperCase) + { + sb.append(Character.toUpperCase(c)); + upperCase = false; + } + else + { + sb.append(c); + } + } + return sb.toString(); + } + + /** + * 查找指定字符串是否匹配指定字符串列表中的任意一个字符串 + * + * @param str 指定字符串 + * @param strs 需要检查的字符串数组 + * @return 是否匹配 + */ + public static boolean matches(String str, List strs) + { + if (isEmpty(str) || isEmpty(strs)) + { + return false; + } + for (String pattern : strs) + { + if (isMatch(pattern, str)) + { + return true; + } + } + return false; + } + + /** + * 判断url是否与规则配置: + * ? 表示单个字符; + * * 表示一层路径内的任意字符串,不可跨层级; + * ** 表示任意层路径; + * + * @param pattern 匹配规则 + * @param url 需要匹配的url + * @return + */ + public static boolean isMatch(String pattern, String url) + { + AntPathMatcher matcher = new AntPathMatcher(); + return matcher.match(pattern, url); + } + + @SuppressWarnings("unchecked") + public static T cast(Object obj) + { + return (T) obj; + } + + /** + * 数字左边补齐0,使之达到指定长度。注意,如果数字转换为字符串后,长度大于size,则只保留 最后size个字符。 + * + * @param num 数字对象 + * @param size 字符串指定长度 + * @return 返回数字的字符串格式,该字符串为指定长度。 + */ + public static final String padl(final Number num, final int size) + { + return padl(num.toString(), size, '0'); + } + + /** + * 字符串左补齐。如果原始字符串s长度大于size,则只保留最后size个字符。 + * + * @param s 原始字符串 + * @param size 字符串指定长度 + * @param c 用于补齐的字符 + * @return 返回指定长度的字符串,由原字符串左补齐或截取得到。 + */ + public static final String padl(final String s, final int size, final char c) + { + final StringBuilder sb = new StringBuilder(size); + if (s != null) + { + final int len = s.length(); + if (s.length() <= size) + { + for (int i = size - len; i > 0; i--) + { + sb.append(c); + } + sb.append(s); + } + else + { + return s.substring(len - size, len); + } + } + else + { + for (int i = size; i > 0; i--) + { + sb.append(c); + } + } + return sb.toString(); + } +} \ No newline at end of file diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java new file mode 100644 index 0000000..f420d9e --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java @@ -0,0 +1,99 @@ +package com.ruoyi.common.utils; + +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 线程相关工具类. + * + * @author #author# + */ +public class Threads +{ + private static final Logger logger = LoggerFactory.getLogger(Threads.class); + + /** + * sleep等待,单位为毫秒 + */ + public static void sleep(long milliseconds) + { + try + { + Thread.sleep(milliseconds); + } + catch (InterruptedException e) + { + return; + } + } + + /** + * 停止线程池 + * 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务. + * 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数. + * 如果仍然超時,則強制退出. + * 另对在shutdown时线程本身被调用中断做了处理. + */ + public static void shutdownAndAwaitTermination(ExecutorService pool) + { + if (pool != null && !pool.isShutdown()) + { + pool.shutdown(); + try + { + if (!pool.awaitTermination(120, TimeUnit.SECONDS)) + { + pool.shutdownNow(); + if (!pool.awaitTermination(120, TimeUnit.SECONDS)) + { + logger.info("Pool did not terminate"); + } + } + } + catch (InterruptedException ie) + { + pool.shutdownNow(); + Thread.currentThread().interrupt(); + } + } + } + + /** + * 打印线程异常信息 + */ + public static void printException(Runnable r, Throwable t) + { + if (t == null && r instanceof Future) + { + try + { + Future future = (Future) r; + if (future.isDone()) + { + future.get(); + } + } + catch (CancellationException ce) + { + t = ce; + } + catch (ExecutionException ee) + { + t = ee.getCause(); + } + catch (InterruptedException ie) + { + Thread.currentThread().interrupt(); + } + } + if (t != null) + { + logger.error(t.getMessage(), t); + } + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java new file mode 100644 index 0000000..f807f9e --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java @@ -0,0 +1,110 @@ +package com.ruoyi.common.utils.bean; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Bean 工具类 + * + * @author #author# + */ +public class BeanUtils extends org.springframework.beans.BeanUtils +{ + /** Bean方法名中属性名开始的下标 */ + private static final int BEAN_METHOD_PROP_INDEX = 3; + + /** * 匹配getter方法的正则表达式 */ + private static final Pattern GET_PATTERN = Pattern.compile("get(\\p{javaUpperCase}\\w*)"); + + /** * 匹配setter方法的正则表达式 */ + private static final Pattern SET_PATTERN = Pattern.compile("set(\\p{javaUpperCase}\\w*)"); + + /** + * Bean属性复制工具方法。 + * + * @param dest 目标对象 + * @param src 源对象 + */ + public static void copyBeanProp(Object dest, Object src) + { + try + { + copyProperties(src, dest); + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + /** + * 获取对象的setter方法。 + * + * @param obj 对象 + * @return 对象的setter方法列表 + */ + public static List getSetterMethods(Object obj) + { + // setter方法列表 + List setterMethods = new ArrayList(); + + // 获取所有方法 + Method[] methods = obj.getClass().getMethods(); + + // 查找setter方法 + + for (Method method : methods) + { + Matcher m = SET_PATTERN.matcher(method.getName()); + if (m.matches() && (method.getParameterTypes().length == 1)) + { + setterMethods.add(method); + } + } + // 返回setter方法列表 + return setterMethods; + } + + /** + * 获取对象的getter方法。 + * + * @param obj 对象 + * @return 对象的getter方法列表 + */ + + public static List getGetterMethods(Object obj) + { + // getter方法列表 + List getterMethods = new ArrayList(); + // 获取所有方法 + Method[] methods = obj.getClass().getMethods(); + // 查找getter方法 + for (Method method : methods) + { + Matcher m = GET_PATTERN.matcher(method.getName()); + if (m.matches() && (method.getParameterTypes().length == 0)) + { + getterMethods.add(method); + } + } + // 返回getter方法列表 + return getterMethods; + } + + /** + * 检查Bean方法名中的属性名是否相等。
+ * 如getName()和setName()属性名一样,getName()和setAge()属性名不一样。 + * + * @param m1 方法名1 + * @param m2 方法名2 + * @return 属性名一样返回true,否则返回false + */ + + public static boolean isMethodPropEquals(String m1, String m2) + { + return m1.substring(BEAN_METHOD_PROP_INDEX).equals(m2.substring(BEAN_METHOD_PROP_INDEX)); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanValidators.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanValidators.java new file mode 100644 index 0000000..1d6521f --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanValidators.java @@ -0,0 +1,24 @@ +package com.ruoyi.common.utils.bean; + +import java.util.Set; +import javax.validation.ConstraintViolation; +import javax.validation.ConstraintViolationException; +import javax.validation.Validator; + +/** + * bean对象属性验证 + * + * @author #author# + */ +public class BeanValidators +{ + public static void validateWithException(Validator validator, Object object, Class... groups) + throws ConstraintViolationException + { + Set> constraintViolations = validator.validate(object, groups); + if (!constraintViolations.isEmpty()) + { + throw new ConstraintViolationException(constraintViolations); + } + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java new file mode 100644 index 0000000..6ded4de --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java @@ -0,0 +1,76 @@ +package com.ruoyi.common.utils.file; + +import java.io.File; +import org.apache.commons.lang3.StringUtils; + +/** + * 文件类型工具类 + * + * @author #author# + */ +public class FileTypeUtils +{ + /** + * 获取文件类型 + *

+ * 例如: ruoyi.txt, 返回: txt + * + * @param file 文件名 + * @return 后缀(不含".") + */ + public static String getFileType(File file) + { + if (null == file) + { + return StringUtils.EMPTY; + } + return getFileType(file.getName()); + } + + /** + * 获取文件类型 + *

+ * 例如: ruoyi.txt, 返回: txt + * + * @param fileName 文件名 + * @return 后缀(不含".") + */ + public static String getFileType(String fileName) + { + int separatorIndex = fileName.lastIndexOf("."); + if (separatorIndex < 0) + { + return ""; + } + return fileName.substring(separatorIndex + 1).toLowerCase(); + } + + /** + * 获取文件类型 + * + * @param photoByte 文件字节码 + * @return 后缀(不含".") + */ + public static String getFileExtendName(byte[] photoByte) + { + String strFileExtendName = "JPG"; + if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56) + && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97)) + { + strFileExtendName = "GIF"; + } + else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70)) + { + strFileExtendName = "JPG"; + } + else if ((photoByte[0] == 66) && (photoByte[1] == 77)) + { + strFileExtendName = "BMP"; + } + else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71)) + { + strFileExtendName = "PNG"; + } + return strFileExtendName; + } +} \ No newline at end of file diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java new file mode 100644 index 0000000..831bb83 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java @@ -0,0 +1,232 @@ +package com.ruoyi.common.utils.file; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Paths; +import java.util.Objects; +import org.apache.commons.io.FilenameUtils; +import org.springframework.web.multipart.MultipartFile; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.exception.file.FileNameLengthLimitExceededException; +import com.ruoyi.common.exception.file.FileSizeLimitExceededException; +import com.ruoyi.common.exception.file.InvalidExtensionException; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.uuid.Seq; + +/** + * 文件上传工具类 + * + * @author #author# + */ +public class FileUploadUtils +{ + /** + * 默认大小 50M + */ + public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024; + + /** + * 默认的文件名最大长度 100 + */ + public static final int DEFAULT_FILE_NAME_LENGTH = 100; + + /** + * 默认上传的地址 + */ + private static String defaultBaseDir = RuoYiConfig.getProfile(); + + public static void setDefaultBaseDir(String defaultBaseDir) + { + FileUploadUtils.defaultBaseDir = defaultBaseDir; + } + + public static String getDefaultBaseDir() + { + return defaultBaseDir; + } + + /** + * 以默认配置进行文件上传 + * + * @param file 上传的文件 + * @return 文件名称 + * @throws Exception + */ + public static final String upload(MultipartFile file) throws IOException + { + try + { + return upload(getDefaultBaseDir(), file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION); + } + catch (Exception e) + { + throw new IOException(e.getMessage(), e); + } + } + + /** + * 根据文件路径上传 + * + * @param baseDir 相对应用的基目录 + * @param file 上传的文件 + * @return 文件名称 + * @throws IOException + */ + public static final String upload(String baseDir, MultipartFile file) throws IOException + { + try + { + return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION); + } + catch (Exception e) + { + throw new IOException(e.getMessage(), e); + } + } + + /** + * 文件上传 + * + * @param baseDir 相对应用的基目录 + * @param file 上传的文件 + * @param allowedExtension 上传文件类型 + * @return 返回上传成功的文件名 + * @throws FileSizeLimitExceededException 如果超出最大大小 + * @throws FileNameLengthLimitExceededException 文件名太长 + * @throws IOException 比如读写文件出错时 + * @throws InvalidExtensionException 文件校验异常 + */ + public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension) + throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException, + InvalidExtensionException + { + int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length(); + if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) + { + throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH); + } + + assertAllowed(file, allowedExtension); + + String fileName = extractFilename(file); + + String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath(); + file.transferTo(Paths.get(absPath)); + return getPathFileName(baseDir, fileName); + } + + /** + * 编码文件名 + */ + public static final String extractFilename(MultipartFile file) + { + return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(), + FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), getExtension(file)); + } + + public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException + { + File desc = new File(uploadDir + File.separator + fileName); + + if (!desc.exists()) + { + if (!desc.getParentFile().exists()) + { + desc.getParentFile().mkdirs(); + } + } + return desc; + } + + public static final String getPathFileName(String uploadDir, String fileName) throws IOException + { + int dirLastIndex = RuoYiConfig.getProfile().length() + 1; + String currentDir = StringUtils.substring(uploadDir, dirLastIndex); + return Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName; + } + + /** + * 文件大小校验 + * + * @param file 上传的文件 + * @return + * @throws FileSizeLimitExceededException 如果超出最大大小 + * @throws InvalidExtensionException + */ + public static final void assertAllowed(MultipartFile file, String[] allowedExtension) + throws FileSizeLimitExceededException, InvalidExtensionException + { + long size = file.getSize(); + if (size > DEFAULT_MAX_SIZE) + { + throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024); + } + + String fileName = file.getOriginalFilename(); + String extension = getExtension(file); + if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension)) + { + if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION) + { + throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension, + fileName); + } + else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION) + { + throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension, + fileName); + } + else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION) + { + throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension, + fileName); + } + else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION) + { + throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension, + fileName); + } + else + { + throw new InvalidExtensionException(allowedExtension, extension, fileName); + } + } + } + + /** + * 判断MIME类型是否是允许的MIME类型 + * + * @param extension + * @param allowedExtension + * @return + */ + public static final boolean isAllowedExtension(String extension, String[] allowedExtension) + { + for (String str : allowedExtension) + { + if (str.equalsIgnoreCase(extension)) + { + return true; + } + } + return false; + } + + /** + * 获取文件名的后缀 + * + * @param file 表单文件 + * @return 后缀名 + */ + public static final String getExtension(MultipartFile file) + { + String extension = FilenameUtils.getExtension(file.getOriginalFilename()); + if (StringUtils.isEmpty(extension)) + { + extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType())); + } + return extension; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java new file mode 100644 index 0000000..a8a5736 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java @@ -0,0 +1,291 @@ +package com.ruoyi.common.utils.file; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.ArrayUtils; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.uuid.IdUtils; +import org.apache.commons.io.FilenameUtils; + +/** + * 文件处理工具类 + * + * @author #author# + */ +public class FileUtils +{ + public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+"; + + /** + * 输出指定文件的byte数组 + * + * @param filePath 文件路径 + * @param os 输出流 + * @return + */ + public static void writeBytes(String filePath, OutputStream os) throws IOException + { + FileInputStream fis = null; + try + { + File file = new File(filePath); + if (!file.exists()) + { + throw new FileNotFoundException(filePath); + } + fis = new FileInputStream(file); + byte[] b = new byte[1024]; + int length; + while ((length = fis.read(b)) > 0) + { + os.write(b, 0, length); + } + } + catch (IOException e) + { + throw e; + } + finally + { + IOUtils.close(os); + IOUtils.close(fis); + } + } + + /** + * 写数据到文件中 + * + * @param data 数据 + * @return 目标文件 + * @throws IOException IO异常 + */ + public static String writeImportBytes(byte[] data) throws IOException + { + return writeBytes(data, RuoYiConfig.getImportPath()); + } + + /** + * 写数据到文件中 + * + * @param data 数据 + * @param uploadDir 目标文件 + * @return 目标文件 + * @throws IOException IO异常 + */ + public static String writeBytes(byte[] data, String uploadDir) throws IOException + { + FileOutputStream fos = null; + String pathName = ""; + try + { + String extension = getFileExtendName(data); + pathName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension; + File file = FileUploadUtils.getAbsoluteFile(uploadDir, pathName); + fos = new FileOutputStream(file); + fos.write(data); + } + finally + { + IOUtils.close(fos); + } + return FileUploadUtils.getPathFileName(uploadDir, pathName); + } + + /** + * 删除文件 + * + * @param filePath 文件 + * @return + */ + public static boolean deleteFile(String filePath) + { + boolean flag = false; + File file = new File(filePath); + // 路径为文件且不为空则进行删除 + if (file.isFile() && file.exists()) + { + flag = file.delete(); + } + return flag; + } + + /** + * 文件名称验证 + * + * @param filename 文件名称 + * @return true 正常 false 非法 + */ + public static boolean isValidFilename(String filename) + { + return filename.matches(FILENAME_PATTERN); + } + + /** + * 检查文件是否可下载 + * + * @param resource 需要下载的文件 + * @return true 正常 false 非法 + */ + public static boolean checkAllowDownload(String resource) + { + // 禁止目录上跳级别 + if (StringUtils.contains(resource, "..")) + { + return false; + } + + // 检查允许下载的文件规则 + if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource))) + { + return true; + } + + // 不在允许下载的文件规则 + return false; + } + + /** + * 下载文件名重新编码 + * + * @param request 请求对象 + * @param fileName 文件名 + * @return 编码后的文件名 + */ + public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException + { + final String agent = request.getHeader("USER-AGENT"); + String filename = fileName; + if (agent.contains("MSIE")) + { + // IE浏览器 + filename = URLEncoder.encode(filename, "utf-8"); + filename = filename.replace("+", " "); + } + else if (agent.contains("Firefox")) + { + // 火狐浏览器 + filename = new String(fileName.getBytes(), "ISO8859-1"); + } + else if (agent.contains("Chrome")) + { + // google浏览器 + filename = URLEncoder.encode(filename, "utf-8"); + } + else + { + // 其它浏览器 + filename = URLEncoder.encode(filename, "utf-8"); + } + return filename; + } + + /** + * 下载文件名重新编码 + * + * @param response 响应对象 + * @param realFileName 真实文件名 + */ + public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException + { + String percentEncodedFileName = percentEncode(realFileName); + + StringBuilder contentDispositionValue = new StringBuilder(); + contentDispositionValue.append("attachment; filename=") + .append(percentEncodedFileName) + .append(";") + .append("filename*=") + .append("utf-8''") + .append(percentEncodedFileName); + + response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename"); + response.setHeader("Content-disposition", contentDispositionValue.toString()); + response.setHeader("download-filename", percentEncodedFileName); + } + + /** + * 百分号编码工具方法 + * + * @param s 需要百分号编码的字符串 + * @return 百分号编码后的字符串 + */ + public static String percentEncode(String s) throws UnsupportedEncodingException + { + String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString()); + return encode.replaceAll("\\+", "%20"); + } + + /** + * 获取图像后缀 + * + * @param photoByte 图像数据 + * @return 后缀名 + */ + public static String getFileExtendName(byte[] photoByte) + { + String strFileExtendName = "jpg"; + if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56) + && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97)) + { + strFileExtendName = "gif"; + } + else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70)) + { + strFileExtendName = "jpg"; + } + else if ((photoByte[0] == 66) && (photoByte[1] == 77)) + { + strFileExtendName = "bmp"; + } + else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71)) + { + strFileExtendName = "png"; + } + return strFileExtendName; + } + + /** + * 获取文件名称 /profile/upload/2022/04/16/ruoyi.png -- ruoyi.png + * + * @param fileName 路径名称 + * @return 没有文件路径的名称 + */ + public static String getName(String fileName) + { + if (fileName == null) + { + return null; + } + int lastUnixPos = fileName.lastIndexOf('/'); + int lastWindowsPos = fileName.lastIndexOf('\\'); + int index = Math.max(lastUnixPos, lastWindowsPos); + return fileName.substring(index + 1); + } + + /** + * 获取不带后缀文件名称 /profile/upload/2022/04/16/ruoyi.png -- ruoyi + * + * @param fileName 路径名称 + * @return 没有文件路径和后缀的名称 + */ + public static String getNameNotSuffix(String fileName) + { + if (fileName == null) + { + return null; + } + String baseName = FilenameUtils.getBaseName(fileName); + return baseName; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java new file mode 100644 index 0000000..d957c14 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java @@ -0,0 +1,98 @@ +package com.ruoyi.common.utils.file; + +import java.io.ByteArrayInputStream; +import java.io.FileInputStream; +import java.io.InputStream; +import java.net.URL; +import java.net.URLConnection; +import java.util.Arrays; +import org.apache.poi.util.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.utils.StringUtils; + +/** + * 图片处理工具类 + * + * @author #author# + */ +public class ImageUtils +{ + private static final Logger log = LoggerFactory.getLogger(ImageUtils.class); + + public static byte[] getImage(String imagePath) + { + InputStream is = getFile(imagePath); + try + { + return IOUtils.toByteArray(is); + } + catch (Exception e) + { + log.error("图片加载异常 {}", e); + return null; + } + finally + { + IOUtils.closeQuietly(is); + } + } + + public static InputStream getFile(String imagePath) + { + try + { + byte[] result = readFile(imagePath); + result = Arrays.copyOf(result, result.length); + return new ByteArrayInputStream(result); + } + catch (Exception e) + { + log.error("获取图片异常 {}", e); + } + return null; + } + + /** + * 读取文件为字节数据 + * + * @param url 地址 + * @return 字节数据 + */ + public static byte[] readFile(String url) + { + InputStream in = null; + try + { + if (url.startsWith("http")) + { + // 网络地址 + URL urlObj = new URL(url); + URLConnection urlConnection = urlObj.openConnection(); + urlConnection.setConnectTimeout(30 * 1000); + urlConnection.setReadTimeout(60 * 1000); + urlConnection.setDoInput(true); + in = urlConnection.getInputStream(); + } + else + { + // 本机地址 + String localPath = RuoYiConfig.getProfile(); + String downloadPath = localPath + StringUtils.substringAfter(url, Constants.RESOURCE_PREFIX); + in = new FileInputStream(downloadPath); + } + return IOUtils.toByteArray(in); + } + catch (Exception e) + { + log.error("获取文件路径异常 {}", e); + return null; + } + finally + { + IOUtils.closeQuietly(in); + } + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java new file mode 100644 index 0000000..2babfc2 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java @@ -0,0 +1,59 @@ +package com.ruoyi.common.utils.file; + +/** + * 媒体类型工具类 + * + * @author #author# + */ +public class MimeTypeUtils +{ + public static final String IMAGE_PNG = "image/png"; + + public static final String IMAGE_JPG = "image/jpg"; + + public static final String IMAGE_JPEG = "image/jpeg"; + + public static final String IMAGE_BMP = "image/bmp"; + + public static final String IMAGE_GIF = "image/gif"; + + public static final String[] IMAGE_EXTENSION = { "bmp", "gif", "jpg", "jpeg", "png" }; + + public static final String[] FLASH_EXTENSION = { "swf", "flv" }; + + public static final String[] MEDIA_EXTENSION = { "swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg", + "asf", "rm", "rmvb" }; + + public static final String[] VIDEO_EXTENSION = { "mp4", "avi", "rmvb" }; + + public static final String[] DEFAULT_ALLOWED_EXTENSION = { + // 图片 + "bmp", "gif", "jpg", "jpeg", "png", + // word excel powerpoint + "doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt", + // 压缩文件 + "rar", "zip", "gz", "bz2", + // 视频格式 + "mp4", "avi", "rmvb", + // pdf + "pdf" }; + + public static String getExtension(String prefix) + { + switch (prefix) + { + case IMAGE_PNG: + return "png"; + case IMAGE_JPG: + return "jpg"; + case IMAGE_JPEG: + return "jpeg"; + case IMAGE_BMP: + return "bmp"; + case IMAGE_GIF: + return "gif"; + default: + return ""; + } + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java new file mode 100644 index 0000000..24ac58e --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java @@ -0,0 +1,167 @@ +package com.ruoyi.common.utils.html; + +import com.ruoyi.common.utils.StringUtils; + +/** + * 转义和反转义工具类 + * + * @author #author# + */ +public class EscapeUtil +{ + public static final String RE_HTML_MARK = "(<[^<]*?>)|(<[\\s]*?/[^<]*?>)|(<[^<]*?/[\\s]*?>)"; + + private static final char[][] TEXT = new char[64][]; + + static + { + for (int i = 0; i < 64; i++) + { + TEXT[i] = new char[] { (char) i }; + } + + // special HTML characters + TEXT['\''] = "'".toCharArray(); // 单引号 + TEXT['"'] = """.toCharArray(); // 双引号 + TEXT['&'] = "&".toCharArray(); // &符 + TEXT['<'] = "<".toCharArray(); // 小于号 + TEXT['>'] = ">".toCharArray(); // 大于号 + } + + /** + * 转义文本中的HTML字符为安全的字符 + * + * @param text 被转义的文本 + * @return 转义后的文本 + */ + public static String escape(String text) + { + return encode(text); + } + + /** + * 还原被转义的HTML特殊字符 + * + * @param content 包含转义符的HTML内容 + * @return 转换后的字符串 + */ + public static String unescape(String content) + { + return decode(content); + } + + /** + * 清除所有HTML标签,但是不删除标签内的内容 + * + * @param content 文本 + * @return 清除标签后的文本 + */ + public static String clean(String content) + { + return new HTMLFilter().filter(content); + } + + /** + * Escape编码 + * + * @param text 被编码的文本 + * @return 编码后的字符 + */ + private static String encode(String text) + { + if (StringUtils.isEmpty(text)) + { + return StringUtils.EMPTY; + } + + final StringBuilder tmp = new StringBuilder(text.length() * 6); + char c; + for (int i = 0; i < text.length(); i++) + { + c = text.charAt(i); + if (c < 256) + { + tmp.append("%"); + if (c < 16) + { + tmp.append("0"); + } + tmp.append(Integer.toString(c, 16)); + } + else + { + tmp.append("%u"); + if (c <= 0xfff) + { + // issue#I49JU8@Gitee + tmp.append("0"); + } + tmp.append(Integer.toString(c, 16)); + } + } + return tmp.toString(); + } + + /** + * Escape解码 + * + * @param content 被转义的内容 + * @return 解码后的字符串 + */ + public static String decode(String content) + { + if (StringUtils.isEmpty(content)) + { + return content; + } + + StringBuilder tmp = new StringBuilder(content.length()); + int lastPos = 0, pos = 0; + char ch; + while (lastPos < content.length()) + { + pos = content.indexOf("%", lastPos); + if (pos == lastPos) + { + if (content.charAt(pos + 1) == 'u') + { + ch = (char) Integer.parseInt(content.substring(pos + 2, pos + 6), 16); + tmp.append(ch); + lastPos = pos + 6; + } + else + { + ch = (char) Integer.parseInt(content.substring(pos + 1, pos + 3), 16); + tmp.append(ch); + lastPos = pos + 3; + } + } + else + { + if (pos == -1) + { + tmp.append(content.substring(lastPos)); + lastPos = content.length(); + } + else + { + tmp.append(content.substring(lastPos, pos)); + lastPos = pos; + } + } + } + return tmp.toString(); + } + + public static void main(String[] args) + { + String html = ""; + String escape = EscapeUtil.escape(html); + // String html = "ipt>alert(\"XSS\")ipt>"; + // String html = "<123"; + // String html = "123>"; + System.out.println("clean: " + EscapeUtil.clean(html)); + System.out.println("escape: " + escape); + System.out.println("unescape: " + EscapeUtil.unescape(escape)); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java new file mode 100644 index 0000000..eebfcd3 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java @@ -0,0 +1,570 @@ +package com.ruoyi.common.utils.html; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * HTML过滤器,用于去除XSS漏洞隐患。 + * + * @author #author# + */ +public final class HTMLFilter +{ + /** + * regex flag union representing /si modifiers in php + **/ + private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL; + private static final Pattern P_COMMENTS = Pattern.compile("", Pattern.DOTALL); + private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI); + private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL); + private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI); + private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI); + private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI); + private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI); + private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI); + private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?"); + private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?"); + private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?"); + private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))"); + private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL); + private static final Pattern P_END_ARROW = Pattern.compile("^>"); + private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)"); + private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)"); + private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)"); + private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)"); + private static final Pattern P_AMP = Pattern.compile("&"); + private static final Pattern P_QUOTE = Pattern.compile("\""); + private static final Pattern P_LEFT_ARROW = Pattern.compile("<"); + private static final Pattern P_RIGHT_ARROW = Pattern.compile(">"); + private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>"); + + // @xxx could grow large... maybe use sesat's ReferenceMap + private static final ConcurrentMap P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<>(); + private static final ConcurrentMap P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<>(); + + /** + * set of allowed html elements, along with allowed attributes for each element + **/ + private final Map> vAllowed; + /** + * counts of open tags for each (allowable) html element + **/ + private final Map vTagCounts = new HashMap<>(); + + /** + * html elements which must always be self-closing (e.g. "") + **/ + private final String[] vSelfClosingTags; + /** + * html elements which must always have separate opening and closing tags (e.g. "") + **/ + private final String[] vNeedClosingTags; + /** + * set of disallowed html elements + **/ + private final String[] vDisallowed; + /** + * attributes which should be checked for valid protocols + **/ + private final String[] vProtocolAtts; + /** + * allowed protocols + **/ + private final String[] vAllowedProtocols; + /** + * tags which should be removed if they contain no content (e.g. "" or "") + **/ + private final String[] vRemoveBlanks; + /** + * entities allowed within html markup + **/ + private final String[] vAllowedEntities; + /** + * flag determining whether comments are allowed in input String. + */ + private final boolean stripComment; + private final boolean encodeQuotes; + /** + * flag determining whether to try to make tags when presented with "unbalanced" angle brackets (e.g. "" + * becomes " text "). If set to false, unbalanced angle brackets will be html escaped. + */ + private final boolean alwaysMakeTags; + + /** + * Default constructor. + */ + public HTMLFilter() + { + vAllowed = new HashMap<>(); + + final ArrayList a_atts = new ArrayList<>(); + a_atts.add("href"); + a_atts.add("target"); + vAllowed.put("a", a_atts); + + final ArrayList img_atts = new ArrayList<>(); + img_atts.add("src"); + img_atts.add("width"); + img_atts.add("height"); + img_atts.add("alt"); + vAllowed.put("img", img_atts); + + final ArrayList no_atts = new ArrayList<>(); + vAllowed.put("b", no_atts); + vAllowed.put("strong", no_atts); + vAllowed.put("i", no_atts); + vAllowed.put("em", no_atts); + + vSelfClosingTags = new String[] { "img" }; + vNeedClosingTags = new String[] { "a", "b", "strong", "i", "em" }; + vDisallowed = new String[] {}; + vAllowedProtocols = new String[] { "http", "mailto", "https" }; // no ftp. + vProtocolAtts = new String[] { "src", "href" }; + vRemoveBlanks = new String[] { "a", "b", "strong", "i", "em" }; + vAllowedEntities = new String[] { "amp", "gt", "lt", "quot" }; + stripComment = true; + encodeQuotes = true; + alwaysMakeTags = false; + } + + /** + * Map-parameter configurable constructor. + * + * @param conf map containing configuration. keys match field names. + */ + @SuppressWarnings("unchecked") + public HTMLFilter(final Map conf) + { + + assert conf.containsKey("vAllowed") : "configuration requires vAllowed"; + assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags"; + assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags"; + assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed"; + assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols"; + assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts"; + assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks"; + assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities"; + + vAllowed = Collections.unmodifiableMap((HashMap>) conf.get("vAllowed")); + vSelfClosingTags = (String[]) conf.get("vSelfClosingTags"); + vNeedClosingTags = (String[]) conf.get("vNeedClosingTags"); + vDisallowed = (String[]) conf.get("vDisallowed"); + vAllowedProtocols = (String[]) conf.get("vAllowedProtocols"); + vProtocolAtts = (String[]) conf.get("vProtocolAtts"); + vRemoveBlanks = (String[]) conf.get("vRemoveBlanks"); + vAllowedEntities = (String[]) conf.get("vAllowedEntities"); + stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true; + encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true; + alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true; + } + + private void reset() + { + vTagCounts.clear(); + } + + // --------------------------------------------------------------- + // my versions of some PHP library functions + public static String chr(final int decimal) + { + return String.valueOf((char) decimal); + } + + public static String htmlSpecialChars(final String s) + { + String result = s; + result = regexReplace(P_AMP, "&", result); + result = regexReplace(P_QUOTE, """, result); + result = regexReplace(P_LEFT_ARROW, "<", result); + result = regexReplace(P_RIGHT_ARROW, ">", result); + return result; + } + + // --------------------------------------------------------------- + + /** + * given a user submitted input String, filter out any invalid or restricted html. + * + * @param input text (i.e. submitted by a user) than may contain html + * @return "clean" version of input, with only valid, whitelisted html elements allowed + */ + public String filter(final String input) + { + reset(); + String s = input; + + s = escapeComments(s); + + s = balanceHTML(s); + + s = checkTags(s); + + s = processRemoveBlanks(s); + + // s = validateEntities(s); + + return s; + } + + public boolean isAlwaysMakeTags() + { + return alwaysMakeTags; + } + + public boolean isStripComments() + { + return stripComment; + } + + private String escapeComments(final String s) + { + final Matcher m = P_COMMENTS.matcher(s); + final StringBuffer buf = new StringBuffer(); + if (m.find()) + { + final String match = m.group(1); // (.*?) + m.appendReplacement(buf, Matcher.quoteReplacement("")); + } + m.appendTail(buf); + + return buf.toString(); + } + + private String balanceHTML(String s) + { + if (alwaysMakeTags) + { + // + // try and form html + // + s = regexReplace(P_END_ARROW, "", s); + // 不追加结束标签 + s = regexReplace(P_BODY_TO_END, "<$1>", s); + s = regexReplace(P_XML_CONTENT, "$1<$2", s); + + } + else + { + // + // escape stray brackets + // + s = regexReplace(P_STRAY_LEFT_ARROW, "<$1", s); + s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2><", s); + + // + // the last regexp causes '<>' entities to appear + // (we need to do a lookahead assertion so that the last bracket can + // be used in the next pass of the regexp) + // + s = regexReplace(P_BOTH_ARROWS, "", s); + } + + return s; + } + + private String checkTags(String s) + { + Matcher m = P_TAGS.matcher(s); + + final StringBuffer buf = new StringBuffer(); + while (m.find()) + { + String replaceStr = m.group(1); + replaceStr = processTag(replaceStr); + m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr)); + } + m.appendTail(buf); + + // these get tallied in processTag + // (remember to reset before subsequent calls to filter method) + final StringBuilder sBuilder = new StringBuilder(buf.toString()); + for (String key : vTagCounts.keySet()) + { + for (int ii = 0; ii < vTagCounts.get(key); ii++) + { + sBuilder.append(""); + } + } + s = sBuilder.toString(); + + return s; + } + + private String processRemoveBlanks(final String s) + { + String result = s; + for (String tag : vRemoveBlanks) + { + if (!P_REMOVE_PAIR_BLANKS.containsKey(tag)) + { + P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?>")); + } + result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result); + if (!P_REMOVE_SELF_BLANKS.containsKey(tag)) + { + P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>")); + } + result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result); + } + + return result; + } + + private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s) + { + Matcher m = regex_pattern.matcher(s); + return m.replaceAll(replacement); + } + + private String processTag(final String s) + { + // ending tags + Matcher m = P_END_TAG.matcher(s); + if (m.find()) + { + final String name = m.group(1).toLowerCase(); + if (allowed(name)) + { + if (!inArray(name, vSelfClosingTags)) + { + if (vTagCounts.containsKey(name)) + { + vTagCounts.put(name, vTagCounts.get(name) - 1); + return ""; + } + } + } + } + + // starting tags + m = P_START_TAG.matcher(s); + if (m.find()) + { + final String name = m.group(1).toLowerCase(); + final String body = m.group(2); + String ending = m.group(3); + + // debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" ); + if (allowed(name)) + { + final StringBuilder params = new StringBuilder(); + + final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body); + final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body); + final List paramNames = new ArrayList<>(); + final List paramValues = new ArrayList<>(); + while (m2.find()) + { + paramNames.add(m2.group(1)); // ([a-z0-9]+) + paramValues.add(m2.group(3)); // (.*?) + } + while (m3.find()) + { + paramNames.add(m3.group(1)); // ([a-z0-9]+) + paramValues.add(m3.group(3)); // ([^\"\\s']+) + } + + String paramName, paramValue; + for (int ii = 0; ii < paramNames.size(); ii++) + { + paramName = paramNames.get(ii).toLowerCase(); + paramValue = paramValues.get(ii); + + // debug( "paramName='" + paramName + "'" ); + // debug( "paramValue='" + paramValue + "'" ); + // debug( "allowed? " + vAllowed.get( name ).contains( paramName ) ); + + if (allowedAttribute(name, paramName)) + { + if (inArray(paramName, vProtocolAtts)) + { + paramValue = processParamProtocol(paramValue); + } + params.append(' ').append(paramName).append("=\\\"").append(paramValue).append("\\\""); + } + } + + if (inArray(name, vSelfClosingTags)) + { + ending = " /"; + } + + if (inArray(name, vNeedClosingTags)) + { + ending = ""; + } + + if (ending == null || ending.length() < 1) + { + if (vTagCounts.containsKey(name)) + { + vTagCounts.put(name, vTagCounts.get(name) + 1); + } + else + { + vTagCounts.put(name, 1); + } + } + else + { + ending = " /"; + } + return "<" + name + params + ending + ">"; + } + else + { + return ""; + } + } + + // comments + m = P_COMMENT.matcher(s); + if (!stripComment && m.find()) + { + return "<" + m.group() + ">"; + } + + return ""; + } + + private String processParamProtocol(String s) + { + s = decodeEntities(s); + final Matcher m = P_PROTOCOL.matcher(s); + if (m.find()) + { + final String protocol = m.group(1); + if (!inArray(protocol, vAllowedProtocols)) + { + // bad protocol, turn into local anchor link instead + s = "#" + s.substring(protocol.length() + 1); + if (s.startsWith("#//")) + { + s = "#" + s.substring(3); + } + } + } + + return s; + } + + private String decodeEntities(String s) + { + StringBuffer buf = new StringBuffer(); + + Matcher m = P_ENTITY.matcher(s); + while (m.find()) + { + final String match = m.group(1); + final int decimal = Integer.decode(match).intValue(); + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + } + m.appendTail(buf); + s = buf.toString(); + + buf = new StringBuffer(); + m = P_ENTITY_UNICODE.matcher(s); + while (m.find()) + { + final String match = m.group(1); + final int decimal = Integer.valueOf(match, 16).intValue(); + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + } + m.appendTail(buf); + s = buf.toString(); + + buf = new StringBuffer(); + m = P_ENCODE.matcher(s); + while (m.find()) + { + final String match = m.group(1); + final int decimal = Integer.valueOf(match, 16).intValue(); + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + } + m.appendTail(buf); + s = buf.toString(); + + s = validateEntities(s); + return s; + } + + private String validateEntities(final String s) + { + StringBuffer buf = new StringBuffer(); + + // validate entities throughout the string + Matcher m = P_VALID_ENTITIES.matcher(s); + while (m.find()) + { + final String one = m.group(1); // ([^&;]*) + final String two = m.group(2); // (?=(;|&|$)) + m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two))); + } + m.appendTail(buf); + + return encodeQuotes(buf.toString()); + } + + private String encodeQuotes(final String s) + { + if (encodeQuotes) + { + StringBuffer buf = new StringBuffer(); + Matcher m = P_VALID_QUOTES.matcher(s); + while (m.find()) + { + final String one = m.group(1); // (>|^) + final String two = m.group(2); // ([^<]+?) + final String three = m.group(3); // (<|$) + // 不替换双引号为",防止json格式无效 regexReplace(P_QUOTE, """, two) + m.appendReplacement(buf, Matcher.quoteReplacement(one + two + three)); + } + m.appendTail(buf); + return buf.toString(); + } + else + { + return s; + } + } + + private String checkEntity(final String preamble, final String term) + { + + return ";".equals(term) && isValidEntity(preamble) ? '&' + preamble : "&" + preamble; + } + + private boolean isValidEntity(final String entity) + { + return inArray(entity, vAllowedEntities); + } + + private static boolean inArray(final String s, final String[] array) + { + for (String item : array) + { + if (item != null && item.equals(s)) + { + return true; + } + } + return false; + } + + private boolean allowed(final String name) + { + return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed); + } + + private boolean allowedAttribute(final String name, final String paramName) + { + return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName)); + } +} \ No newline at end of file diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java new file mode 100644 index 0000000..3fe178c --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java @@ -0,0 +1,55 @@ +package com.ruoyi.common.utils.http; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import javax.servlet.ServletRequest; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 通用http工具封装 + * + * @author #author# + */ +public class HttpHelper +{ + private static final Logger LOGGER = LoggerFactory.getLogger(HttpHelper.class); + + public static String getBodyString(ServletRequest request) + { + StringBuilder sb = new StringBuilder(); + BufferedReader reader = null; + try (InputStream inputStream = request.getInputStream()) + { + reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); + String line = ""; + while ((line = reader.readLine()) != null) + { + sb.append(line); + } + } + catch (IOException e) + { + LOGGER.warn("getBodyString出现问题!"); + } + finally + { + if (reader != null) + { + try + { + reader.close(); + } + catch (IOException e) + { + LOGGER.error(ExceptionUtils.getMessage(e)); + } + } + } + return sb.toString(); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java new file mode 100644 index 0000000..c1d5c11 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java @@ -0,0 +1,274 @@ +package com.ruoyi.common.utils.http; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.net.ConnectException; +import java.net.SocketTimeoutException; +import java.net.URL; +import java.net.URLConnection; +import java.nio.charset.StandardCharsets; +import java.security.cert.X509Certificate; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.utils.StringUtils; + +/** + * 通用http发送方法 + * + * @author #author# + */ +public class HttpUtils +{ + private static final Logger log = LoggerFactory.getLogger(HttpUtils.class); + + /** + * 向指定 URL 发送GET方法的请求 + * + * @param url 发送请求的 URL + * @return 所代表远程资源的响应结果 + */ + public static String sendGet(String url) + { + return sendGet(url, StringUtils.EMPTY); + } + + /** + * 向指定 URL 发送GET方法的请求 + * + * @param url 发送请求的 URL + * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 + * @return 所代表远程资源的响应结果 + */ + public static String sendGet(String url, String param) + { + return sendGet(url, param, Constants.UTF8); + } + + /** + * 向指定 URL 发送GET方法的请求 + * + * @param url 发送请求的 URL + * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 + * @param contentType 编码类型 + * @return 所代表远程资源的响应结果 + */ + public static String sendGet(String url, String param, String contentType) + { + StringBuilder result = new StringBuilder(); + BufferedReader in = null; + try + { + String urlNameString = StringUtils.isNotBlank(param) ? url + "?" + param : url; + log.info("sendGet - {}", urlNameString); + URL realUrl = new URL(urlNameString); + URLConnection connection = realUrl.openConnection(); + connection.setRequestProperty("accept", "*/*"); + connection.setRequestProperty("connection", "Keep-Alive"); + connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + connection.connect(); + in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType)); + String line; + while ((line = in.readLine()) != null) + { + result.append(line); + } + log.info("recv - {}", result); + } + catch (ConnectException e) + { + log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e); + } + catch (SocketTimeoutException e) + { + log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e); + } + catch (IOException e) + { + log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e); + } + catch (Exception e) + { + log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e); + } + finally + { + try + { + if (in != null) + { + in.close(); + } + } + catch (Exception ex) + { + log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); + } + } + return result.toString(); + } + + /** + * 向指定 URL 发送POST方法的请求 + * + * @param url 发送请求的 URL + * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 + * @return 所代表远程资源的响应结果 + */ + public static String sendPost(String url, String param) + { + PrintWriter out = null; + BufferedReader in = null; + StringBuilder result = new StringBuilder(); + try + { + log.info("sendPost - {}", url); + URL realUrl = new URL(url); + URLConnection conn = realUrl.openConnection(); + conn.setRequestProperty("accept", "*/*"); + conn.setRequestProperty("connection", "Keep-Alive"); + conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + conn.setRequestProperty("Accept-Charset", "utf-8"); + conn.setRequestProperty("contentType", "utf-8"); + conn.setDoOutput(true); + conn.setDoInput(true); + out = new PrintWriter(conn.getOutputStream()); + out.print(param); + out.flush(); + in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8)); + String line; + while ((line = in.readLine()) != null) + { + result.append(line); + } + log.info("recv - {}", result); + } + catch (ConnectException e) + { + log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e); + } + catch (SocketTimeoutException e) + { + log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e); + } + catch (IOException e) + { + log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e); + } + catch (Exception e) + { + log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e); + } + finally + { + try + { + if (out != null) + { + out.close(); + } + if (in != null) + { + in.close(); + } + } + catch (IOException ex) + { + log.error("调用in.close Exception, url=" + url + ",param=" + param, ex); + } + } + return result.toString(); + } + + public static String sendSSLPost(String url, String param) + { + StringBuilder result = new StringBuilder(); + String urlNameString = url + "?" + param; + try + { + log.info("sendSSLPost - {}", urlNameString); + SSLContext sc = SSLContext.getInstance("SSL"); + sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom()); + URL console = new URL(urlNameString); + HttpsURLConnection conn = (HttpsURLConnection) console.openConnection(); + conn.setRequestProperty("accept", "*/*"); + conn.setRequestProperty("connection", "Keep-Alive"); + conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + conn.setRequestProperty("Accept-Charset", "utf-8"); + conn.setRequestProperty("contentType", "utf-8"); + conn.setDoOutput(true); + conn.setDoInput(true); + + conn.setSSLSocketFactory(sc.getSocketFactory()); + conn.setHostnameVerifier(new TrustAnyHostnameVerifier()); + conn.connect(); + InputStream is = conn.getInputStream(); + BufferedReader br = new BufferedReader(new InputStreamReader(is)); + String ret = ""; + while ((ret = br.readLine()) != null) + { + if (ret != null && !"".equals(ret.trim())) + { + result.append(new String(ret.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8)); + } + } + log.info("recv - {}", result); + conn.disconnect(); + br.close(); + } + catch (ConnectException e) + { + log.error("调用HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e); + } + catch (SocketTimeoutException e) + { + log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e); + } + catch (IOException e) + { + log.error("调用HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e); + } + catch (Exception e) + { + log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e); + } + return result.toString(); + } + + private static class TrustAnyTrustManager implements X509TrustManager + { + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) + { + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) + { + } + + @Override + public X509Certificate[] getAcceptedIssuers() + { + return new X509Certificate[] {}; + } + } + + private static class TrustAnyHostnameVerifier implements HostnameVerifier + { + @Override + public boolean verify(String hostname, SSLSession session) + { + return true; + } + } +} \ No newline at end of file diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java new file mode 100644 index 0000000..f00b5c5 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java @@ -0,0 +1,56 @@ +package com.ruoyi.common.utils.ip; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.http.HttpUtils; + +/** + * 获取地址类 + * + * @author #author# + */ +public class AddressUtils +{ + private static final Logger log = LoggerFactory.getLogger(AddressUtils.class); + + // IP地址查询 + public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp"; + + // 未知地址 + public static final String UNKNOWN = "XX XX"; + + public static String getRealAddressByIP(String ip) + { + // 内网不查询 + if (IpUtils.internalIp(ip)) + { + return "内网IP"; + } + if (RuoYiConfig.isAddressEnabled()) + { + try + { + String rspStr = HttpUtils.sendGet(IP_URL, "ip=" + ip + "&json=true", Constants.GBK); + if (StringUtils.isEmpty(rspStr)) + { + log.error("获取地理位置异常 {}", ip); + return UNKNOWN; + } + JSONObject obj = JSON.parseObject(rspStr); + String region = obj.getString("pro"); + String city = obj.getString("city"); + return String.format("%s %s", region, city); + } + catch (Exception e) + { + log.error("获取地理位置异常 {}", ip); + } + } + return UNKNOWN; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java new file mode 100644 index 0000000..c4dd8fe --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java @@ -0,0 +1,264 @@ +package com.ruoyi.common.utils.ip; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import javax.servlet.http.HttpServletRequest; +import com.ruoyi.common.utils.StringUtils; + +/** + * 获取IP方法 + * + * @author #author# + */ +public class IpUtils +{ + /** + * 获取客户端IP + * + * @param request 请求对象 + * @return IP地址 + */ + public static String getIpAddr(HttpServletRequest request) + { + if (request == null) + { + return "unknown"; + } + String ip = request.getHeader("x-forwarded-for"); + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) + { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) + { + ip = request.getHeader("X-Forwarded-For"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) + { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) + { + ip = request.getHeader("X-Real-IP"); + } + + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) + { + ip = request.getRemoteAddr(); + } + + return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : getMultistageReverseProxyIp(ip); + } + + /** + * 检查是否为内部IP地址 + * + * @param ip IP地址 + * @return 结果 + */ + public static boolean internalIp(String ip) + { + byte[] addr = textToNumericFormatV4(ip); + return internalIp(addr) || "127.0.0.1".equals(ip); + } + + /** + * 检查是否为内部IP地址 + * + * @param addr byte地址 + * @return 结果 + */ + private static boolean internalIp(byte[] addr) + { + if (StringUtils.isNull(addr) || addr.length < 2) + { + return true; + } + final byte b0 = addr[0]; + final byte b1 = addr[1]; + // 10.x.x.x/8 + final byte SECTION_1 = 0x0A; + // 172.16.x.x/12 + final byte SECTION_2 = (byte) 0xAC; + final byte SECTION_3 = (byte) 0x10; + final byte SECTION_4 = (byte) 0x1F; + // 192.168.x.x/16 + final byte SECTION_5 = (byte) 0xC0; + final byte SECTION_6 = (byte) 0xA8; + switch (b0) + { + case SECTION_1: + return true; + case SECTION_2: + if (b1 >= SECTION_3 && b1 <= SECTION_4) + { + return true; + } + case SECTION_5: + switch (b1) + { + case SECTION_6: + return true; + } + default: + return false; + } + } + + /** + * 将IPv4地址转换成字节 + * + * @param text IPv4地址 + * @return byte 字节 + */ + public static byte[] textToNumericFormatV4(String text) + { + if (text.length() == 0) + { + return null; + } + + byte[] bytes = new byte[4]; + String[] elements = text.split("\\.", -1); + try + { + long l; + int i; + switch (elements.length) + { + case 1: + l = Long.parseLong(elements[0]); + if ((l < 0L) || (l > 4294967295L)) + { + return null; + } + bytes[0] = (byte) (int) (l >> 24 & 0xFF); + bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF); + bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); + bytes[3] = (byte) (int) (l & 0xFF); + break; + case 2: + l = Integer.parseInt(elements[0]); + if ((l < 0L) || (l > 255L)) + { + return null; + } + bytes[0] = (byte) (int) (l & 0xFF); + l = Integer.parseInt(elements[1]); + if ((l < 0L) || (l > 16777215L)) + { + return null; + } + bytes[1] = (byte) (int) (l >> 16 & 0xFF); + bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); + bytes[3] = (byte) (int) (l & 0xFF); + break; + case 3: + for (i = 0; i < 2; ++i) + { + l = Integer.parseInt(elements[i]); + if ((l < 0L) || (l > 255L)) + { + return null; + } + bytes[i] = (byte) (int) (l & 0xFF); + } + l = Integer.parseInt(elements[2]); + if ((l < 0L) || (l > 65535L)) + { + return null; + } + bytes[2] = (byte) (int) (l >> 8 & 0xFF); + bytes[3] = (byte) (int) (l & 0xFF); + break; + case 4: + for (i = 0; i < 4; ++i) + { + l = Integer.parseInt(elements[i]); + if ((l < 0L) || (l > 255L)) + { + return null; + } + bytes[i] = (byte) (int) (l & 0xFF); + } + break; + default: + return null; + } + } + catch (NumberFormatException e) + { + return null; + } + return bytes; + } + + /** + * 获取IP地址 + * + * @return 本地IP地址 + */ + public static String getHostIp() + { + try + { + return InetAddress.getLocalHost().getHostAddress(); + } + catch (UnknownHostException e) + { + } + return "127.0.0.1"; + } + + /** + * 获取主机名 + * + * @return 本地主机名 + */ + public static String getHostName() + { + try + { + return InetAddress.getLocalHost().getHostName(); + } + catch (UnknownHostException e) + { + } + return "未知"; + } + + /** + * 从多级反向代理中获得第一个非unknown IP地址 + * + * @param ip 获得的IP地址 + * @return 第一个非unknown IP地址 + */ + public static String getMultistageReverseProxyIp(String ip) + { + // 多级反向代理检测 + if (ip != null && ip.indexOf(",") > 0) + { + final String[] ips = ip.trim().split(","); + for (String subIp : ips) + { + if (false == isUnknown(subIp)) + { + ip = subIp; + break; + } + } + } + return ip; + } + + /** + * 检测给定字符串是否为未知,多用于检测HTTP请求相关 + * + * @param checkString 被检测的字符串 + * @return 是否未知 + */ + public static boolean isUnknown(String checkString) + { + return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString); + } +} \ No newline at end of file diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelHandlerAdapter.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelHandlerAdapter.java new file mode 100644 index 0000000..a402370 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelHandlerAdapter.java @@ -0,0 +1,19 @@ +package com.ruoyi.common.utils.poi; + +/** + * Excel数据格式处理适配器 + * + * @author #author# + */ +public interface ExcelHandlerAdapter +{ + /** + * 格式化 + * + * @param value 单元格数据值 + * @param args excel注解args参数组 + * + * @return 处理后的值 + */ + Object format(Object value, String[] args); +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java new file mode 100644 index 0000000..69c5758 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java @@ -0,0 +1,1734 @@ +package com.ruoyi.common.utils.poi; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.math.BigDecimal; +import java.text.DecimalFormat; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Comparator; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; +import javax.servlet.http.HttpServletResponse; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.RegExUtils; +import org.apache.commons.lang3.reflect.FieldUtils; +import org.apache.poi.hssf.usermodel.HSSFClientAnchor; +import org.apache.poi.hssf.usermodel.HSSFPicture; +import org.apache.poi.hssf.usermodel.HSSFPictureData; +import org.apache.poi.hssf.usermodel.HSSFShape; +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.ooxml.POIXMLDocumentPart; +import org.apache.poi.ss.usermodel.BorderStyle; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.ClientAnchor; +import org.apache.poi.ss.usermodel.DataValidation; +import org.apache.poi.ss.usermodel.DataValidationConstraint; +import org.apache.poi.ss.usermodel.DataValidationHelper; +import org.apache.poi.ss.usermodel.DateUtil; +import org.apache.poi.ss.usermodel.Drawing; +import org.apache.poi.ss.usermodel.FillPatternType; +import org.apache.poi.ss.usermodel.Font; +import org.apache.poi.ss.usermodel.HorizontalAlignment; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.poi.ss.usermodel.Name; +import org.apache.poi.ss.usermodel.PictureData; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.VerticalAlignment; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.usermodel.WorkbookFactory; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.ss.util.CellRangeAddressList; +import org.apache.poi.util.IOUtils; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; +import org.apache.poi.xssf.usermodel.XSSFClientAnchor; +import org.apache.poi.xssf.usermodel.XSSFDataValidation; +import org.apache.poi.xssf.usermodel.XSSFDrawing; +import org.apache.poi.xssf.usermodel.XSSFPicture; +import org.apache.poi.xssf.usermodel.XSSFShape; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; +import com.ruoyi.common.annotation.Excel.Type; +import com.ruoyi.common.annotation.Excels; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.text.Convert; +import com.ruoyi.common.exception.UtilException; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.DictUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.file.FileTypeUtils; +import com.ruoyi.common.utils.file.FileUtils; +import com.ruoyi.common.utils.file.ImageUtils; +import com.ruoyi.common.utils.reflect.ReflectUtils; + +/** + * Excel相关处理 + * + * @author #author# + */ +public class ExcelUtil +{ + private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class); + + public static final String FORMULA_REGEX_STR = "=|-|\\+|@"; + + public static final String[] FORMULA_STR = { "=", "-", "+", "@" }; + + /** + * Excel sheet最大行数,默认65536 + */ + public static final int sheetSize = 65536; + + /** + * 工作表名称 + */ + private String sheetName; + + /** + * 导出类型(EXPORT:导出数据;IMPORT:导入模板) + */ + private Type type; + + /** + * 工作薄对象 + */ + private Workbook wb; + + /** + * 工作表对象 + */ + private Sheet sheet; + + /** + * 样式列表 + */ + private Map styles; + + /** + * 导入导出数据列表 + */ + private List list; + + /** + * 注解列表 + */ + private List fields; + + /** + * 当前行号 + */ + private int rownum; + + /** + * 标题 + */ + private String title; + + /** + * 最大高度 + */ + private short maxHeight; + + /** + * 合并后最后行数 + */ + private int subMergedLastRowNum = 0; + + /** + * 合并后开始行数 + */ + private int subMergedFirstRowNum = 1; + + /** + * 对象的子列表方法 + */ + private Method subMethod; + + /** + * 对象的子列表属性 + */ + private List subFields; + + /** + * 统计列表 + */ + private Map statistics = new HashMap(); + + /** + * 数字格式 + */ + private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00"); + + /** + * 实体对象 + */ + public Class clazz; + + /** + * 需要排除列属性 + */ + public String[] excludeFields; + + public ExcelUtil(Class clazz) + { + this.clazz = clazz; + } + + /** + * 隐藏Excel中列属性 + * + * @param fields 列属性名 示例[单个"name"/多个"id","name"] + * @throws Exception + */ + public void hideColumn(String... fields) + { + this.excludeFields = fields; + } + + public void init(List list, String sheetName, String title, Type type) + { + if (list == null) + { + list = new ArrayList(); + } + this.list = list; + this.sheetName = sheetName; + this.type = type; + this.title = title; + createExcelField(); + createWorkbook(); + createTitle(); + createSubHead(); + } + + /** + * 创建excel第一行标题 + */ + public void createTitle() + { + if (StringUtils.isNotEmpty(title)) + { + subMergedFirstRowNum++; + subMergedLastRowNum++; + int titleLastCol = this.fields.size() - 1; + if (isSubList()) + { + titleLastCol = titleLastCol + subFields.size() - 1; + } + Row titleRow = sheet.createRow(rownum == 0 ? rownum++ : 0); + titleRow.setHeightInPoints(30); + Cell titleCell = titleRow.createCell(0); + titleCell.setCellStyle(styles.get("title")); + titleCell.setCellValue(title); + sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), titleRow.getRowNum(), titleLastCol)); + } + } + + /** + * 创建对象的子列表名称 + */ + public void createSubHead() + { + if (isSubList()) + { + subMergedFirstRowNum++; + subMergedLastRowNum++; + Row subRow = sheet.createRow(rownum); + int excelNum = 0; + for (Object[] objects : fields) + { + Excel attr = (Excel) objects[1]; + Cell headCell1 = subRow.createCell(excelNum); + headCell1.setCellValue(attr.name()); + headCell1.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor()))); + excelNum++; + } + int headFirstRow = excelNum - 1; + int headLastRow = headFirstRow + subFields.size() - 1; + if (headLastRow > headFirstRow) + { + sheet.addMergedRegion(new CellRangeAddress(rownum, rownum, headFirstRow, headLastRow)); + } + rownum++; + } + } + + /** + * 对excel表单默认第一个索引名转换成list + * + * @param is 输入流 + * @return 转换后集合 + */ + public List importExcel(InputStream is) throws Exception + { + return importExcel(is, 0); + } + + /** + * 对excel表单默认第一个索引名转换成list + * + * @param is 输入流 + * @param titleNum 标题占用行数 + * @return 转换后集合 + */ + public List importExcel(InputStream is, int titleNum) throws Exception + { + return importExcel(StringUtils.EMPTY, is, titleNum); + } + + /** + * 对excel表单指定表格索引名转换成list + * + * @param sheetName 表格索引名 + * @param titleNum 标题占用行数 + * @param is 输入流 + * @return 转换后集合 + */ + public List importExcel(String sheetName, InputStream is, int titleNum) throws Exception + { + this.type = Type.IMPORT; + this.wb = WorkbookFactory.create(is); + List list = new ArrayList(); + // 如果指定sheet名,则取指定sheet中的内容 否则默认指向第1个sheet + Sheet sheet = StringUtils.isNotEmpty(sheetName) ? wb.getSheet(sheetName) : wb.getSheetAt(0); + if (sheet == null) + { + throw new IOException("文件sheet不存在"); + } + boolean isXSSFWorkbook = !(wb instanceof HSSFWorkbook); + Map pictures; + if (isXSSFWorkbook) + { + pictures = getSheetPictures07((XSSFSheet) sheet, (XSSFWorkbook) wb); + } + else + { + pictures = getSheetPictures03((HSSFSheet) sheet, (HSSFWorkbook) wb); + } + // 获取最后一个非空行的行下标,比如总行数为n,则返回的为n-1 + int rows = sheet.getLastRowNum(); + + if (rows > 0) + { + // 定义一个map用于存放excel列的序号和field. + Map cellMap = new HashMap(); + // 获取表头 + Row heard = sheet.getRow(titleNum); + for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++) + { + Cell cell = heard.getCell(i); + if (StringUtils.isNotNull(cell)) + { + String value = this.getCellValue(heard, i).toString(); + cellMap.put(value, i); + } + else + { + cellMap.put(null, i); + } + } + // 有数据时才处理 得到类的所有field. + List fields = this.getFields(); + Map fieldsMap = new HashMap(); + for (Object[] objects : fields) + { + Excel attr = (Excel) objects[1]; + Integer column = cellMap.get(attr.name()); + if (column != null) + { + fieldsMap.put(column, objects); + } + } + for (int i = titleNum + 1; i <= rows; i++) + { + // 从第2行开始取数据,默认第一行是表头. + Row row = sheet.getRow(i); + // 判断当前行是否是空行 + if (isRowEmpty(row)) + { + continue; + } + T entity = null; + for (Map.Entry entry : fieldsMap.entrySet()) + { + Object val = this.getCellValue(row, entry.getKey()); + + // 如果不存在实例则新建. + entity = (entity == null ? clazz.newInstance() : entity); + // 从map中得到对应列的field. + Field field = (Field) entry.getValue()[0]; + Excel attr = (Excel) entry.getValue()[1]; + // 取得类型,并根据对象类型设置值. + Class fieldType = field.getType(); + if (String.class == fieldType) + { + String s = Convert.toStr(val); + if (StringUtils.endsWith(s, ".0")) + { + val = StringUtils.substringBefore(s, ".0"); + } + else + { + String dateFormat = field.getAnnotation(Excel.class).dateFormat(); + if (StringUtils.isNotEmpty(dateFormat)) + { + val = parseDateToStr(dateFormat, val); + } + else + { + val = Convert.toStr(val); + } + } + } + else if ((Integer.TYPE == fieldType || Integer.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val))) + { + val = Convert.toInt(val); + } + else if ((Long.TYPE == fieldType || Long.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val))) + { + val = Convert.toLong(val); + } + else if (Double.TYPE == fieldType || Double.class == fieldType) + { + val = Convert.toDouble(val); + } + else if (Float.TYPE == fieldType || Float.class == fieldType) + { + val = Convert.toFloat(val); + } + else if (BigDecimal.class == fieldType) + { + val = Convert.toBigDecimal(val); + } + else if (Date.class == fieldType) + { + if (val instanceof String) + { + val = DateUtils.parseDate(val); + } + else if (val instanceof Double) + { + val = DateUtil.getJavaDate((Double) val); + } + } + else if (Boolean.TYPE == fieldType || Boolean.class == fieldType) + { + val = Convert.toBool(val, false); + } + if (StringUtils.isNotNull(fieldType)) + { + String propertyName = field.getName(); + if (StringUtils.isNotEmpty(attr.targetAttr())) + { + propertyName = field.getName() + "." + attr.targetAttr(); + } + else if (StringUtils.isNotEmpty(attr.readConverterExp())) + { + val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator()); + } + else if (StringUtils.isNotEmpty(attr.dictType())) + { + val = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator()); + } + else if (!attr.handler().equals(ExcelHandlerAdapter.class)) + { + val = dataFormatHandlerAdapter(val, attr); + } + else if (ColumnType.IMAGE == attr.cellType() && StringUtils.isNotEmpty(pictures)) + { + PictureData image = pictures.get(row.getRowNum() + "_" + entry.getKey()); + if (image == null) + { + val = ""; + } + else + { + byte[] data = image.getData(); + val = FileUtils.writeImportBytes(data); + } + } + ReflectUtils.invokeSetter(entity, propertyName, val); + } + } + list.add(entity); + } + } + return list; + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @param list 导出数据集合 + * @param sheetName 工作表的名称 + * @return 结果 + */ + public AjaxResult exportExcel(List list, String sheetName) + { + return exportExcel(list, sheetName, StringUtils.EMPTY); + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @param list 导出数据集合 + * @param sheetName 工作表的名称 + * @param title 标题 + * @return 结果 + */ + public AjaxResult exportExcel(List list, String sheetName, String title) + { + this.init(list, sheetName, title, Type.EXPORT); + return exportExcel(); + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @param response 返回数据 + * @param list 导出数据集合 + * @param sheetName 工作表的名称 + * @return 结果 + */ + public void exportExcel(HttpServletResponse response, List list, String sheetName) + { + exportExcel(response, list, sheetName, StringUtils.EMPTY); + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @param response 返回数据 + * @param list 导出数据集合 + * @param sheetName 工作表的名称 + * @param title 标题 + * @return 结果 + */ + public void exportExcel(HttpServletResponse response, List list, String sheetName, String title) + { + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setCharacterEncoding("utf-8"); + this.init(list, sheetName, title, Type.EXPORT); + exportExcel(response); + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @param sheetName 工作表的名称 + * @return 结果 + */ + public AjaxResult importTemplateExcel(String sheetName) + { + return importTemplateExcel(sheetName, StringUtils.EMPTY); + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @param sheetName 工作表的名称 + * @param title 标题 + * @return 结果 + */ + public AjaxResult importTemplateExcel(String sheetName, String title) + { + this.init(null, sheetName, title, Type.IMPORT); + return exportExcel(); + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @param sheetName 工作表的名称 + * @return 结果 + */ + public void importTemplateExcel(HttpServletResponse response, String sheetName) + { + importTemplateExcel(response, sheetName, StringUtils.EMPTY); + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @param sheetName 工作表的名称 + * @param title 标题 + * @return 结果 + */ + public void importTemplateExcel(HttpServletResponse response, String sheetName, String title) + { + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setCharacterEncoding("utf-8"); + this.init(null, sheetName, title, Type.IMPORT); + exportExcel(response); + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @return 结果 + */ + public void exportExcel(HttpServletResponse response) + { + try + { + writeSheet(); + wb.write(response.getOutputStream()); + } + catch (Exception e) + { + log.error("导出Excel异常{}", e.getMessage()); + } + finally + { + IOUtils.closeQuietly(wb); + } + } + + /** + * 对list数据源将其里面的数据导入到excel表单 + * + * @return 结果 + */ + public AjaxResult exportExcel() + { + OutputStream out = null; + try + { + writeSheet(); + String filename = encodingFilename(sheetName); + out = new FileOutputStream(getAbsoluteFile(filename)); + wb.write(out); + return AjaxResult.success(filename); + } + catch (Exception e) + { + log.error("导出Excel异常{}", e.getMessage()); + throw new UtilException("导出Excel失败,请联系网站管理员!"); + } + finally + { + IOUtils.closeQuietly(wb); + IOUtils.closeQuietly(out); + } + } + + /** + * 创建写入数据到Sheet + */ + public void writeSheet() + { + // 取出一共有多少个sheet. + int sheetNo = Math.max(1, (int) Math.ceil(list.size() * 1.0 / sheetSize)); + for (int index = 0; index < sheetNo; index++) + { + createSheet(sheetNo, index); + + // 产生一行 + Row row = sheet.createRow(rownum); + int column = 0; + // 写入各个字段的列头名称 + for (Object[] os : fields) + { + Field field = (Field) os[0]; + Excel excel = (Excel) os[1]; + if (Collection.class.isAssignableFrom(field.getType())) + { + for (Field subField : subFields) + { + Excel subExcel = subField.getAnnotation(Excel.class); + this.createHeadCell(subExcel, row, column++); + } + } + else + { + this.createHeadCell(excel, row, column++); + } + } + if (Type.EXPORT.equals(type)) + { + fillExcelData(index, row); + addStatisticsRow(); + } + } + } + + /** + * 填充excel数据 + * + * @param index 序号 + * @param row 单元格行 + */ + @SuppressWarnings("unchecked") + public void fillExcelData(int index, Row row) + { + int startNo = index * sheetSize; + int endNo = Math.min(startNo + sheetSize, list.size()); + int rowNo = (1 + rownum) - startNo; + for (int i = startNo; i < endNo; i++) + { + rowNo = isSubList() ? (i > 1 ? rowNo + 1 : rowNo + i) : i + 1 + rownum - startNo; + row = sheet.createRow(rowNo); + // 得到导出对象. + T vo = (T) list.get(i); + Collection subList = null; + if (isSubList()) + { + if (isSubListValue(vo)) + { + subList = getListCellValue(vo); + subMergedLastRowNum = subMergedLastRowNum + subList.size(); + } + else + { + subMergedFirstRowNum++; + subMergedLastRowNum++; + } + } + int column = 0; + for (Object[] os : fields) + { + Field field = (Field) os[0]; + Excel excel = (Excel) os[1]; + if (Collection.class.isAssignableFrom(field.getType()) && StringUtils.isNotNull(subList)) + { + boolean subFirst = false; + for (Object obj : subList) + { + if (subFirst) + { + rowNo++; + row = sheet.createRow(rowNo); + } + List subFields = FieldUtils.getFieldsListWithAnnotation(obj.getClass(), Excel.class); + int subIndex = 0; + for (Field subField : subFields) + { + if (subField.isAnnotationPresent(Excel.class)) + { + subField.setAccessible(true); + Excel attr = subField.getAnnotation(Excel.class); + this.addCell(attr, row, (T) obj, subField, column + subIndex); + } + subIndex++; + } + subFirst = true; + } + this.subMergedFirstRowNum = this.subMergedFirstRowNum + subList.size(); + } + else + { + this.addCell(excel, row, vo, field, column++); + } + } + } + } + + /** + * 创建表格样式 + * + * @param wb 工作薄对象 + * @return 样式列表 + */ + private Map createStyles(Workbook wb) + { + // 写入各条记录,每条记录对应excel表中的一行 + Map styles = new HashMap(); + CellStyle style = wb.createCellStyle(); + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + Font titleFont = wb.createFont(); + titleFont.setFontName("Arial"); + titleFont.setFontHeightInPoints((short) 16); + titleFont.setBold(true); + style.setFont(titleFont); + styles.put("title", style); + + style = wb.createCellStyle(); + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + style.setBorderRight(BorderStyle.THIN); + style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderLeft(BorderStyle.THIN); + style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderTop(BorderStyle.THIN); + style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderBottom(BorderStyle.THIN); + style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + Font dataFont = wb.createFont(); + dataFont.setFontName("Arial"); + dataFont.setFontHeightInPoints((short) 10); + style.setFont(dataFont); + styles.put("data", style); + + style = wb.createCellStyle(); + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + Font totalFont = wb.createFont(); + totalFont.setFontName("Arial"); + totalFont.setFontHeightInPoints((short) 10); + style.setFont(totalFont); + styles.put("total", style); + + styles.putAll(annotationHeaderStyles(wb, styles)); + + styles.putAll(annotationDataStyles(wb)); + + return styles; + } + + /** + * 根据Excel注解创建表格头样式 + * + * @param wb 工作薄对象 + * @return 自定义样式列表 + */ + private Map annotationHeaderStyles(Workbook wb, Map styles) + { + Map headerStyles = new HashMap(); + for (Object[] os : fields) + { + Excel excel = (Excel) os[1]; + String key = StringUtils.format("header_{}_{}", excel.headerColor(), excel.headerBackgroundColor()); + if (!headerStyles.containsKey(key)) + { + CellStyle style = wb.createCellStyle(); + style.cloneStyleFrom(styles.get("data")); + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + style.setFillForegroundColor(excel.headerBackgroundColor().index); + style.setFillPattern(FillPatternType.SOLID_FOREGROUND); + Font headerFont = wb.createFont(); + headerFont.setFontName("Arial"); + headerFont.setFontHeightInPoints((short) 10); + headerFont.setBold(true); + headerFont.setColor(excel.headerColor().index); + style.setFont(headerFont); + headerStyles.put(key, style); + } + } + return headerStyles; + } + + /** + * 根据Excel注解创建表格列样式 + * + * @param wb 工作薄对象 + * @return 自定义样式列表 + */ + private Map annotationDataStyles(Workbook wb) + { + Map styles = new HashMap(); + for (Object[] os : fields) + { + Excel excel = (Excel) os[1]; + String key = StringUtils.format("data_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor()); + if (!styles.containsKey(key)) + { + CellStyle style = wb.createCellStyle(); + style.setAlignment(excel.align()); + style.setVerticalAlignment(VerticalAlignment.CENTER); + style.setBorderRight(BorderStyle.THIN); + style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderLeft(BorderStyle.THIN); + style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderTop(BorderStyle.THIN); + style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderBottom(BorderStyle.THIN); + style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setFillPattern(FillPatternType.SOLID_FOREGROUND); + style.setFillForegroundColor(excel.backgroundColor().getIndex()); + Font dataFont = wb.createFont(); + dataFont.setFontName("Arial"); + dataFont.setFontHeightInPoints((short) 10); + dataFont.setColor(excel.color().index); + style.setFont(dataFont); + styles.put(key, style); + } + } + return styles; + } + + /** + * 创建单元格 + */ + public Cell createHeadCell(Excel attr, Row row, int column) + { + // 创建列 + Cell cell = row.createCell(column); + // 写入列信息 + cell.setCellValue(attr.name()); + setDataValidation(attr, row, column); + cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor()))); + if (isSubList()) + { + // 填充默认样式,防止合并单元格样式失效 + sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor()))); + if (attr.needMerge()) + { + sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column)); + } + } + return cell; + } + + /** + * 设置单元格信息 + * + * @param value 单元格值 + * @param attr 注解相关 + * @param cell 单元格信息 + */ + public void setCellVo(Object value, Excel attr, Cell cell) + { + if (ColumnType.STRING == attr.cellType()) + { + String cellValue = Convert.toStr(value); + // 对于任何以表达式触发字符 =-+@开头的单元格,直接使用tab字符作为前缀,防止CSV注入。 + if (StringUtils.startsWithAny(cellValue, FORMULA_STR)) + { + cellValue = RegExUtils.replaceFirst(cellValue, FORMULA_REGEX_STR, "\t$0"); + } + if (value instanceof Collection && StringUtils.equals("[]", cellValue)) + { + cellValue = StringUtils.EMPTY; + } + cell.setCellValue(StringUtils.isNull(cellValue) ? attr.defaultValue() : cellValue + attr.suffix()); + } + else if (ColumnType.NUMERIC == attr.cellType()) + { + if (StringUtils.isNotNull(value)) + { + cell.setCellValue(StringUtils.contains(Convert.toStr(value), ".") ? Convert.toDouble(value) : Convert.toInt(value)); + } + } + else if (ColumnType.IMAGE == attr.cellType()) + { + ClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1), cell.getRow().getRowNum() + 1); + String imagePath = Convert.toStr(value); + if (StringUtils.isNotEmpty(imagePath)) + { + byte[] data = ImageUtils.getImage(imagePath); + getDrawingPatriarch(cell.getSheet()).createPicture(anchor, + cell.getSheet().getWorkbook().addPicture(data, getImageType(data))); + } + } + } + + /** + * 获取画布 + */ + public static Drawing getDrawingPatriarch(Sheet sheet) + { + if (sheet.getDrawingPatriarch() == null) + { + sheet.createDrawingPatriarch(); + } + return sheet.getDrawingPatriarch(); + } + + /** + * 获取图片类型,设置图片插入类型 + */ + public int getImageType(byte[] value) + { + String type = FileTypeUtils.getFileExtendName(value); + if ("JPG".equalsIgnoreCase(type)) + { + return Workbook.PICTURE_TYPE_JPEG; + } + else if ("PNG".equalsIgnoreCase(type)) + { + return Workbook.PICTURE_TYPE_PNG; + } + return Workbook.PICTURE_TYPE_JPEG; + } + + /** + * 创建表格样式 + */ + public void setDataValidation(Excel attr, Row row, int column) + { + if (attr.name().indexOf("注:") >= 0) + { + sheet.setColumnWidth(column, 6000); + } + else + { + // 设置列宽 + sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256)); + } + if (StringUtils.isNotEmpty(attr.prompt()) || attr.combo().length > 0) + { + if (attr.combo().length > 15 || StringUtils.join(attr.combo()).length() > 255) + { + // 如果下拉数大于15或字符串长度大于255,则使用一个新sheet存储,避免生成的模板下拉值获取不到 + setXSSFValidationWithHidden(sheet, attr.combo(), attr.prompt(), 1, 100, column, column); + } + else + { + // 提示信息或只能选择不能输入的列内容. + setPromptOrValidation(sheet, attr.combo(), attr.prompt(), 1, 100, column, column); + } + } + } + + /** + * 添加单元格 + */ + public Cell addCell(Excel attr, Row row, T vo, Field field, int column) + { + Cell cell = null; + try + { + // 设置行高 + row.setHeight(maxHeight); + // 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列. + if (attr.isExport()) + { + // 创建cell + cell = row.createCell(column); + if (isSubListValue(vo) && getListCellValue(vo).size() > 1 && attr.needMerge()) + { + CellRangeAddress cellAddress = new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column); + sheet.addMergedRegion(cellAddress); + } + cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor()))); + + // 用于读取对象中的属性 + Object value = getTargetValue(vo, field, attr); + String dateFormat = attr.dateFormat(); + String readConverterExp = attr.readConverterExp(); + String separator = attr.separator(); + String dictType = attr.dictType(); + if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value)) + { + cell.setCellValue(parseDateToStr(dateFormat, value)); + } + else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value)) + { + cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator)); + } + else if (StringUtils.isNotEmpty(dictType) && StringUtils.isNotNull(value)) + { + cell.setCellValue(convertDictByExp(Convert.toStr(value), dictType, separator)); + } + else if (value instanceof BigDecimal && -1 != attr.scale()) + { + cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).doubleValue()); + } + else if (!attr.handler().equals(ExcelHandlerAdapter.class)) + { + cell.setCellValue(dataFormatHandlerAdapter(value, attr)); + } + else + { + // 设置列类型 + setCellVo(value, attr, cell); + } + addStatisticsData(column, Convert.toStr(value), attr); + } + } + catch (Exception e) + { + log.error("导出Excel失败{}", e); + } + return cell; + } + + /** + * 设置 POI XSSFSheet 单元格提示或选择框 + * + * @param sheet 表单 + * @param textlist 下拉框显示的内容 + * @param promptContent 提示内容 + * @param firstRow 开始行 + * @param endRow 结束行 + * @param firstCol 开始列 + * @param endCol 结束列 + */ + public void setPromptOrValidation(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, + int firstCol, int endCol) + { + DataValidationHelper helper = sheet.getDataValidationHelper(); + DataValidationConstraint constraint = textlist.length > 0 ? helper.createExplicitListConstraint(textlist) : helper.createCustomConstraint("DD1"); + CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); + DataValidation dataValidation = helper.createValidation(constraint, regions); + if (StringUtils.isNotEmpty(promptContent)) + { + // 如果设置了提示信息则鼠标放上去提示 + dataValidation.createPromptBox("", promptContent); + dataValidation.setShowPromptBox(true); + } + // 处理Excel兼容性问题 + if (dataValidation instanceof XSSFDataValidation) + { + dataValidation.setSuppressDropDownArrow(true); + dataValidation.setShowErrorBox(true); + } + else + { + dataValidation.setSuppressDropDownArrow(false); + } + sheet.addValidationData(dataValidation); + } + + /** + * 设置某些列的值只能输入预制的数据,显示下拉框(兼容超出一定数量的下拉框). + * + * @param sheet 要设置的sheet. + * @param textlist 下拉框显示的内容 + * @param promptContent 提示内容 + * @param firstRow 开始行 + * @param endRow 结束行 + * @param firstCol 开始列 + * @param endCol 结束列 + */ + public void setXSSFValidationWithHidden(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, int firstCol, int endCol) + { + String hideSheetName = "combo_" + firstCol + "_" + endCol; + Sheet hideSheet = wb.createSheet(hideSheetName); // 用于存储 下拉菜单数据 + for (int i = 0; i < textlist.length; i++) + { + hideSheet.createRow(i).createCell(0).setCellValue(textlist[i]); + } + // 创建名称,可被其他单元格引用 + Name name = wb.createName(); + name.setNameName(hideSheetName + "_data"); + name.setRefersToFormula(hideSheetName + "!$A$1:$A$" + textlist.length); + DataValidationHelper helper = sheet.getDataValidationHelper(); + // 加载下拉列表内容 + DataValidationConstraint constraint = helper.createFormulaListConstraint(hideSheetName + "_data"); + // 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列 + CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol); + // 数据有效性对象 + DataValidation dataValidation = helper.createValidation(constraint, regions); + if (StringUtils.isNotEmpty(promptContent)) + { + // 如果设置了提示信息则鼠标放上去提示 + dataValidation.createPromptBox("", promptContent); + dataValidation.setShowPromptBox(true); + } + // 处理Excel兼容性问题 + if (dataValidation instanceof XSSFDataValidation) + { + dataValidation.setSuppressDropDownArrow(true); + dataValidation.setShowErrorBox(true); + } + else + { + dataValidation.setSuppressDropDownArrow(false); + } + + sheet.addValidationData(dataValidation); + // 设置hiddenSheet隐藏 + wb.setSheetHidden(wb.getSheetIndex(hideSheet), true); + } + + /** + * 解析导出值 0=男,1=女,2=未知 + * + * @param propertyValue 参数值 + * @param converterExp 翻译注解 + * @param separator 分隔符 + * @return 解析后值 + */ + public static String convertByExp(String propertyValue, String converterExp, String separator) + { + StringBuilder propertyString = new StringBuilder(); + String[] convertSource = converterExp.split(","); + for (String item : convertSource) + { + String[] itemArray = item.split("="); + if (StringUtils.containsAny(propertyValue, separator)) + { + for (String value : propertyValue.split(separator)) + { + if (itemArray[0].equals(value)) + { + propertyString.append(itemArray[1] + separator); + break; + } + } + } + else + { + if (itemArray[0].equals(propertyValue)) + { + return itemArray[1]; + } + } + } + return StringUtils.stripEnd(propertyString.toString(), separator); + } + + /** + * 反向解析值 男=0,女=1,未知=2 + * + * @param propertyValue 参数值 + * @param converterExp 翻译注解 + * @param separator 分隔符 + * @return 解析后值 + */ + public static String reverseByExp(String propertyValue, String converterExp, String separator) + { + StringBuilder propertyString = new StringBuilder(); + String[] convertSource = converterExp.split(","); + for (String item : convertSource) + { + String[] itemArray = item.split("="); + if (StringUtils.containsAny(propertyValue, separator)) + { + for (String value : propertyValue.split(separator)) + { + if (itemArray[1].equals(value)) + { + propertyString.append(itemArray[0] + separator); + break; + } + } + } + else + { + if (itemArray[1].equals(propertyValue)) + { + return itemArray[0]; + } + } + } + return StringUtils.stripEnd(propertyString.toString(), separator); + } + + /** + * 解析字典值 + * + * @param dictValue 字典值 + * @param dictType 字典类型 + * @param separator 分隔符 + * @return 字典标签 + */ + public static String convertDictByExp(String dictValue, String dictType, String separator) + { + return DictUtils.getDictLabel(dictType, dictValue, separator); + } + + /** + * 反向解析值字典值 + * + * @param dictLabel 字典标签 + * @param dictType 字典类型 + * @param separator 分隔符 + * @return 字典值 + */ + public static String reverseDictByExp(String dictLabel, String dictType, String separator) + { + return DictUtils.getDictValue(dictType, dictLabel, separator); + } + + /** + * 数据处理器 + * + * @param value 数据值 + * @param excel 数据注解 + * @return + */ + public String dataFormatHandlerAdapter(Object value, Excel excel) + { + try + { + Object instance = excel.handler().newInstance(); + Method formatMethod = excel.handler().getMethod("format", new Class[] { Object.class, String[].class }); + value = formatMethod.invoke(instance, value, excel.args()); + } + catch (Exception e) + { + log.error("不能格式化数据 " + excel.handler(), e.getMessage()); + } + return Convert.toStr(value); + } + + /** + * 合计统计信息 + */ + private void addStatisticsData(Integer index, String text, Excel entity) + { + if (entity != null && entity.isStatistics()) + { + Double temp = 0D; + if (!statistics.containsKey(index)) + { + statistics.put(index, temp); + } + try + { + temp = Double.valueOf(text); + } + catch (NumberFormatException e) + { + } + statistics.put(index, statistics.get(index) + temp); + } + } + + /** + * 创建统计行 + */ + public void addStatisticsRow() + { + if (statistics.size() > 0) + { + Row row = sheet.createRow(sheet.getLastRowNum() + 1); + Set keys = statistics.keySet(); + Cell cell = row.createCell(0); + cell.setCellStyle(styles.get("total")); + cell.setCellValue("合计"); + + for (Integer key : keys) + { + cell = row.createCell(key); + cell.setCellStyle(styles.get("total")); + cell.setCellValue(DOUBLE_FORMAT.format(statistics.get(key))); + } + statistics.clear(); + } + } + + /** + * 编码文件名 + */ + public String encodingFilename(String filename) + { + filename = UUID.randomUUID().toString() + "_" + filename + ".xlsx"; + return filename; + } + + /** + * 获取下载路径 + * + * @param filename 文件名称 + */ + public String getAbsoluteFile(String filename) + { + String downloadPath = RuoYiConfig.getDownloadPath() + filename; + File desc = new File(downloadPath); + if (!desc.getParentFile().exists()) + { + desc.getParentFile().mkdirs(); + } + return downloadPath; + } + + /** + * 获取bean中的属性值 + * + * @param vo 实体对象 + * @param field 字段 + * @param excel 注解 + * @return 最终的属性值 + * @throws Exception + */ + private Object getTargetValue(T vo, Field field, Excel excel) throws Exception + { + Object o = field.get(vo); + if (StringUtils.isNotEmpty(excel.targetAttr())) + { + String target = excel.targetAttr(); + if (target.contains(".")) + { + String[] targets = target.split("[.]"); + for (String name : targets) + { + o = getValue(o, name); + } + } + else + { + o = getValue(o, target); + } + } + return o; + } + + /** + * 以类的属性的get方法方法形式获取值 + * + * @param o + * @param name + * @return value + * @throws Exception + */ + private Object getValue(Object o, String name) throws Exception + { + if (StringUtils.isNotNull(o) && StringUtils.isNotEmpty(name)) + { + Class clazz = o.getClass(); + Field field = clazz.getDeclaredField(name); + field.setAccessible(true); + o = field.get(o); + } + return o; + } + + /** + * 得到所有定义字段 + */ + private void createExcelField() + { + this.fields = getFields(); + this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList()); + this.maxHeight = getRowHeight(); + } + + /** + * 获取字段注解信息 + */ + public List getFields() + { + List fields = new ArrayList(); + List tempFields = new ArrayList<>(); + tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields())); + tempFields.addAll(Arrays.asList(clazz.getDeclaredFields())); + for (Field field : tempFields) + { + if (!ArrayUtils.contains(this.excludeFields, field.getName())) + { + // 单注解 + if (field.isAnnotationPresent(Excel.class)) + { + Excel attr = field.getAnnotation(Excel.class); + if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) + { + field.setAccessible(true); + fields.add(new Object[] { field, attr }); + } + if (Collection.class.isAssignableFrom(field.getType())) + { + subMethod = getSubMethod(field.getName(), clazz); + ParameterizedType pt = (ParameterizedType) field.getGenericType(); + Class subClass = (Class) pt.getActualTypeArguments()[0]; + this.subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class); + } + } + + // 多注解 + if (field.isAnnotationPresent(Excels.class)) + { + Excels attrs = field.getAnnotation(Excels.class); + Excel[] excels = attrs.value(); + for (Excel attr : excels) + { + if (attr != null && (attr.type() == Type.ALL || attr.type() == type)) + { + field.setAccessible(true); + fields.add(new Object[] { field, attr }); + } + } + } + } + } + return fields; + } + + /** + * 根据注解获取最大行高 + */ + public short getRowHeight() + { + double maxHeight = 0; + for (Object[] os : this.fields) + { + Excel excel = (Excel) os[1]; + maxHeight = Math.max(maxHeight, excel.height()); + } + return (short) (maxHeight * 20); + } + + /** + * 创建一个工作簿 + */ + public void createWorkbook() + { + this.wb = new SXSSFWorkbook(500); + this.sheet = wb.createSheet(); + wb.setSheetName(0, sheetName); + this.styles = createStyles(wb); + } + + /** + * 创建工作表 + * + * @param sheetNo sheet数量 + * @param index 序号 + */ + public void createSheet(int sheetNo, int index) + { + // 设置工作表的名称. + if (sheetNo > 1 && index > 0) + { + this.sheet = wb.createSheet(); + this.createTitle(); + wb.setSheetName(index, sheetName + index); + } + } + + /** + * 获取单元格值 + * + * @param row 获取的行 + * @param column 获取单元格列号 + * @return 单元格值 + */ + public Object getCellValue(Row row, int column) + { + if (row == null) + { + return row; + } + Object val = ""; + try + { + Cell cell = row.getCell(column); + if (StringUtils.isNotNull(cell)) + { + if (cell.getCellType() == CellType.NUMERIC || cell.getCellType() == CellType.FORMULA) + { + val = cell.getNumericCellValue(); + if (DateUtil.isCellDateFormatted(cell)) + { + val = DateUtil.getJavaDate((Double) val); // POI Excel 日期格式转换 + } + else + { + if ((Double) val % 1 != 0) + { + val = new BigDecimal(val.toString()); + } + else + { + val = new DecimalFormat("0").format(val); + } + } + } + else if (cell.getCellType() == CellType.STRING) + { + val = cell.getStringCellValue(); + } + else if (cell.getCellType() == CellType.BOOLEAN) + { + val = cell.getBooleanCellValue(); + } + else if (cell.getCellType() == CellType.ERROR) + { + val = cell.getErrorCellValue(); + } + + } + } + catch (Exception e) + { + return val; + } + return val; + } + + /** + * 判断是否是空行 + * + * @param row 判断的行 + * @return + */ + private boolean isRowEmpty(Row row) + { + if (row == null) + { + return true; + } + for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++) + { + Cell cell = row.getCell(i); + if (cell != null && cell.getCellType() != CellType.BLANK) + { + return false; + } + } + return true; + } + + /** + * 获取Excel2003图片 + * + * @param sheet 当前sheet对象 + * @param workbook 工作簿对象 + * @return Map key:图片单元格索引(1_1)String,value:图片流PictureData + */ + public static Map getSheetPictures03(HSSFSheet sheet, HSSFWorkbook workbook) + { + Map sheetIndexPicMap = new HashMap(); + List pictures = workbook.getAllPictures(); + if (!pictures.isEmpty()) + { + for (HSSFShape shape : sheet.getDrawingPatriarch().getChildren()) + { + HSSFClientAnchor anchor = (HSSFClientAnchor) shape.getAnchor(); + if (shape instanceof HSSFPicture) + { + HSSFPicture pic = (HSSFPicture) shape; + int pictureIndex = pic.getPictureIndex() - 1; + HSSFPictureData picData = pictures.get(pictureIndex); + String picIndex = String.valueOf(anchor.getRow1()) + "_" + String.valueOf(anchor.getCol1()); + sheetIndexPicMap.put(picIndex, picData); + } + } + return sheetIndexPicMap; + } + else + { + return sheetIndexPicMap; + } + } + + /** + * 获取Excel2007图片 + * + * @param sheet 当前sheet对象 + * @param workbook 工作簿对象 + * @return Map key:图片单元格索引(1_1)String,value:图片流PictureData + */ + public static Map getSheetPictures07(XSSFSheet sheet, XSSFWorkbook workbook) + { + Map sheetIndexPicMap = new HashMap(); + for (POIXMLDocumentPart dr : sheet.getRelations()) + { + if (dr instanceof XSSFDrawing) + { + XSSFDrawing drawing = (XSSFDrawing) dr; + List shapes = drawing.getShapes(); + for (XSSFShape shape : shapes) + { + if (shape instanceof XSSFPicture) + { + XSSFPicture pic = (XSSFPicture) shape; + XSSFClientAnchor anchor = pic.getPreferredSize(); + CTMarker ctMarker = anchor.getFrom(); + String picIndex = ctMarker.getRow() + "_" + ctMarker.getCol(); + sheetIndexPicMap.put(picIndex, pic.getPictureData()); + } + } + } + } + return sheetIndexPicMap; + } + + /** + * 格式化不同类型的日期对象 + * + * @param dateFormat 日期格式 + * @param val 被格式化的日期对象 + * @return 格式化后的日期字符 + */ + public String parseDateToStr(String dateFormat, Object val) + { + if (val == null) + { + return ""; + } + String str; + if (val instanceof Date) + { + str = DateUtils.parseDateToStr(dateFormat, (Date) val); + } + else if (val instanceof LocalDateTime) + { + str = DateUtils.parseDateToStr(dateFormat, DateUtils.toDate((LocalDateTime) val)); + } + else if (val instanceof LocalDate) + { + str = DateUtils.parseDateToStr(dateFormat, DateUtils.toDate((LocalDate) val)); + } + else + { + str = val.toString(); + } + return str; + } + + /** + * 是否有对象的子列表 + */ + public boolean isSubList() + { + return StringUtils.isNotNull(subFields) && subFields.size() > 0; + } + + /** + * 是否有对象的子列表,集合不为空 + */ + public boolean isSubListValue(T vo) + { + return StringUtils.isNotNull(subFields) && subFields.size() > 0 && StringUtils.isNotNull(getListCellValue(vo)) && getListCellValue(vo).size() > 0; + } + + /** + * 获取集合的值 + */ + public Collection getListCellValue(Object obj) + { + Object value; + try + { + value = subMethod.invoke(obj, new Object[] {}); + } + catch (Exception e) + { + return new ArrayList(); + } + return (Collection) value; + } + + /** + * 获取对象的子列表方法 + * + * @param name 名称 + * @param pojoClass 类对象 + * @return 子列表方法 + */ + public Method getSubMethod(String name, Class pojoClass) + { + StringBuffer getMethodName = new StringBuffer("get"); + getMethodName.append(name.substring(0, 1).toUpperCase()); + getMethodName.append(name.substring(1)); + Method method = null; + try + { + method = pojoClass.getMethod(getMethodName.toString(), new Class[] {}); + } + catch (Exception e) + { + log.error("获取对象异常{}", e.getMessage()); + } + return method; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java new file mode 100644 index 0000000..5134e13 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java @@ -0,0 +1,410 @@ +package com.ruoyi.common.utils.reflect; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Date; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.Validate; +import org.apache.poi.ss.usermodel.DateUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.ruoyi.common.core.text.Convert; +import com.ruoyi.common.utils.DateUtils; + +/** + * 反射工具类. 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数. + * + * @author #author# + */ +@SuppressWarnings("rawtypes") +public class ReflectUtils +{ + private static final String SETTER_PREFIX = "set"; + + private static final String GETTER_PREFIX = "get"; + + private static final String CGLIB_CLASS_SEPARATOR = "$$"; + + private static Logger logger = LoggerFactory.getLogger(ReflectUtils.class); + + /** + * 调用Getter方法. + * 支持多级,如:对象名.对象名.方法 + */ + @SuppressWarnings("unchecked") + public static E invokeGetter(Object obj, String propertyName) + { + Object object = obj; + for (String name : StringUtils.split(propertyName, ".")) + { + String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name); + object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {}); + } + return (E) object; + } + + /** + * 调用Setter方法, 仅匹配方法名。 + * 支持多级,如:对象名.对象名.方法 + */ + public static void invokeSetter(Object obj, String propertyName, E value) + { + Object object = obj; + String[] names = StringUtils.split(propertyName, "."); + for (int i = 0; i < names.length; i++) + { + if (i < names.length - 1) + { + String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]); + object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {}); + } + else + { + String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]); + invokeMethodByName(object, setterMethodName, new Object[] { value }); + } + } + } + + /** + * 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数. + */ + @SuppressWarnings("unchecked") + public static E getFieldValue(final Object obj, final String fieldName) + { + Field field = getAccessibleField(obj, fieldName); + if (field == null) + { + logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 "); + return null; + } + E result = null; + try + { + result = (E) field.get(obj); + } + catch (IllegalAccessException e) + { + logger.error("不可能抛出的异常{}", e.getMessage()); + } + return result; + } + + /** + * 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数. + */ + public static void setFieldValue(final Object obj, final String fieldName, final E value) + { + Field field = getAccessibleField(obj, fieldName); + if (field == null) + { + // throw new IllegalArgumentException("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 "); + logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 "); + return; + } + try + { + field.set(obj, value); + } + catch (IllegalAccessException e) + { + logger.error("不可能抛出的异常: {}", e.getMessage()); + } + } + + /** + * 直接调用对象方法, 无视private/protected修饰符. + * 用于一次性调用的情况,否则应使用getAccessibleMethod()函数获得Method后反复调用. + * 同时匹配方法名+参数类型, + */ + @SuppressWarnings("unchecked") + public static E invokeMethod(final Object obj, final String methodName, final Class[] parameterTypes, + final Object[] args) + { + if (obj == null || methodName == null) + { + return null; + } + Method method = getAccessibleMethod(obj, methodName, parameterTypes); + if (method == null) + { + logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 "); + return null; + } + try + { + return (E) method.invoke(obj, args); + } + catch (Exception e) + { + String msg = "method: " + method + ", obj: " + obj + ", args: " + args + ""; + throw convertReflectionExceptionToUnchecked(msg, e); + } + } + + /** + * 直接调用对象方法, 无视private/protected修饰符, + * 用于一次性调用的情况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用. + * 只匹配函数名,如果有多个同名函数调用第一个。 + */ + @SuppressWarnings("unchecked") + public static E invokeMethodByName(final Object obj, final String methodName, final Object[] args) + { + Method method = getAccessibleMethodByName(obj, methodName, args.length); + if (method == null) + { + // 如果为空不报错,直接返回空。 + logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 "); + return null; + } + try + { + // 类型转换(将参数数据类型转换为目标方法参数类型) + Class[] cs = method.getParameterTypes(); + for (int i = 0; i < cs.length; i++) + { + if (args[i] != null && !args[i].getClass().equals(cs[i])) + { + if (cs[i] == String.class) + { + args[i] = Convert.toStr(args[i]); + if (StringUtils.endsWith((String) args[i], ".0")) + { + args[i] = StringUtils.substringBefore((String) args[i], ".0"); + } + } + else if (cs[i] == Integer.class) + { + args[i] = Convert.toInt(args[i]); + } + else if (cs[i] == Long.class) + { + args[i] = Convert.toLong(args[i]); + } + else if (cs[i] == Double.class) + { + args[i] = Convert.toDouble(args[i]); + } + else if (cs[i] == Float.class) + { + args[i] = Convert.toFloat(args[i]); + } + else if (cs[i] == Date.class) + { + if (args[i] instanceof String) + { + args[i] = DateUtils.parseDate(args[i]); + } + else + { + args[i] = DateUtil.getJavaDate((Double) args[i]); + } + } + else if (cs[i] == boolean.class || cs[i] == Boolean.class) + { + args[i] = Convert.toBool(args[i]); + } + } + } + return (E) method.invoke(obj, args); + } + catch (Exception e) + { + String msg = "method: " + method + ", obj: " + obj + ", args: " + args + ""; + throw convertReflectionExceptionToUnchecked(msg, e); + } + } + + /** + * 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问. + * 如向上转型到Object仍无法找到, 返回null. + */ + public static Field getAccessibleField(final Object obj, final String fieldName) + { + // 为空不报错。直接返回 null + if (obj == null) + { + return null; + } + Validate.notBlank(fieldName, "fieldName can't be blank"); + for (Class superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) + { + try + { + Field field = superClass.getDeclaredField(fieldName); + makeAccessible(field); + return field; + } + catch (NoSuchFieldException e) + { + continue; + } + } + return null; + } + + /** + * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. + * 如向上转型到Object仍无法找到, 返回null. + * 匹配函数名+参数类型。 + * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args) + */ + public static Method getAccessibleMethod(final Object obj, final String methodName, + final Class... parameterTypes) + { + // 为空不报错。直接返回 null + if (obj == null) + { + return null; + } + Validate.notBlank(methodName, "methodName can't be blank"); + for (Class searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) + { + try + { + Method method = searchType.getDeclaredMethod(methodName, parameterTypes); + makeAccessible(method); + return method; + } + catch (NoSuchMethodException e) + { + continue; + } + } + return null; + } + + /** + * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. + * 如向上转型到Object仍无法找到, 返回null. + * 只匹配函数名。 + * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args) + */ + public static Method getAccessibleMethodByName(final Object obj, final String methodName, int argsNum) + { + // 为空不报错。直接返回 null + if (obj == null) + { + return null; + } + Validate.notBlank(methodName, "methodName can't be blank"); + for (Class searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) + { + Method[] methods = searchType.getDeclaredMethods(); + for (Method method : methods) + { + if (method.getName().equals(methodName) && method.getParameterTypes().length == argsNum) + { + makeAccessible(method); + return method; + } + } + } + return null; + } + + /** + * 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。 + */ + public static void makeAccessible(Method method) + { + if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) + && !method.isAccessible()) + { + method.setAccessible(true); + } + } + + /** + * 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。 + */ + public static void makeAccessible(Field field) + { + if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) + || Modifier.isFinal(field.getModifiers())) && !field.isAccessible()) + { + field.setAccessible(true); + } + } + + /** + * 通过反射, 获得Class定义中声明的泛型参数的类型, 注意泛型必须定义在父类处 + * 如无法找到, 返回Object.class. + */ + @SuppressWarnings("unchecked") + public static Class getClassGenricType(final Class clazz) + { + return getClassGenricType(clazz, 0); + } + + /** + * 通过反射, 获得Class定义中声明的父类的泛型参数的类型. + * 如无法找到, 返回Object.class. + */ + public static Class getClassGenricType(final Class clazz, final int index) + { + Type genType = clazz.getGenericSuperclass(); + + if (!(genType instanceof ParameterizedType)) + { + logger.debug(clazz.getSimpleName() + "'s superclass not ParameterizedType"); + return Object.class; + } + + Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); + + if (index >= params.length || index < 0) + { + logger.debug("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: " + + params.length); + return Object.class; + } + if (!(params[index] instanceof Class)) + { + logger.debug(clazz.getSimpleName() + " not set the actual class on superclass generic parameter"); + return Object.class; + } + + return (Class) params[index]; + } + + public static Class getUserClass(Object instance) + { + if (instance == null) + { + throw new RuntimeException("Instance must not be null"); + } + Class clazz = instance.getClass(); + if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) + { + Class superClass = clazz.getSuperclass(); + if (superClass != null && !Object.class.equals(superClass)) + { + return superClass; + } + } + return clazz; + + } + + /** + * 将反射时的checked exception转换为unchecked exception. + */ + public static RuntimeException convertReflectionExceptionToUnchecked(String msg, Exception e) + { + if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException + || e instanceof NoSuchMethodException) + { + return new IllegalArgumentException(msg, e); + } + else if (e instanceof InvocationTargetException) + { + return new RuntimeException(msg, ((InvocationTargetException) e).getTargetException()); + } + return new RuntimeException(msg, e); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Base64.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Base64.java new file mode 100644 index 0000000..06e069d --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Base64.java @@ -0,0 +1,291 @@ +package com.ruoyi.common.utils.sign; + +/** + * Base64工具类 + * + * @author #author# + */ +public final class Base64 +{ + static private final int BASELENGTH = 128; + static private final int LOOKUPLENGTH = 64; + static private final int TWENTYFOURBITGROUP = 24; + static private final int EIGHTBIT = 8; + static private final int SIXTEENBIT = 16; + static private final int FOURBYTE = 4; + static private final int SIGN = -128; + static private final char PAD = '='; + static final private byte[] base64Alphabet = new byte[BASELENGTH]; + static final private char[] lookUpBase64Alphabet = new char[LOOKUPLENGTH]; + + static + { + for (int i = 0; i < BASELENGTH; ++i) + { + base64Alphabet[i] = -1; + } + for (int i = 'Z'; i >= 'A'; i--) + { + base64Alphabet[i] = (byte) (i - 'A'); + } + for (int i = 'z'; i >= 'a'; i--) + { + base64Alphabet[i] = (byte) (i - 'a' + 26); + } + + for (int i = '9'; i >= '0'; i--) + { + base64Alphabet[i] = (byte) (i - '0' + 52); + } + + base64Alphabet['+'] = 62; + base64Alphabet['/'] = 63; + + for (int i = 0; i <= 25; i++) + { + lookUpBase64Alphabet[i] = (char) ('A' + i); + } + + for (int i = 26, j = 0; i <= 51; i++, j++) + { + lookUpBase64Alphabet[i] = (char) ('a' + j); + } + + for (int i = 52, j = 0; i <= 61; i++, j++) + { + lookUpBase64Alphabet[i] = (char) ('0' + j); + } + lookUpBase64Alphabet[62] = (char) '+'; + lookUpBase64Alphabet[63] = (char) '/'; + } + + private static boolean isWhiteSpace(char octect) + { + return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9); + } + + private static boolean isPad(char octect) + { + return (octect == PAD); + } + + private static boolean isData(char octect) + { + return (octect < BASELENGTH && base64Alphabet[octect] != -1); + } + + /** + * Encodes hex octects into Base64 + * + * @param binaryData Array containing binaryData + * @return Encoded Base64 array + */ + public static String encode(byte[] binaryData) + { + if (binaryData == null) + { + return null; + } + + int lengthDataBits = binaryData.length * EIGHTBIT; + if (lengthDataBits == 0) + { + return ""; + } + + int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP; + int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP; + int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 : numberTriplets; + char encodedData[] = null; + + encodedData = new char[numberQuartet * 4]; + + byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0; + + int encodedIndex = 0; + int dataIndex = 0; + + for (int i = 0; i < numberTriplets; i++) + { + b1 = binaryData[dataIndex++]; + b2 = binaryData[dataIndex++]; + b3 = binaryData[dataIndex++]; + + l = (byte) (b2 & 0x0f); + k = (byte) (b1 & 0x03); + + byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); + byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0); + byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc); + + encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; + encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)]; + encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3]; + encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f]; + } + + // form integral number of 6-bit groups + if (fewerThan24bits == EIGHTBIT) + { + b1 = binaryData[dataIndex]; + k = (byte) (b1 & 0x03); + byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); + encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; + encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4]; + encodedData[encodedIndex++] = PAD; + encodedData[encodedIndex++] = PAD; + } + else if (fewerThan24bits == SIXTEENBIT) + { + b1 = binaryData[dataIndex]; + b2 = binaryData[dataIndex + 1]; + l = (byte) (b2 & 0x0f); + k = (byte) (b1 & 0x03); + + byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0); + byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0); + + encodedData[encodedIndex++] = lookUpBase64Alphabet[val1]; + encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)]; + encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2]; + encodedData[encodedIndex++] = PAD; + } + return new String(encodedData); + } + + /** + * Decodes Base64 data into octects + * + * @param encoded string containing Base64 data + * @return Array containind decoded data. + */ + public static byte[] decode(String encoded) + { + if (encoded == null) + { + return null; + } + + char[] base64Data = encoded.toCharArray(); + // remove white spaces + int len = removeWhiteSpace(base64Data); + + if (len % FOURBYTE != 0) + { + return null;// should be divisible by four + } + + int numberQuadruple = (len / FOURBYTE); + + if (numberQuadruple == 0) + { + return new byte[0]; + } + + byte decodedData[] = null; + byte b1 = 0, b2 = 0, b3 = 0, b4 = 0; + char d1 = 0, d2 = 0, d3 = 0, d4 = 0; + + int i = 0; + int encodedIndex = 0; + int dataIndex = 0; + decodedData = new byte[(numberQuadruple) * 3]; + + for (; i < numberQuadruple - 1; i++) + { + + if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++])) + || !isData((d3 = base64Data[dataIndex++])) || !isData((d4 = base64Data[dataIndex++]))) + { + return null; + } // if found "no data" just return null + + b1 = base64Alphabet[d1]; + b2 = base64Alphabet[d2]; + b3 = base64Alphabet[d3]; + b4 = base64Alphabet[d4]; + + decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); + decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); + decodedData[encodedIndex++] = (byte) (b3 << 6 | b4); + } + + if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))) + { + return null;// if found "no data" just return null + } + + b1 = base64Alphabet[d1]; + b2 = base64Alphabet[d2]; + + d3 = base64Data[dataIndex++]; + d4 = base64Data[dataIndex++]; + if (!isData((d3)) || !isData((d4))) + {// Check if they are PAD characters + if (isPad(d3) && isPad(d4)) + { + if ((b2 & 0xf) != 0)// last 4 bits should be zero + { + return null; + } + byte[] tmp = new byte[i * 3 + 1]; + System.arraycopy(decodedData, 0, tmp, 0, i * 3); + tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); + return tmp; + } + else if (!isPad(d3) && isPad(d4)) + { + b3 = base64Alphabet[d3]; + if ((b3 & 0x3) != 0)// last 2 bits should be zero + { + return null; + } + byte[] tmp = new byte[i * 3 + 2]; + System.arraycopy(decodedData, 0, tmp, 0, i * 3); + tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); + tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); + return tmp; + } + else + { + return null; + } + } + else + { // No PAD e.g 3cQl + b3 = base64Alphabet[d3]; + b4 = base64Alphabet[d4]; + decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4); + decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); + decodedData[encodedIndex++] = (byte) (b3 << 6 | b4); + + } + return decodedData; + } + + /** + * remove WhiteSpace from MIME containing encoded Base64 data. + * + * @param data the byte array of base64 data (with WS) + * @return the new length + */ + private static int removeWhiteSpace(char[] data) + { + if (data == null) + { + return 0; + } + + // count characters that's not whitespace + int newSize = 0; + int len = data.length; + for (int i = 0; i < len; i++) + { + if (!isWhiteSpace(data[i])) + { + data[newSize++] = data[i]; + } + } + return newSize; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java new file mode 100644 index 0000000..6df6afa --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java @@ -0,0 +1,67 @@ +package com.ruoyi.common.utils.sign; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Md5加密方法 + * + * @author #author# + */ +public class Md5Utils +{ + private static final Logger log = LoggerFactory.getLogger(Md5Utils.class); + + private static byte[] md5(String s) + { + MessageDigest algorithm; + try + { + algorithm = MessageDigest.getInstance("MD5"); + algorithm.reset(); + algorithm.update(s.getBytes("UTF-8")); + byte[] messageDigest = algorithm.digest(); + return messageDigest; + } + catch (Exception e) + { + log.error("MD5 Error...", e); + } + return null; + } + + private static final String toHex(byte hash[]) + { + if (hash == null) + { + return null; + } + StringBuffer buf = new StringBuffer(hash.length * 2); + int i; + + for (i = 0; i < hash.length; i++) + { + if ((hash[i] & 0xff) < 0x10) + { + buf.append("0"); + } + buf.append(Long.toString(hash[i] & 0xff, 16)); + } + return buf.toString(); + } + + public static String hash(String s) + { + try + { + return new String(toHex(md5(s)).getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8); + } + catch (Exception e) + { + log.error("not supported charset...{}", e); + return s; + } + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java new file mode 100644 index 0000000..20ece8d --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java @@ -0,0 +1,158 @@ +package com.ruoyi.common.utils.spring; + +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; +import com.ruoyi.common.utils.StringUtils; + +/** + * spring工具类 方便在非spring管理环境中获取bean + * + * @author #author# + */ +@Component +public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware +{ + /** Spring应用上下文环境 */ + private static ConfigurableListableBeanFactory beanFactory; + + private static ApplicationContext applicationContext; + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException + { + SpringUtils.beanFactory = beanFactory; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException + { + SpringUtils.applicationContext = applicationContext; + } + + /** + * 获取对象 + * + * @param name + * @return Object 一个以所给名字注册的bean的实例 + * @throws org.springframework.beans.BeansException + * + */ + @SuppressWarnings("unchecked") + public static T getBean(String name) throws BeansException + { + return (T) beanFactory.getBean(name); + } + + /** + * 获取类型为requiredType的对象 + * + * @param clz + * @return + * @throws org.springframework.beans.BeansException + * + */ + public static T getBean(Class clz) throws BeansException + { + T result = (T) beanFactory.getBean(clz); + return result; + } + + /** + * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true + * + * @param name + * @return boolean + */ + public static boolean containsBean(String name) + { + return beanFactory.containsBean(name); + } + + /** + * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException) + * + * @param name + * @return boolean + * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException + * + */ + public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException + { + return beanFactory.isSingleton(name); + } + + /** + * @param name + * @return Class 注册对象的类型 + * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException + * + */ + public static Class getType(String name) throws NoSuchBeanDefinitionException + { + return beanFactory.getType(name); + } + + /** + * 如果给定的bean名字在bean定义中有别名,则返回这些别名 + * + * @param name + * @return + * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException + * + */ + public static String[] getAliases(String name) throws NoSuchBeanDefinitionException + { + return beanFactory.getAliases(name); + } + + /** + * 获取aop代理对象 + * + * @param invoker + * @return + */ + @SuppressWarnings("unchecked") + public static T getAopProxy(T invoker) + { + return (T) AopContext.currentProxy(); + } + + /** + * 获取当前的环境配置,无配置返回null + * + * @return 当前的环境配置 + */ + public static String[] getActiveProfiles() + { + return applicationContext.getEnvironment().getActiveProfiles(); + } + + /** + * 获取当前的环境配置,当有多个环境配置时,只获取第一个 + * + * @return 当前的环境配置 + */ + public static String getActiveProfile() + { + final String[] activeProfiles = getActiveProfiles(); + return StringUtils.isNotEmpty(activeProfiles) ? activeProfiles[0] : null; + } + + /** + * 获取配置文件中的值 + * + * @param key 配置文件的key + * @return 当前的配置文件的值 + * + */ + public static String getRequiredProperty(String key) + { + return applicationContext.getEnvironment().getRequiredProperty(key); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java new file mode 100644 index 0000000..b0dc0e8 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java @@ -0,0 +1,61 @@ +package com.ruoyi.common.utils.sql; + +import com.ruoyi.common.exception.UtilException; +import com.ruoyi.common.utils.StringUtils; + +/** + * sql操作工具类 + * + * @author #author# + */ +public class SqlUtil +{ + /** + * 定义常用的 sql关键字 + */ + public static String SQL_REGEX = "and |extractvalue|updatexml|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |+|user()"; + + /** + * 仅支持字母、数字、下划线、空格、逗号、小数点(支持多个字段排序) + */ + public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+"; + + /** + * 检查字符,防止注入绕过 + */ + public static String escapeOrderBySql(String value) + { + if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value)) + { + throw new UtilException("参数不符合规范,不能进行查询"); + } + return value; + } + + /** + * 验证 order by 语法是否符合规范 + */ + public static boolean isValidOrderBySql(String value) + { + return value.matches(SQL_PATTERN); + } + + /** + * SQL关键字检查 + */ + public static void filterKeyword(String value) + { + if (StringUtils.isEmpty(value)) + { + return; + } + String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|"); + for (String sqlKeyword : sqlKeywords) + { + if (StringUtils.indexOfIgnoreCase(value, sqlKeyword) > -1) + { + throw new UtilException("参数存在SQL注入风险"); + } + } + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/IdUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/IdUtils.java new file mode 100644 index 0000000..9f42275 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/IdUtils.java @@ -0,0 +1,49 @@ +package com.ruoyi.common.utils.uuid; + +/** + * ID生成器工具类 + * + * @author #author# + */ +public class IdUtils +{ + /** + * 获取随机UUID + * + * @return 随机UUID + */ + public static String randomUUID() + { + return UUID.randomUUID().toString(); + } + + /** + * 简化的UUID,去掉了横线 + * + * @return 简化的UUID,去掉了横线 + */ + public static String simpleUUID() + { + return UUID.randomUUID().toString(true); + } + + /** + * 获取随机UUID,使用性能更好的ThreadLocalRandom生成UUID + * + * @return 随机UUID + */ + public static String fastUUID() + { + return UUID.fastUUID().toString(); + } + + /** + * 简化的UUID,去掉了横线,使用性能更好的ThreadLocalRandom生成UUID + * + * @return 简化的UUID,去掉了横线 + */ + public static String fastSimpleUUID() + { + return UUID.fastUUID().toString(true); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/Seq.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/Seq.java new file mode 100644 index 0000000..b8c5170 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/Seq.java @@ -0,0 +1,86 @@ +package com.ruoyi.common.utils.uuid; + +import java.util.concurrent.atomic.AtomicInteger; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.StringUtils; + +/** + * @author #author# 序列生成类 + */ +public class Seq +{ + // 通用序列类型 + public static final String commSeqType = "COMMON"; + + // 上传序列类型 + public static final String uploadSeqType = "UPLOAD"; + + // 通用接口序列数 + private static AtomicInteger commSeq = new AtomicInteger(1); + + // 上传接口序列数 + private static AtomicInteger uploadSeq = new AtomicInteger(1); + + // 机器标识 + private static String machineCode = "A"; + + /** + * 获取通用序列号 + * + * @return 序列值 + */ + public static String getId() + { + return getId(commSeqType); + } + + /** + * 默认16位序列号 yyMMddHHmmss + 一位机器标识 + 3长度循环递增字符串 + * + * @return 序列值 + */ + public static String getId(String type) + { + AtomicInteger atomicInt = commSeq; + if (uploadSeqType.equals(type)) + { + atomicInt = uploadSeq; + } + return getId(atomicInt, 3); + } + + /** + * 通用接口序列号 yyMMddHHmmss + 一位机器标识 + length长度循环递增字符串 + * + * @param atomicInt 序列数 + * @param length 数值长度 + * @return 序列值 + */ + public static String getId(AtomicInteger atomicInt, int length) + { + String result = DateUtils.dateTimeNow(); + result += machineCode; + result += getSeq(atomicInt, length); + return result; + } + + /** + * 序列循环递增字符串[1, 10 的 (length)幂次方), 用0左补齐length位数 + * + * @return 序列值 + */ + private synchronized static String getSeq(AtomicInteger atomicInt, int length) + { + // 先取值再+1 + int value = atomicInt.getAndIncrement(); + + // 如果更新后值>=10 的 (length)幂次方则重置为1 + int maxSeq = (int) Math.pow(10, length); + if (atomicInt.get() >= maxSeq) + { + atomicInt.set(1); + } + // 转字符串,用0左补齐 + return StringUtils.padl(value, length); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/UUID.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/UUID.java new file mode 100644 index 0000000..c9cebec --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/UUID.java @@ -0,0 +1,484 @@ +package com.ruoyi.common.utils.uuid; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; +import com.ruoyi.common.exception.UtilException; + +/** + * 提供通用唯一识别码(universally unique identifier)(UUID)实现 + * + * @author #author# + */ +public final class UUID implements java.io.Serializable, Comparable +{ + private static final long serialVersionUID = -1185015143654744140L; + + /** + * SecureRandom 的单例 + * + */ + private static class Holder + { + static final SecureRandom numberGenerator = getSecureRandom(); + } + + /** 此UUID的最高64有效位 */ + private final long mostSigBits; + + /** 此UUID的最低64有效位 */ + private final long leastSigBits; + + /** + * 私有构造 + * + * @param data 数据 + */ + private UUID(byte[] data) + { + long msb = 0; + long lsb = 0; + assert data.length == 16 : "data must be 16 bytes in length"; + for (int i = 0; i < 8; i++) + { + msb = (msb << 8) | (data[i] & 0xff); + } + for (int i = 8; i < 16; i++) + { + lsb = (lsb << 8) | (data[i] & 0xff); + } + this.mostSigBits = msb; + this.leastSigBits = lsb; + } + + /** + * 使用指定的数据构造新的 UUID。 + * + * @param mostSigBits 用于 {@code UUID} 的最高有效 64 位 + * @param leastSigBits 用于 {@code UUID} 的最低有效 64 位 + */ + public UUID(long mostSigBits, long leastSigBits) + { + this.mostSigBits = mostSigBits; + this.leastSigBits = leastSigBits; + } + + /** + * 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的本地线程伪随机数生成器生成该 UUID。 + * + * @return 随机生成的 {@code UUID} + */ + public static UUID fastUUID() + { + return randomUUID(false); + } + + /** + * 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。 + * + * @return 随机生成的 {@code UUID} + */ + public static UUID randomUUID() + { + return randomUUID(true); + } + + /** + * 获取类型 4(伪随机生成的)UUID 的静态工厂。 使用加密的强伪随机数生成器生成该 UUID。 + * + * @param isSecure 是否使用{@link SecureRandom}如果是可以获得更安全的随机码,否则可以得到更好的性能 + * @return 随机生成的 {@code UUID} + */ + public static UUID randomUUID(boolean isSecure) + { + final Random ng = isSecure ? Holder.numberGenerator : getRandom(); + + byte[] randomBytes = new byte[16]; + ng.nextBytes(randomBytes); + randomBytes[6] &= 0x0f; /* clear version */ + randomBytes[6] |= 0x40; /* set to version 4 */ + randomBytes[8] &= 0x3f; /* clear variant */ + randomBytes[8] |= 0x80; /* set to IETF variant */ + return new UUID(randomBytes); + } + + /** + * 根据指定的字节数组获取类型 3(基于名称的)UUID 的静态工厂。 + * + * @param name 用于构造 UUID 的字节数组。 + * + * @return 根据指定数组生成的 {@code UUID} + */ + public static UUID nameUUIDFromBytes(byte[] name) + { + MessageDigest md; + try + { + md = MessageDigest.getInstance("MD5"); + } + catch (NoSuchAlgorithmException nsae) + { + throw new InternalError("MD5 not supported"); + } + byte[] md5Bytes = md.digest(name); + md5Bytes[6] &= 0x0f; /* clear version */ + md5Bytes[6] |= 0x30; /* set to version 3 */ + md5Bytes[8] &= 0x3f; /* clear variant */ + md5Bytes[8] |= 0x80; /* set to IETF variant */ + return new UUID(md5Bytes); + } + + /** + * 根据 {@link #toString()} 方法中描述的字符串标准表示形式创建{@code UUID}。 + * + * @param name 指定 {@code UUID} 字符串 + * @return 具有指定值的 {@code UUID} + * @throws IllegalArgumentException 如果 name 与 {@link #toString} 中描述的字符串表示形式不符抛出此异常 + * + */ + public static UUID fromString(String name) + { + String[] components = name.split("-"); + if (components.length != 5) + { + throw new IllegalArgumentException("Invalid UUID string: " + name); + } + for (int i = 0; i < 5; i++) + { + components[i] = "0x" + components[i]; + } + + long mostSigBits = Long.decode(components[0]).longValue(); + mostSigBits <<= 16; + mostSigBits |= Long.decode(components[1]).longValue(); + mostSigBits <<= 16; + mostSigBits |= Long.decode(components[2]).longValue(); + + long leastSigBits = Long.decode(components[3]).longValue(); + leastSigBits <<= 48; + leastSigBits |= Long.decode(components[4]).longValue(); + + return new UUID(mostSigBits, leastSigBits); + } + + /** + * 返回此 UUID 的 128 位值中的最低有效 64 位。 + * + * @return 此 UUID 的 128 位值中的最低有效 64 位。 + */ + public long getLeastSignificantBits() + { + return leastSigBits; + } + + /** + * 返回此 UUID 的 128 位值中的最高有效 64 位。 + * + * @return 此 UUID 的 128 位值中最高有效 64 位。 + */ + public long getMostSignificantBits() + { + return mostSigBits; + } + + /** + * 与此 {@code UUID} 相关联的版本号. 版本号描述此 {@code UUID} 是如何生成的。 + *

+ * 版本号具有以下含意: + *

    + *
  • 1 基于时间的 UUID + *
  • 2 DCE 安全 UUID + *
  • 3 基于名称的 UUID + *
  • 4 随机生成的 UUID + *
+ * + * @return 此 {@code UUID} 的版本号 + */ + public int version() + { + // Version is bits masked by 0x000000000000F000 in MS long + return (int) ((mostSigBits >> 12) & 0x0f); + } + + /** + * 与此 {@code UUID} 相关联的变体号。变体号描述 {@code UUID} 的布局。 + *

+ * 变体号具有以下含意: + *

    + *
  • 0 为 NCS 向后兼容保留 + *
  • 2 IETF RFC 4122(Leach-Salz), 用于此类 + *
  • 6 保留,微软向后兼容 + *
  • 7 保留供以后定义使用 + *
+ * + * @return 此 {@code UUID} 相关联的变体号 + */ + public int variant() + { + // This field is composed of a varying number of bits. + // 0 - - Reserved for NCS backward compatibility + // 1 0 - The IETF aka Leach-Salz variant (used by this class) + // 1 1 0 Reserved, Microsoft backward compatibility + // 1 1 1 Reserved for future definition. + return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62))) & (leastSigBits >> 63)); + } + + /** + * 与此 UUID 相关联的时间戳值。 + * + *

+ * 60 位的时间戳值根据此 {@code UUID} 的 time_low、time_mid 和 time_hi 字段构造。
+ * 所得到的时间戳以 100 毫微秒为单位,从 UTC(通用协调时间) 1582 年 10 月 15 日零时开始。 + * + *

+ * 时间戳值仅在在基于时间的 UUID(其 version 类型为 1)中才有意义。
+ * 如果此 {@code UUID} 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。 + * + * @throws UnsupportedOperationException 如果此 {@code UUID} 不是 version 为 1 的 UUID。 + */ + public long timestamp() throws UnsupportedOperationException + { + checkTimeBase(); + return (mostSigBits & 0x0FFFL) << 48// + | ((mostSigBits >> 16) & 0x0FFFFL) << 32// + | mostSigBits >>> 32; + } + + /** + * 与此 UUID 相关联的时钟序列值。 + * + *

+ * 14 位的时钟序列值根据此 UUID 的 clock_seq 字段构造。clock_seq 字段用于保证在基于时间的 UUID 中的时间唯一性。 + *

+ * {@code clockSequence} 值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。 如果此 UUID 不是基于时间的 UUID,则此方法抛出 + * UnsupportedOperationException。 + * + * @return 此 {@code UUID} 的时钟序列 + * + * @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1 + */ + public int clockSequence() throws UnsupportedOperationException + { + checkTimeBase(); + return (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48); + } + + /** + * 与此 UUID 相关的节点值。 + * + *

+ * 48 位的节点值根据此 UUID 的 node 字段构造。此字段旨在用于保存机器的 IEEE 802 地址,该地址用于生成此 UUID 以保证空间唯一性。 + *

+ * 节点值仅在基于时间的 UUID(其 version 类型为 1)中才有意义。
+ * 如果此 UUID 不是基于时间的 UUID,则此方法抛出 UnsupportedOperationException。 + * + * @return 此 {@code UUID} 的节点值 + * + * @throws UnsupportedOperationException 如果此 UUID 的 version 不为 1 + */ + public long node() throws UnsupportedOperationException + { + checkTimeBase(); + return leastSigBits & 0x0000FFFFFFFFFFFFL; + } + + /** + * 返回此{@code UUID} 的字符串表现形式。 + * + *

+ * UUID 的字符串表示形式由此 BNF 描述: + * + *

+     * {@code
+     * UUID                   = ----
+     * time_low               = 4*
+     * time_mid               = 2*
+     * time_high_and_version  = 2*
+     * variant_and_sequence   = 2*
+     * node                   = 6*
+     * hexOctet               = 
+     * hexDigit               = [0-9a-fA-F]
+     * }
+     * 
+ * + * + * + * @return 此{@code UUID} 的字符串表现形式 + * @see #toString(boolean) + */ + @Override + public String toString() + { + return toString(false); + } + + /** + * 返回此{@code UUID} 的字符串表现形式。 + * + *

+ * UUID 的字符串表示形式由此 BNF 描述: + * + *

+     * {@code
+     * UUID                   = ----
+     * time_low               = 4*
+     * time_mid               = 2*
+     * time_high_and_version  = 2*
+     * variant_and_sequence   = 2*
+     * node                   = 6*
+     * hexOctet               = 
+     * hexDigit               = [0-9a-fA-F]
+     * }
+     * 
+ * + * + * + * @param isSimple 是否简单模式,简单模式为不带'-'的UUID字符串 + * @return 此{@code UUID} 的字符串表现形式 + */ + public String toString(boolean isSimple) + { + final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36); + // time_low + builder.append(digits(mostSigBits >> 32, 8)); + if (!isSimple) + { + builder.append('-'); + } + // time_mid + builder.append(digits(mostSigBits >> 16, 4)); + if (!isSimple) + { + builder.append('-'); + } + // time_high_and_version + builder.append(digits(mostSigBits, 4)); + if (!isSimple) + { + builder.append('-'); + } + // variant_and_sequence + builder.append(digits(leastSigBits >> 48, 4)); + if (!isSimple) + { + builder.append('-'); + } + // node + builder.append(digits(leastSigBits, 12)); + + return builder.toString(); + } + + /** + * 返回此 UUID 的哈希码。 + * + * @return UUID 的哈希码值。 + */ + @Override + public int hashCode() + { + long hilo = mostSigBits ^ leastSigBits; + return ((int) (hilo >> 32)) ^ (int) hilo; + } + + /** + * 将此对象与指定对象比较。 + *

+ * 当且仅当参数不为 {@code null}、而是一个 UUID 对象、具有与此 UUID 相同的 varriant、包含相同的值(每一位均相同)时,结果才为 {@code true}。 + * + * @param obj 要与之比较的对象 + * + * @return 如果对象相同,则返回 {@code true};否则返回 {@code false} + */ + @Override + public boolean equals(Object obj) + { + if ((null == obj) || (obj.getClass() != UUID.class)) + { + return false; + } + UUID id = (UUID) obj; + return (mostSigBits == id.mostSigBits && leastSigBits == id.leastSigBits); + } + + // Comparison Operations + + /** + * 将此 UUID 与指定的 UUID 比较。 + * + *

+ * 如果两个 UUID 不同,且第一个 UUID 的最高有效字段大于第二个 UUID 的对应字段,则第一个 UUID 大于第二个 UUID。 + * + * @param val 与此 UUID 比较的 UUID + * + * @return 在此 UUID 小于、等于或大于 val 时,分别返回 -1、0 或 1。 + * + */ + @Override + public int compareTo(UUID val) + { + // The ordering is intentionally set up so that the UUIDs + // can simply be numerically compared as two numbers + return (this.mostSigBits < val.mostSigBits ? -1 : // + (this.mostSigBits > val.mostSigBits ? 1 : // + (this.leastSigBits < val.leastSigBits ? -1 : // + (this.leastSigBits > val.leastSigBits ? 1 : // + 0)))); + } + + // ------------------------------------------------------------------------------------------------------------------- + // Private method start + /** + * 返回指定数字对应的hex值 + * + * @param val 值 + * @param digits 位 + * @return 值 + */ + private static String digits(long val, int digits) + { + long hi = 1L << (digits * 4); + return Long.toHexString(hi | (val & (hi - 1))).substring(1); + } + + /** + * 检查是否为time-based版本UUID + */ + private void checkTimeBase() + { + if (version() != 1) + { + throw new UnsupportedOperationException("Not a time-based UUID"); + } + } + + /** + * 获取{@link SecureRandom},类提供加密的强随机数生成器 (RNG) + * + * @return {@link SecureRandom} + */ + public static SecureRandom getSecureRandom() + { + try + { + return SecureRandom.getInstance("SHA1PRNG"); + } + catch (NoSuchAlgorithmException e) + { + throw new UtilException(e); + } + } + + /** + * 获取随机数生成器对象
+ * ThreadLocalRandom是JDK 7之后提供并发产生随机数,能够解决多个线程发生的竞争争夺。 + * + * @return {@link ThreadLocalRandom} + */ + public static ThreadLocalRandom getRandom() + { + return ThreadLocalRandom.current(); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/xss/Xss.java b/ruoyi-common/src/main/java/com/ruoyi/common/xss/Xss.java new file mode 100644 index 0000000..5b814b8 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/xss/Xss.java @@ -0,0 +1,27 @@ +package com.ruoyi.common.xss; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 自定义xss校验注解 + * + * @author #author# + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(value = { ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER }) +@Constraint(validatedBy = { XssValidator.class }) +public @interface Xss +{ + String message() + + default "不允许任何脚本运行"; + + Class[] groups() default {}; + + Class[] payload() default {}; +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/xss/XssValidator.java b/ruoyi-common/src/main/java/com/ruoyi/common/xss/XssValidator.java new file mode 100644 index 0000000..f93413e --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/xss/XssValidator.java @@ -0,0 +1,34 @@ +package com.ruoyi.common.xss; + +import com.ruoyi.common.utils.StringUtils; +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 自定义xss校验注解实现 + * + * @author #author# + */ +public class XssValidator implements ConstraintValidator +{ + private static final String HTML_PATTERN = "<(\\S*?)[^>]*>.*?|<.*? />"; + + @Override + public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) + { + if (StringUtils.isBlank(value)) + { + return true; + } + return !containsHtml(value); + } + + public static boolean containsHtml(String value) + { + Pattern pattern = Pattern.compile(HTML_PATTERN); + Matcher matcher = pattern.matcher(value); + return matcher.matches(); + } +} \ No newline at end of file diff --git a/ruoyi-framework/pom.xml b/ruoyi-framework/pom.xml new file mode 100644 index 0000000..b290918 --- /dev/null +++ b/ruoyi-framework/pom.xml @@ -0,0 +1,70 @@ + + + + ruoyi + com.ruoyi + 3.8.5 + + 4.0.0 + + ruoyi-framework + + + framework框架核心 + + + + + + + org.springframework.boot + spring-boot-starter-web + + + + + org.springframework.boot + spring-boot-starter-aop + + + + + com.alibaba + druid-spring-boot-starter + + + + + pro.fessional + kaptcha + + + javax.servlet-api + javax.servlet + + + + + + + com.github.oshi + oshi-core + + + + + com.ruoyi + ruoyi-system + + + + + com.ruoyi + ruoyi-business + + + + + \ No newline at end of file diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java new file mode 100644 index 0000000..eb1f783 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java @@ -0,0 +1,167 @@ +package com.ruoyi.framework.aspectj; + +import java.util.ArrayList; +import java.util.List; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.springframework.stereotype.Component; +import com.ruoyi.common.annotation.DataScope; +import com.ruoyi.common.core.domain.BaseEntity; +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.core.text.Convert; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.framework.security.context.PermissionContextHolder; + +/** + * 数据过滤处理 + * + * @author #author# + */ +@Aspect +@Component +public class DataScopeAspect +{ + /** + * 全部数据权限 + */ + public static final String DATA_SCOPE_ALL = "1"; + + /** + * 自定数据权限 + */ + public static final String DATA_SCOPE_CUSTOM = "2"; + + /** + * 部门数据权限 + */ + public static final String DATA_SCOPE_DEPT = "3"; + + /** + * 部门及以下数据权限 + */ + public static final String DATA_SCOPE_DEPT_AND_CHILD = "4"; + + /** + * 仅本人数据权限 + */ + public static final String DATA_SCOPE_SELF = "5"; + + /** + * 数据权限过滤关键字 + */ + public static final String DATA_SCOPE = "dataScope"; + + @Before("@annotation(controllerDataScope)") + public void doBefore(JoinPoint point, DataScope controllerDataScope) throws Throwable + { + clearDataScope(point); + handleDataScope(point, controllerDataScope); + } + + protected void handleDataScope(final JoinPoint joinPoint, DataScope controllerDataScope) + { + // 获取当前的用户 + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (StringUtils.isNotNull(loginUser)) + { + SysUser currentUser = loginUser.getUser(); + // 如果是超级管理员,则不过滤数据 + if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin()) + { + String permission = StringUtils.defaultIfEmpty(controllerDataScope.permission(), PermissionContextHolder.getContext()); + dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(), + controllerDataScope.userAlias(), permission); + } + } + } + + /** + * 数据范围过滤 + * + * @param joinPoint 切点 + * @param user 用户 + * @param deptAlias 部门别名 + * @param userAlias 用户别名 + * @param permission 权限字符 + */ + public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias, String permission) + { + StringBuilder sqlString = new StringBuilder(); + List conditions = new ArrayList(); + + for (SysRole role : user.getRoles()) + { + String dataScope = role.getDataScope(); + if (!DATA_SCOPE_CUSTOM.equals(dataScope) && conditions.contains(dataScope)) + { + continue; + } + if (StringUtils.isNotEmpty(permission) && StringUtils.isNotEmpty(role.getPermissions()) + && !StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission))) + { + continue; + } + if (DATA_SCOPE_ALL.equals(dataScope)) + { + sqlString = new StringBuilder(); + break; + } + else if (DATA_SCOPE_CUSTOM.equals(dataScope)) + { + sqlString.append(StringUtils.format( + " OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias, + role.getRoleId())); + } + else if (DATA_SCOPE_DEPT.equals(dataScope)) + { + sqlString.append(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId())); + } + else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) + { + sqlString.append(StringUtils.format( + " OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )", + deptAlias, user.getDeptId(), user.getDeptId())); + } + else if (DATA_SCOPE_SELF.equals(dataScope)) + { + if (StringUtils.isNotBlank(userAlias)) + { + sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId())); + } + else + { + // 数据权限为仅本人且没有userAlias别名不查询任何数据 + sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias)); + } + } + conditions.add(dataScope); + } + + if (StringUtils.isNotBlank(sqlString.toString())) + { + Object params = joinPoint.getArgs()[0]; + if (StringUtils.isNotNull(params) && params instanceof BaseEntity) + { + BaseEntity baseEntity = (BaseEntity) params; + baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")"); + } + } + } + + /** + * 拼接权限sql前先清空params.dataScope参数防止注入 + */ + private void clearDataScope(final JoinPoint joinPoint) + { + Object params = joinPoint.getArgs()[0]; + if (StringUtils.isNotNull(params) && params instanceof BaseEntity) + { + BaseEntity baseEntity = (BaseEntity) params; + baseEntity.getParams().put(DATA_SCOPE, ""); + } + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java new file mode 100644 index 0000000..6287327 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java @@ -0,0 +1,72 @@ +package com.ruoyi.framework.aspectj; + +import java.util.Objects; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import com.ruoyi.common.annotation.DataSource; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.framework.datasource.DynamicDataSourceContextHolder; + +/** + * 多数据源处理 + * + * @author #author# + */ +@Aspect +@Order(1) +@Component +public class DataSourceAspect +{ + protected Logger logger = LoggerFactory.getLogger(getClass()); + + @Pointcut("@annotation(com.ruoyi.common.annotation.DataSource)" + + "|| @within(com.ruoyi.common.annotation.DataSource)") + public void dsPointCut() + { + + } + + @Around("dsPointCut()") + public Object around(ProceedingJoinPoint point) throws Throwable + { + DataSource dataSource = getDataSource(point); + + if (StringUtils.isNotNull(dataSource)) + { + DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name()); + } + + try + { + return point.proceed(); + } + finally + { + // 销毁数据源 在执行方法之后 + DynamicDataSourceContextHolder.clearDataSourceType(); + } + } + + /** + * 获取需要切换的数据源 + */ + public DataSource getDataSource(ProceedingJoinPoint point) + { + MethodSignature signature = (MethodSignature) point.getSignature(); + DataSource dataSource = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class); + if (Objects.nonNull(dataSource)) + { + return dataSource; + } + + return AnnotationUtils.findAnnotation(signature.getDeclaringType(), DataSource.class); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java new file mode 100644 index 0000000..db4c6d6 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java @@ -0,0 +1,227 @@ +package com.ruoyi.framework.aspectj; + +import java.util.Collection; +import java.util.Map; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.AfterReturning; +import org.aspectj.lang.annotation.AfterThrowing; +import org.aspectj.lang.annotation.Aspect; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; +import org.springframework.validation.BindingResult; +import org.springframework.web.multipart.MultipartFile; +import com.alibaba.fastjson2.JSON; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.enums.BusinessStatus; +import com.ruoyi.common.enums.HttpMethod; +import com.ruoyi.common.filter.PropertyPreExcludeFilter; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.ip.IpUtils; +import com.ruoyi.framework.manager.AsyncManager; +import com.ruoyi.framework.manager.factory.AsyncFactory; +import com.ruoyi.system.domain.SysOperLog; + +/** + * 操作日志记录处理 + * + * @author #author# + */ +@Aspect +@Component +public class LogAspect +{ + private static final Logger log = LoggerFactory.getLogger(LogAspect.class); + + /** 排除敏感属性字段 */ + public static final String[] EXCLUDE_PROPERTIES = { "password", "oldPassword", "newPassword", "confirmPassword" }; + + /** + * 处理完请求后执行 + * + * @param joinPoint 切点 + */ + @AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult") + public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult) + { + handleLog(joinPoint, controllerLog, null, jsonResult); + } + + /** + * 拦截异常操作 + * + * @param joinPoint 切点 + * @param e 异常 + */ + @AfterThrowing(value = "@annotation(controllerLog)", throwing = "e") + public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e) + { + handleLog(joinPoint, controllerLog, e, null); + } + + protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult) + { + try + { + // 获取当前的用户 + LoginUser loginUser = SecurityUtils.getLoginUser(); + + // *========数据库日志=========*// + SysOperLog operLog = new SysOperLog(); + operLog.setStatus(BusinessStatus.SUCCESS.ordinal()); + // 请求的地址 + String ip = IpUtils.getIpAddr(ServletUtils.getRequest()); + operLog.setOperIp(ip); + operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255)); + if (loginUser != null) + { + operLog.setOperName(loginUser.getUsername()); + } + + if (e != null) + { + operLog.setStatus(BusinessStatus.FAIL.ordinal()); + operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000)); + } + // 设置方法名称 + String className = joinPoint.getTarget().getClass().getName(); + String methodName = joinPoint.getSignature().getName(); + operLog.setMethod(className + "." + methodName + "()"); + // 设置请求方式 + operLog.setRequestMethod(ServletUtils.getRequest().getMethod()); + // 处理设置注解上的参数 + getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult); + // 保存数据库 + AsyncManager.me().execute(AsyncFactory.recordOper(operLog)); + } + catch (Exception exp) + { + // 记录本地异常日志 + log.error("异常信息:{}", exp.getMessage()); + exp.printStackTrace(); + } + } + + /** + * 获取注解中对方法的描述信息 用于Controller层注解 + * + * @param log 日志 + * @param operLog 操作日志 + * @throws Exception + */ + public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperLog operLog, Object jsonResult) throws Exception + { + // 设置action动作 + operLog.setBusinessType(log.businessType().ordinal()); + // 设置标题 + operLog.setTitle(log.title()); + // 设置操作人类别 + operLog.setOperatorType(log.operatorType().ordinal()); + // 是否需要保存request,参数和值 + if (log.isSaveRequestData()) + { + // 获取参数的信息,传入到数据库中。 + setRequestValue(joinPoint, operLog); + } + // 是否需要保存response,参数和值 + if (log.isSaveResponseData() && StringUtils.isNotNull(jsonResult)) + { + operLog.setJsonResult(StringUtils.substring(JSON.toJSONString(jsonResult), 0, 2000)); + } + } + + /** + * 获取请求的参数,放到log中 + * + * @param operLog 操作日志 + * @throws Exception 异常 + */ + private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog) throws Exception + { + String requestMethod = operLog.getRequestMethod(); + if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) + { + String params = argsArrayToString(joinPoint.getArgs()); + operLog.setOperParam(StringUtils.substring(params, 0, 2000)); + } + else + { + Map paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest()); + operLog.setOperParam(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter()), 0, 2000)); + } + } + + /** + * 参数拼装 + */ + private String argsArrayToString(Object[] paramsArray) + { + String params = ""; + if (paramsArray != null && paramsArray.length > 0) + { + for (Object o : paramsArray) + { + if (StringUtils.isNotNull(o) && !isFilterObject(o)) + { + try + { + String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter()); + params += jsonObj.toString() + " "; + } + catch (Exception e) + { + } + } + } + } + return params.trim(); + } + + /** + * 忽略敏感属性 + */ + public PropertyPreExcludeFilter excludePropertyPreFilter() + { + return new PropertyPreExcludeFilter().addExcludes(EXCLUDE_PROPERTIES); + } + + /** + * 判断是否需要过滤的对象。 + * + * @param o 对象信息。 + * @return 如果是需要过滤的对象,则返回true;否则返回false。 + */ + @SuppressWarnings("rawtypes") + public boolean isFilterObject(final Object o) + { + Class clazz = o.getClass(); + if (clazz.isArray()) + { + return clazz.getComponentType().isAssignableFrom(MultipartFile.class); + } + else if (Collection.class.isAssignableFrom(clazz)) + { + Collection collection = (Collection) o; + for (Object value : collection) + { + return value instanceof MultipartFile; + } + } + else if (Map.class.isAssignableFrom(clazz)) + { + Map map = (Map) o; + for (Object value : map.entrySet()) + { + Map.Entry entry = (Map.Entry) value; + return entry.getValue() instanceof MultipartFile; + } + } + return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse + || o instanceof BindingResult; + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java new file mode 100644 index 0000000..c7c3faa --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java @@ -0,0 +1,90 @@ +package com.ruoyi.framework.aspectj; + +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.List; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.reflect.MethodSignature; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.script.RedisScript; +import org.springframework.stereotype.Component; +import com.ruoyi.common.annotation.RateLimiter; +import com.ruoyi.common.enums.LimitType; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.ip.IpUtils; + +/** + * 限流处理 + * + * @author #author# + */ +@Aspect +@Component +public class RateLimiterAspect +{ + private static final Logger log = LoggerFactory.getLogger(RateLimiterAspect.class); + + private RedisTemplate redisTemplate; + + private RedisScript limitScript; + + @Autowired + public void setRedisTemplate1(RedisTemplate redisTemplate) + { + this.redisTemplate = redisTemplate; + } + + @Autowired + public void setLimitScript(RedisScript limitScript) + { + this.limitScript = limitScript; + } + + @Before("@annotation(rateLimiter)") + public void doBefore(JoinPoint point, RateLimiter rateLimiter) throws Throwable + { + int time = rateLimiter.time(); + int count = rateLimiter.count(); + + String combineKey = getCombineKey(rateLimiter, point); + List keys = Collections.singletonList(combineKey); + try + { + Long number = redisTemplate.execute(limitScript, keys, count, time); + if (StringUtils.isNull(number) || number.intValue() > count) + { + throw new ServiceException("访问过于频繁,请稍候再试"); + } + log.info("限制请求'{}',当前请求'{}',缓存key'{}'", count, number.intValue(), combineKey); + } + catch (ServiceException e) + { + throw e; + } + catch (Exception e) + { + throw new RuntimeException("服务器限流异常,请稍候再试"); + } + } + + public String getCombineKey(RateLimiter rateLimiter, JoinPoint point) + { + StringBuffer stringBuffer = new StringBuffer(rateLimiter.key()); + if (rateLimiter.limitType() == LimitType.IP) + { + stringBuffer.append(IpUtils.getIpAddr(ServletUtils.getRequest())).append("-"); + } + MethodSignature signature = (MethodSignature) point.getSignature(); + Method method = signature.getMethod(); + Class targetClass = method.getDeclaringClass(); + stringBuffer.append(targetClass.getName()).append("-").append(method.getName()); + return stringBuffer.toString(); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java new file mode 100644 index 0000000..ea5b954 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java @@ -0,0 +1,30 @@ +package com.ruoyi.framework.config; + +import java.util.TimeZone; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.EnableAspectJAutoProxy; + +/** + * 程序注解配置 + * + * @author #author# + */ +@Configuration +// 表示通过aop框架暴露该代理对象,AopContext能够访问 +@EnableAspectJAutoProxy(exposeProxy = true) +// 指定要扫描的Mapper类的包的路径 +@MapperScan("com.ruoyi.**.mapper") +public class ApplicationConfig +{ + /** + * 时区配置 + */ + @Bean + public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() + { + return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.timeZone(TimeZone.getDefault()); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java new file mode 100644 index 0000000..30e7909 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java @@ -0,0 +1,83 @@ +package com.ruoyi.framework.config; + +import java.util.Properties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import com.google.code.kaptcha.impl.DefaultKaptcha; +import com.google.code.kaptcha.util.Config; +import static com.google.code.kaptcha.Constants.*; + +/** + * 验证码配置 + * + * @author #author# + */ +@Configuration +public class CaptchaConfig +{ + @Bean(name = "captchaProducer") + public DefaultKaptcha getKaptchaBean() + { + DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); + Properties properties = new Properties(); + // 是否有边框 默认为true 我们可以自己设置yes,no + properties.setProperty(KAPTCHA_BORDER, "yes"); + // 验证码文本字符颜色 默认为Color.BLACK + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black"); + // 验证码图片宽度 默认为200 + properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160"); + // 验证码图片高度 默认为50 + properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60"); + // 验证码文本字符大小 默认为40 + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38"); + // KAPTCHA_SESSION_KEY + properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode"); + // 验证码文本字符长度 默认为5 + properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4"); + // 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize) + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier"); + // 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy + properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy"); + Config config = new Config(properties); + defaultKaptcha.setConfig(config); + return defaultKaptcha; + } + + @Bean(name = "captchaProducerMath") + public DefaultKaptcha getKaptchaBeanMath() + { + DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); + Properties properties = new Properties(); + // 是否有边框 默认为true 我们可以自己设置yes,no + properties.setProperty(KAPTCHA_BORDER, "yes"); + // 边框颜色 默认为Color.BLACK + properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90"); + // 验证码文本字符颜色 默认为Color.BLACK + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue"); + // 验证码图片宽度 默认为200 + properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160"); + // 验证码图片高度 默认为50 + properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60"); + // 验证码文本字符大小 默认为40 + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35"); + // KAPTCHA_SESSION_KEY + properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath"); + // 验证码文本生成器 + properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.ruoyi.framework.config.KaptchaTextCreator"); + // 验证码文本字符间距 默认为2 + properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3"); + // 验证码文本字符长度 默认为5 + properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6"); + // 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize) + properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier"); + // 验证码噪点颜色 默认为Color.BLACK + properties.setProperty(KAPTCHA_NOISE_COLOR, "white"); + // 干扰实现类 + properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise"); + // 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy + properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy"); + Config config = new Config(properties); + defaultKaptcha.setConfig(config); + return defaultKaptcha; + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java new file mode 100644 index 0000000..d7c8c01 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java @@ -0,0 +1,126 @@ +package com.ruoyi.framework.config; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.sql.DataSource; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import com.alibaba.druid.pool.DruidDataSource; +import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder; +import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties; +import com.alibaba.druid.util.Utils; +import com.ruoyi.common.enums.DataSourceType; +import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.framework.config.properties.DruidProperties; +import com.ruoyi.framework.datasource.DynamicDataSource; + +/** + * druid 配置多数据源 + * + * @author #author# + */ +@Configuration +public class DruidConfig +{ + @Bean + @ConfigurationProperties("spring.datasource.druid.master") + public DataSource masterDataSource(DruidProperties druidProperties) + { + DruidDataSource dataSource = DruidDataSourceBuilder.create().build(); + return druidProperties.dataSource(dataSource); + } + + @Bean + @ConfigurationProperties("spring.datasource.druid.slave") + @ConditionalOnProperty(prefix = "spring.datasource.druid.slave", name = "enabled", havingValue = "true") + public DataSource slaveDataSource(DruidProperties druidProperties) + { + DruidDataSource dataSource = DruidDataSourceBuilder.create().build(); + return druidProperties.dataSource(dataSource); + } + + @Bean(name = "dynamicDataSource") + @Primary + public DynamicDataSource dataSource(DataSource masterDataSource) + { + Map targetDataSources = new HashMap<>(); + targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource); + setDataSource(targetDataSources, DataSourceType.SLAVE.name(), "slaveDataSource"); + return new DynamicDataSource(masterDataSource, targetDataSources); + } + + /** + * 设置数据源 + * + * @param targetDataSources 备选数据源集合 + * @param sourceName 数据源名称 + * @param beanName bean名称 + */ + public void setDataSource(Map targetDataSources, String sourceName, String beanName) + { + try + { + DataSource dataSource = SpringUtils.getBean(beanName); + targetDataSources.put(sourceName, dataSource); + } + catch (Exception e) + { + } + } + + /** + * 去除监控页面底部的广告 + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Bean + @ConditionalOnProperty(name = "spring.datasource.druid.statViewServlet.enabled", havingValue = "true") + public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties) + { + // 获取web监控页面的参数 + DruidStatProperties.StatViewServlet config = properties.getStatViewServlet(); + // 提取common.js的配置路径 + String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*"; + String commonJsPattern = pattern.replaceAll("\\*", "js/common.js"); + final String filePath = "support/http/resources/js/common.js"; + // 创建filter进行过滤 + Filter filter = new Filter() + { + @Override + public void init(javax.servlet.FilterConfig filterConfig) throws ServletException + { + } + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException + { + chain.doFilter(request, response); + // 重置缓冲区,响应头不会被重置 + response.resetBuffer(); + // 获取common.js + String text = Utils.readFromResource(filePath); + // 正则替换banner, 除去底部的广告信息 + text = text.replaceAll("
", ""); + text = text.replaceAll("powered.*?shrek.wang", ""); + response.getWriter().write(text); + } + @Override + public void destroy() + { + } + }; + FilterRegistrationBean registrationBean = new FilterRegistrationBean(); + registrationBean.setFilter(filter); + registrationBean.addUrlPatterns(commonJsPattern); + return registrationBean; + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..dd28464 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java @@ -0,0 +1,48 @@ +package com.ruoyi.framework.config; + +import java.nio.charset.Charset; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONReader; +import com.alibaba.fastjson2.JSONWriter; + +/** + * Redis使用FastJson序列化 + * + * @author #author# + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer +{ + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + public FastJson2JsonRedisSerializer(Class clazz) + { + super(); + this.clazz = clazz; + } + + @Override + public byte[] serialize(T t) throws SerializationException + { + if (t == null) + { + return new byte[0]; + } + return JSON.toJSONString(t, JSONWriter.Feature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + @Override + public T deserialize(byte[] bytes) throws SerializationException + { + if (bytes == null || bytes.length <= 0) + { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return JSON.parseObject(str, clazz, JSONReader.Feature.SupportAutoType); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java new file mode 100644 index 0000000..0029766 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java @@ -0,0 +1,58 @@ +package com.ruoyi.framework.config; + +import java.util.HashMap; +import java.util.Map; +import javax.servlet.DispatcherType; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import com.ruoyi.common.filter.RepeatableFilter; +import com.ruoyi.common.filter.XssFilter; +import com.ruoyi.common.utils.StringUtils; + +/** + * Filter配置 + * + * @author #author# + */ +@Configuration +public class FilterConfig +{ + @Value("${xss.excludes}") + private String excludes; + + @Value("${xss.urlPatterns}") + private String urlPatterns; + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Bean + @ConditionalOnProperty(value = "xss.enabled", havingValue = "true") + public FilterRegistrationBean xssFilterRegistration() + { + FilterRegistrationBean registration = new FilterRegistrationBean(); + registration.setDispatcherTypes(DispatcherType.REQUEST); + registration.setFilter(new XssFilter()); + registration.addUrlPatterns(StringUtils.split(urlPatterns, ",")); + registration.setName("xssFilter"); + registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE); + Map initParameters = new HashMap(); + initParameters.put("excludes", excludes); + registration.setInitParameters(initParameters); + return registration; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Bean + public FilterRegistrationBean someFilterRegistration() + { + FilterRegistrationBean registration = new FilterRegistrationBean(); + registration.setFilter(new RepeatableFilter()); + registration.addUrlPatterns("/*"); + registration.setName("repeatableFilter"); + registration.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE); + return registration; + } + +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java new file mode 100644 index 0000000..39059c1 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java @@ -0,0 +1,68 @@ +package com.ruoyi.framework.config; + +import java.util.Random; +import com.google.code.kaptcha.text.impl.DefaultTextCreator; + +/** + * 验证码文本生成器 + * + * @author #author# + */ +public class KaptchaTextCreator extends DefaultTextCreator +{ + private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(","); + + @Override + public String getText() + { + Integer result = 0; + Random random = new Random(); + int x = random.nextInt(10); + int y = random.nextInt(10); + StringBuilder suChinese = new StringBuilder(); + int randomoperands = random.nextInt(3); + if (randomoperands == 0) + { + result = x * y; + suChinese.append(CNUMBERS[x]); + suChinese.append("*"); + suChinese.append(CNUMBERS[y]); + } + else if (randomoperands == 1) + { + if ((x != 0) && y % x == 0) + { + result = y / x; + suChinese.append(CNUMBERS[y]); + suChinese.append("/"); + suChinese.append(CNUMBERS[x]); + } + else + { + result = x + y; + suChinese.append(CNUMBERS[x]); + suChinese.append("+"); + suChinese.append(CNUMBERS[y]); + } + } + else + { + if (x >= y) + { + result = x - y; + suChinese.append(CNUMBERS[x]); + suChinese.append("-"); + suChinese.append(CNUMBERS[y]); + } + else + { + result = y - x; + suChinese.append(CNUMBERS[y]); + suChinese.append("-"); + suChinese.append(CNUMBERS[x]); + } + } + suChinese.append("=?@" + result); + return suChinese.toString(); + } +} \ No newline at end of file diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MybatisPlusConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MybatisPlusConfig.java new file mode 100644 index 0000000..11123ee --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/MybatisPlusConfig.java @@ -0,0 +1,62 @@ +package com.ruoyi.framework.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +/** + * Mybatis Plus 配置 + * + * @author 明媒婚恋服务有限公司 + */ +@EnableTransactionManagement(proxyTargetClass = true) +@Configuration +public class MybatisPlusConfig +{ + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() + { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + // 分页插件 + interceptor.addInnerInterceptor(paginationInnerInterceptor()); + // 乐观锁插件 + interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor()); + // 阻断插件 +// interceptor.addInnerInterceptor(blockAttackInnerInterceptor()); + return interceptor; + } + + /** + * 分页插件,自动识别数据库类型 https://baomidou.com/guide/interceptor-pagination.html + */ + public PaginationInnerInterceptor paginationInnerInterceptor() + { + PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(); + // 设置数据库类型为mysql + paginationInnerInterceptor.setDbType(DbType.MYSQL); + // 设置最大单页限制数量,默认 500 条,-1 不受限制 + paginationInnerInterceptor.setMaxLimit(-1L); + return paginationInnerInterceptor; + } + + /** + * 乐观锁插件 https://baomidou.com/guide/interceptor-optimistic-locker.html + */ + public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor() + { + return new OptimisticLockerInnerInterceptor(); + } + + /** + * 如果是对全表的删除或更新操作,就会终止该操作 https://baomidou.com/guide/interceptor-block-attack.html + */ + public BlockAttackInnerInterceptor blockAttackInnerInterceptor() + { + return new BlockAttackInnerInterceptor(); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java new file mode 100644 index 0000000..673d2a4 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java @@ -0,0 +1,69 @@ +package com.ruoyi.framework.config; + +import org.springframework.cache.annotation.CachingConfigurerSupport; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.script.DefaultRedisScript; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * redis配置 + * + * @author #author# + */ +@Configuration +@EnableCaching +public class RedisConfig extends CachingConfigurerSupport +{ + @Bean + @SuppressWarnings(value = { "unchecked", "rawtypes" }) + public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) + { + RedisTemplate template = new RedisTemplate<>(); + template.setConnectionFactory(connectionFactory); + + FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class); + + // 使用StringRedisSerializer来序列化和反序列化redis的key值 + template.setKeySerializer(new StringRedisSerializer()); + template.setValueSerializer(serializer); + + // Hash的key也采用StringRedisSerializer的序列化方式 + template.setHashKeySerializer(new StringRedisSerializer()); + template.setHashValueSerializer(serializer); + + template.afterPropertiesSet(); + return template; + } + + @Bean + public DefaultRedisScript limitScript() + { + DefaultRedisScript redisScript = new DefaultRedisScript<>(); + redisScript.setScriptText(limitScriptText()); + redisScript.setResultType(Long.class); + return redisScript; + } + + /** + * 限流脚本 + */ + private String limitScriptText() + { + return "local key = KEYS[1]\n" + + "local count = tonumber(ARGV[1])\n" + + "local time = tonumber(ARGV[2])\n" + + "local current = redis.call('get', key);\n" + + "if current and tonumber(current) > count then\n" + + " return tonumber(current);\n" + + "end\n" + + "current = redis.call('incr', key)\n" + + "if tonumber(current) == 1 then\n" + + " redis.call('expire', key, time)\n" + + "end\n" + + "return tonumber(current);"; + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java new file mode 100644 index 0000000..ff274da --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java @@ -0,0 +1,73 @@ +package com.ruoyi.framework.config; + +import java.util.concurrent.TimeUnit; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.CacheControl; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import com.ruoyi.common.config.RuoYiConfig; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor; + +/** + * 通用配置 + * + * @author #author# + */ +@Configuration +public class ResourcesConfig implements WebMvcConfigurer +{ + @Autowired + private RepeatSubmitInterceptor repeatSubmitInterceptor; + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) + { + /** 本地文件上传路径 */ + registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**") + .addResourceLocations("file:" + RuoYiConfig.getProfile() + "/"); + + /** swagger配置 */ + registry.addResourceHandler("/swagger-ui/**") + .addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/") + .setCacheControl(CacheControl.maxAge(5, TimeUnit.HOURS).cachePublic());; + } + + /** + * 自定义拦截规则 + */ + @Override + public void addInterceptors(InterceptorRegistry registry) + { + registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**"); + } + + /** + * 跨域配置 + */ + @Bean + public CorsFilter corsFilter() + { + CorsConfiguration config = new CorsConfiguration(); + config.setAllowCredentials(true); + // 设置访问源地址 + config.addAllowedOriginPattern("*"); + // 设置访问源请求头 + config.addAllowedHeader("*"); + // 设置访问源请求方法 + config.addAllowedMethod("*"); + // 有效期 1800秒 + config.setMaxAge(1800L); + // 添加映射路径,拦截一切请求 + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", config); + // 返回新的CorsFilter + return new CorsFilter(source); + } +} \ No newline at end of file diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java new file mode 100644 index 0000000..9130b74 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java @@ -0,0 +1,148 @@ +package com.ruoyi.framework.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.security.web.authentication.logout.LogoutFilter; +import org.springframework.web.filter.CorsFilter; +import com.ruoyi.framework.config.properties.PermitAllUrlProperties; +import com.ruoyi.framework.security.filter.JwtAuthenticationTokenFilter; +import com.ruoyi.framework.security.handle.AuthenticationEntryPointImpl; +import com.ruoyi.framework.security.handle.LogoutSuccessHandlerImpl; + +/** + * spring security配置 + * + * @author #author# + */ +@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) +public class SecurityConfig extends WebSecurityConfigurerAdapter +{ + /** + * 自定义用户认证逻辑 + */ + @Autowired + private UserDetailsService userDetailsService; + + /** + * 认证失败处理类 + */ + @Autowired + private AuthenticationEntryPointImpl unauthorizedHandler; + + /** + * 退出处理类 + */ + @Autowired + private LogoutSuccessHandlerImpl logoutSuccessHandler; + + /** + * token认证过滤器 + */ + @Autowired + private JwtAuthenticationTokenFilter authenticationTokenFilter; + + /** + * 跨域过滤器 + */ + @Autowired + private CorsFilter corsFilter; + + /** + * 允许匿名访问的地址 + */ + @Autowired + private PermitAllUrlProperties permitAllUrl; + + /** + * 解决 无法直接注入 AuthenticationManager + * + * @return + * @throws Exception + */ + @Bean + @Override + public AuthenticationManager authenticationManagerBean() throws Exception + { + return super.authenticationManagerBean(); + } + + /** + * anyRequest | 匹配所有请求路径 + * access | SpringEl表达式结果为true时可以访问 + * anonymous | 匿名可以访问 + * denyAll | 用户不能访问 + * fullyAuthenticated | 用户完全认证可以访问(非remember-me下自动登录) + * hasAnyAuthority | 如果有参数,参数表示权限,则其中任何一个权限可以访问 + * hasAnyRole | 如果有参数,参数表示角色,则其中任何一个角色可以访问 + * hasAuthority | 如果有参数,参数表示权限,则其权限可以访问 + * hasIpAddress | 如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问 + * hasRole | 如果有参数,参数表示角色,则其角色可以访问 + * permitAll | 用户可以任意访问 + * rememberMe | 允许通过remember-me登录的用户访问 + * authenticated | 用户登录后可访问 + */ + @Override + protected void configure(HttpSecurity httpSecurity) throws Exception + { + // 注解标记允许匿名访问的url + ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry registry = httpSecurity.authorizeRequests(); + permitAllUrl.getUrls().forEach(url -> registry.antMatchers(url).permitAll()); + + httpSecurity + // CSRF禁用,因为不使用session + .csrf().disable() + // 禁用HTTP响应标头 + .headers().cacheControl().disable().and() + // 认证失败处理类 + .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and() + // 基于token,所以不需要session + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() + // 过滤请求 + .authorizeRequests() + // 对于登录login 注册register 验证码captchaImage 允许匿名访问 + .antMatchers("/login", "/register", "/captchaImage","/system/config/configKey/sys.account.registerUser").permitAll() + // 静态资源,可匿名访问 + .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll() + .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll() + // 除上面外的所有请求全部需要鉴权认证 + .anyRequest().authenticated() + .and() + .headers().frameOptions().disable(); + // 添加Logout filter + httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler); + // 添加JWT filter + httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); + // 添加CORS filter + httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class); + httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class); + } + + /** + * 强散列哈希加密实现 + */ + @Bean + public BCryptPasswordEncoder bCryptPasswordEncoder() + { + return new BCryptPasswordEncoder(); + } + + /** + * 身份认证接口 + */ + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception + { + auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder()); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ServerConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ServerConfig.java new file mode 100644 index 0000000..fedf97d --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ServerConfig.java @@ -0,0 +1,32 @@ +package com.ruoyi.framework.config; + +import javax.servlet.http.HttpServletRequest; +import org.springframework.stereotype.Component; +import com.ruoyi.common.utils.ServletUtils; + +/** + * 服务相关配置 + * + * @author #author# + */ +@Component +public class ServerConfig +{ + /** + * 获取完整的请求路径,包括:域名,端口,上下文访问路径 + * + * @return 服务地址 + */ + public String getUrl() + { + HttpServletRequest request = ServletUtils.getRequest(); + return getDomain(request); + } + + public static String getDomain(HttpServletRequest request) + { + StringBuffer url = request.getRequestURL(); + String contextPath = request.getServletContext().getContextPath(); + return url.delete(url.length() - request.getRequestURI().length(), url.length()).append(contextPath).toString(); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java new file mode 100644 index 0000000..7e46fa5 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java @@ -0,0 +1,63 @@ +package com.ruoyi.framework.config; + +import com.ruoyi.common.utils.Threads; +import org.apache.commons.lang3.concurrent.BasicThreadFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadPoolExecutor; + +/** + * 线程池配置 + * + * @author #author# + **/ +@Configuration +public class ThreadPoolConfig +{ + // 核心线程池大小 + private int corePoolSize = 50; + + // 最大可创建的线程数 + private int maxPoolSize = 200; + + // 队列最大长度 + private int queueCapacity = 1000; + + // 线程池维护线程所允许的空闲时间 + private int keepAliveSeconds = 300; + + @Bean(name = "threadPoolTaskExecutor") + public ThreadPoolTaskExecutor threadPoolTaskExecutor() + { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setMaxPoolSize(maxPoolSize); + executor.setCorePoolSize(corePoolSize); + executor.setQueueCapacity(queueCapacity); + executor.setKeepAliveSeconds(keepAliveSeconds); + // 线程池对拒绝任务(无线程可用)的处理策略 + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + return executor; + } + + /** + * 执行周期性或定时任务 + */ + @Bean(name = "scheduledExecutorService") + protected ScheduledExecutorService scheduledExecutorService() + { + return new ScheduledThreadPoolExecutor(corePoolSize, + new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(), + new ThreadPoolExecutor.CallerRunsPolicy()) + { + @Override + protected void afterExecute(Runnable r, Throwable t) + { + super.afterExecute(r, t); + Threads.printException(r, t); + } + }; + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java new file mode 100644 index 0000000..c007684 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java @@ -0,0 +1,77 @@ +package com.ruoyi.framework.config.properties; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import com.alibaba.druid.pool.DruidDataSource; + +/** + * druid 配置属性 + * + * @author #author# + */ +@Configuration +public class DruidProperties +{ + @Value("${spring.datasource.druid.initialSize}") + private int initialSize; + + @Value("${spring.datasource.druid.minIdle}") + private int minIdle; + + @Value("${spring.datasource.druid.maxActive}") + private int maxActive; + + @Value("${spring.datasource.druid.maxWait}") + private int maxWait; + + @Value("${spring.datasource.druid.timeBetweenEvictionRunsMillis}") + private int timeBetweenEvictionRunsMillis; + + @Value("${spring.datasource.druid.minEvictableIdleTimeMillis}") + private int minEvictableIdleTimeMillis; + + @Value("${spring.datasource.druid.maxEvictableIdleTimeMillis}") + private int maxEvictableIdleTimeMillis; + + @Value("${spring.datasource.druid.validationQuery}") + private String validationQuery; + + @Value("${spring.datasource.druid.testWhileIdle}") + private boolean testWhileIdle; + + @Value("${spring.datasource.druid.testOnBorrow}") + private boolean testOnBorrow; + + @Value("${spring.datasource.druid.testOnReturn}") + private boolean testOnReturn; + + public DruidDataSource dataSource(DruidDataSource datasource) + { + /** 配置初始化大小、最小、最大 */ + datasource.setInitialSize(initialSize); + datasource.setMaxActive(maxActive); + datasource.setMinIdle(minIdle); + + /** 配置获取连接等待超时的时间 */ + datasource.setMaxWait(maxWait); + + /** 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 */ + datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); + + /** 配置一个连接在池中最小、最大生存的时间,单位是毫秒 */ + datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); + datasource.setMaxEvictableIdleTimeMillis(maxEvictableIdleTimeMillis); + + /** + * 用来检测连接是否有效的sql,要求是一个查询语句,常用select 'x'。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。 + */ + datasource.setValidationQuery(validationQuery); + /** 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 */ + datasource.setTestWhileIdle(testWhileIdle); + /** 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 */ + datasource.setTestOnBorrow(testOnBorrow); + /** 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 */ + datasource.setTestOnReturn(testOnReturn); + return datasource; + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java new file mode 100644 index 0000000..36acaed --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java @@ -0,0 +1,72 @@ +package com.ruoyi.framework.config.properties; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.regex.Pattern; +import org.apache.commons.lang3.RegExUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.mvc.method.RequestMappingInfo; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; +import com.ruoyi.common.annotation.Anonymous; + +/** + * 设置Anonymous注解允许匿名访问的url + * + * @author #author# + */ +@Configuration +public class PermitAllUrlProperties implements InitializingBean, ApplicationContextAware +{ + private static final Pattern PATTERN = Pattern.compile("\\{(.*?)\\}"); + + private ApplicationContext applicationContext; + + private List urls = new ArrayList<>(); + + public String ASTERISK = "*"; + + @Override + public void afterPropertiesSet() + { + RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class); + Map map = mapping.getHandlerMethods(); + + map.keySet().forEach(info -> { + HandlerMethod handlerMethod = map.get(info); + + // 获取方法上边的注解 替代path variable 为 * + Anonymous method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Anonymous.class); + Optional.ofNullable(method).ifPresent(anonymous -> info.getPatternsCondition().getPatterns() + .forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK)))); + + // 获取类上边的注解, 替代path variable 为 * + Anonymous controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Anonymous.class); + Optional.ofNullable(controller).ifPresent(anonymous -> info.getPatternsCondition().getPatterns() + .forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK)))); + }); + } + + @Override + public void setApplicationContext(ApplicationContext context) throws BeansException + { + this.applicationContext = context; + } + + public List getUrls() + { + return urls; + } + + public void setUrls(List urls) + { + this.urls = urls; + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java new file mode 100644 index 0000000..443f727 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java @@ -0,0 +1,26 @@ +package com.ruoyi.framework.datasource; + +import java.util.Map; +import javax.sql.DataSource; +import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; + +/** + * 动态数据源 + * + * @author #author# + */ +public class DynamicDataSource extends AbstractRoutingDataSource +{ + public DynamicDataSource(DataSource defaultTargetDataSource, Map targetDataSources) + { + super.setDefaultTargetDataSource(defaultTargetDataSource); + super.setTargetDataSources(targetDataSources); + super.afterPropertiesSet(); + } + + @Override + protected Object determineCurrentLookupKey() + { + return DynamicDataSourceContextHolder.getDataSourceType(); + } +} \ No newline at end of file diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java new file mode 100644 index 0000000..ce4ab53 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java @@ -0,0 +1,45 @@ +package com.ruoyi.framework.datasource; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 数据源切换处理 + * + * @author #author# + */ +public class DynamicDataSourceContextHolder +{ + public static final Logger log = LoggerFactory.getLogger(DynamicDataSourceContextHolder.class); + + /** + * 使用ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本, + * 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。 + */ + private static final ThreadLocal CONTEXT_HOLDER = new ThreadLocal<>(); + + /** + * 设置数据源的变量 + */ + public static void setDataSourceType(String dsType) + { + log.info("切换到{}数据源", dsType); + CONTEXT_HOLDER.set(dsType); + } + + /** + * 获得数据源的变量 + */ + public static String getDataSourceType() + { + return CONTEXT_HOLDER.get(); + } + + /** + * 清空数据源变量 + */ + public static void clearDataSourceType() + { + CONTEXT_HOLDER.remove(); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java new file mode 100644 index 0000000..316110a --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java @@ -0,0 +1,55 @@ +package com.ruoyi.framework.interceptor; + +import java.lang.reflect.Method; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.springframework.stereotype.Component; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; +import com.alibaba.fastjson2.JSON; +import com.ruoyi.common.annotation.RepeatSubmit; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.utils.ServletUtils; + +/** + * 防止重复提交拦截器 + * + * @author #author# + */ +@Component +public abstract class RepeatSubmitInterceptor implements HandlerInterceptor +{ + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception + { + if (handler instanceof HandlerMethod) + { + HandlerMethod handlerMethod = (HandlerMethod) handler; + Method method = handlerMethod.getMethod(); + RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class); + if (annotation != null) + { + if (this.isRepeatSubmit(request, annotation)) + { + AjaxResult ajaxResult = AjaxResult.error(annotation.message()); + ServletUtils.renderString(response, JSON.toJSONString(ajaxResult)); + return false; + } + } + return true; + } + else + { + return true; + } + } + + /** + * 验证是否重复提交由子类实现具体的防重复提交的规则 + * + * @param request + * @return + * @throws Exception + */ + public abstract boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation); +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java new file mode 100644 index 0000000..b735978 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java @@ -0,0 +1,110 @@ +package com.ruoyi.framework.interceptor.impl; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import javax.servlet.http.HttpServletRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import com.alibaba.fastjson2.JSON; +import com.ruoyi.common.annotation.RepeatSubmit; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.filter.RepeatedlyRequestWrapper; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.http.HttpHelper; +import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor; + +/** + * 判断请求url和数据是否和上一次相同, + * 如果和上次相同,则是重复提交表单。 有效时间为10秒内。 + * + * @author #author# + */ +@Component +public class SameUrlDataInterceptor extends RepeatSubmitInterceptor +{ + public final String REPEAT_PARAMS = "repeatParams"; + + public final String REPEAT_TIME = "repeatTime"; + + // 令牌自定义标识 + @Value("${token.header}") + private String header; + + @Autowired + private RedisCache redisCache; + + @SuppressWarnings("unchecked") + @Override + public boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation) + { + String nowParams = ""; + if (request instanceof RepeatedlyRequestWrapper) + { + RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request; + nowParams = HttpHelper.getBodyString(repeatedlyRequest); + } + + // body参数为空,获取Parameter的数据 + if (StringUtils.isEmpty(nowParams)) + { + nowParams = JSON.toJSONString(request.getParameterMap()); + } + Map nowDataMap = new HashMap(); + nowDataMap.put(REPEAT_PARAMS, nowParams); + nowDataMap.put(REPEAT_TIME, System.currentTimeMillis()); + + // 请求地址(作为存放cache的key值) + String url = request.getRequestURI(); + + // 唯一值(没有消息头则使用请求地址) + String submitKey = StringUtils.trimToEmpty(request.getHeader(header)); + + // 唯一标识(指定key + url + 消息头) + String cacheRepeatKey = CacheConstants.REPEAT_SUBMIT_KEY + url + submitKey; + + Object sessionObj = redisCache.getCacheObject(cacheRepeatKey); + if (sessionObj != null) + { + Map sessionMap = (Map) sessionObj; + if (sessionMap.containsKey(url)) + { + Map preDataMap = (Map) sessionMap.get(url); + if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap, annotation.interval())) + { + return true; + } + } + } + Map cacheMap = new HashMap(); + cacheMap.put(url, nowDataMap); + redisCache.setCacheObject(cacheRepeatKey, cacheMap, annotation.interval(), TimeUnit.MILLISECONDS); + return false; + } + + /** + * 判断参数是否相同 + */ + private boolean compareParams(Map nowMap, Map preMap) + { + String nowParams = (String) nowMap.get(REPEAT_PARAMS); + String preParams = (String) preMap.get(REPEAT_PARAMS); + return nowParams.equals(preParams); + } + + /** + * 判断两次间隔时间 + */ + private boolean compareTime(Map nowMap, Map preMap, int interval) + { + long time1 = (Long) nowMap.get(REPEAT_TIME); + long time2 = (Long) preMap.get(REPEAT_TIME); + if ((time1 - time2) < interval) + { + return true; + } + return false; + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/AsyncManager.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/AsyncManager.java new file mode 100644 index 0000000..cebe371 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/AsyncManager.java @@ -0,0 +1,55 @@ +package com.ruoyi.framework.manager; + +import java.util.TimerTask; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import com.ruoyi.common.utils.Threads; +import com.ruoyi.common.utils.spring.SpringUtils; + +/** + * 异步任务管理器 + * + * @author #author# + */ +public class AsyncManager +{ + /** + * 操作延迟10毫秒 + */ + private final int OPERATE_DELAY_TIME = 10; + + /** + * 异步操作任务调度线程池 + */ + private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService"); + + /** + * 单例模式 + */ + private AsyncManager(){} + + private static AsyncManager me = new AsyncManager(); + + public static AsyncManager me() + { + return me; + } + + /** + * 执行任务 + * + * @param task 任务 + */ + public void execute(TimerTask task) + { + executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS); + } + + /** + * 停止任务线程池 + */ + public void shutdown() + { + Threads.shutdownAndAwaitTermination(executor); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java new file mode 100644 index 0000000..97555a1 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java @@ -0,0 +1,39 @@ +package com.ruoyi.framework.manager; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; +import javax.annotation.PreDestroy; + +/** + * 确保应用退出时能关闭后台线程 + * + * @author #author# + */ +@Component +public class ShutdownManager +{ + private static final Logger logger = LoggerFactory.getLogger("sys-user"); + + @PreDestroy + public void destroy() + { + shutdownAsyncManager(); + } + + /** + * 停止异步执行任务 + */ + private void shutdownAsyncManager() + { + try + { + logger.info("====关闭后台任务任务线程池===="); + AsyncManager.me().shutdown(); + } + catch (Exception e) + { + logger.error(e.getMessage(), e); + } + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java new file mode 100644 index 0000000..ecf3a60 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java @@ -0,0 +1,102 @@ +package com.ruoyi.framework.manager.factory; + +import java.util.TimerTask; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.utils.LogUtils; +import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.ip.AddressUtils; +import com.ruoyi.common.utils.ip.IpUtils; +import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.system.domain.SysLogininfor; +import com.ruoyi.system.domain.SysOperLog; +import com.ruoyi.system.service.ISysLogininforService; +import com.ruoyi.system.service.ISysOperLogService; +import eu.bitwalker.useragentutils.UserAgent; + +/** + * 异步工厂(产生任务用) + * + * @author #author# + */ +public class AsyncFactory +{ + private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user"); + + /** + * 记录登录信息 + * + * @param username 用户名 + * @param status 状态 + * @param message 消息 + * @param args 列表 + * @return 任务task + */ + public static TimerTask recordLogininfor(final String username, final String status, final String message, + final Object... args) + { + final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent")); + final String ip = IpUtils.getIpAddr(ServletUtils.getRequest()); + return new TimerTask() + { + @Override + public void run() + { + String address = AddressUtils.getRealAddressByIP(ip); + StringBuilder s = new StringBuilder(); + s.append(LogUtils.getBlock(ip)); + s.append(address); + s.append(LogUtils.getBlock(username)); + s.append(LogUtils.getBlock(status)); + s.append(LogUtils.getBlock(message)); + // 打印信息到日志 + sys_user_logger.info(s.toString(), args); + // 获取客户端操作系统 + String os = userAgent.getOperatingSystem().getName(); + // 获取客户端浏览器 + String browser = userAgent.getBrowser().getName(); + // 封装对象 + SysLogininfor logininfor = new SysLogininfor(); + logininfor.setUserName(username); + logininfor.setIpaddr(ip); + logininfor.setLoginLocation(address); + logininfor.setBrowser(browser); + logininfor.setOs(os); + logininfor.setMsg(message); + // 日志状态 + if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) + { + logininfor.setStatus(Constants.SUCCESS); + } + else if (Constants.LOGIN_FAIL.equals(status)) + { + logininfor.setStatus(Constants.FAIL); + } + // 插入数据 + SpringUtils.getBean(ISysLogininforService.class).insertLogininfor(logininfor); + } + }; + } + + /** + * 操作日志记录 + * + * @param operLog 操作日志信息 + * @return 任务task + */ + public static TimerTask recordOper(final SysOperLog operLog) + { + return new TimerTask() + { + @Override + public void run() + { + // 远程查询操作地点 + operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp())); + SpringUtils.getBean(ISysOperLogService.class).insertOperlog(operLog); + } + }; + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/AuthenticationContextHolder.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/AuthenticationContextHolder.java new file mode 100644 index 0000000..cbf9b79 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/AuthenticationContextHolder.java @@ -0,0 +1,28 @@ +package com.ruoyi.framework.security.context; + +import org.springframework.security.core.Authentication; + +/** + * 身份验证信息 + * + * @author #author# + */ +public class AuthenticationContextHolder +{ + private static final ThreadLocal contextHolder = new ThreadLocal<>(); + + public static Authentication getContext() + { + return contextHolder.get(); + } + + public static void setContext(Authentication context) + { + contextHolder.set(context); + } + + public static void clearContext() + { + contextHolder.remove(); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/PermissionContextHolder.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/PermissionContextHolder.java new file mode 100644 index 0000000..fa1fd94 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/PermissionContextHolder.java @@ -0,0 +1,27 @@ +package com.ruoyi.framework.security.context; + +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import com.ruoyi.common.core.text.Convert; + +/** + * 权限信息 + * + * @author #author# + */ +public class PermissionContextHolder +{ + private static final String PERMISSION_CONTEXT_ATTRIBUTES = "PERMISSION_CONTEXT"; + + public static void setContext(String permission) + { + RequestContextHolder.currentRequestAttributes().setAttribute(PERMISSION_CONTEXT_ATTRIBUTES, permission, + RequestAttributes.SCOPE_REQUEST); + } + + public static String getContext() + { + return Convert.toStr(RequestContextHolder.currentRequestAttributes().getAttribute(PERMISSION_CONTEXT_ATTRIBUTES, + RequestAttributes.SCOPE_REQUEST)); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java new file mode 100644 index 0000000..b2add6f --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java @@ -0,0 +1,44 @@ +package com.ruoyi.framework.security.filter; + +import java.io.IOException; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.framework.web.service.TokenService; + +/** + * token过滤器 验证token有效性 + * + * @author #author# + */ +@Component +public class JwtAuthenticationTokenFilter extends OncePerRequestFilter +{ + @Autowired + private TokenService tokenService; + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) + throws ServletException, IOException + { + LoginUser loginUser = tokenService.getLoginUser(request); + if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication())) + { + tokenService.verifyToken(loginUser); + UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities()); + authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + SecurityContextHolder.getContext().setAuthentication(authenticationToken); + } + chain.doFilter(request, response); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java new file mode 100644 index 0000000..3d732c1 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java @@ -0,0 +1,34 @@ +package com.ruoyi.framework.security.handle; + +import java.io.IOException; +import java.io.Serializable; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.stereotype.Component; +import com.alibaba.fastjson2.JSON; +import com.ruoyi.common.constant.HttpStatus; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.StringUtils; + +/** + * 认证失败处理类 返回未授权 + * + * @author #author# + */ +@Component +public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint, Serializable +{ + private static final long serialVersionUID = -8970718410437077606L; + + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) + throws IOException + { + int code = HttpStatus.UNAUTHORIZED; + String msg = StringUtils.format("请求访问:{},认证失败,无法访问系统资源", request.getRequestURI()); + ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(code, msg))); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java new file mode 100644 index 0000000..322a09d --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java @@ -0,0 +1,52 @@ +package com.ruoyi.framework.security.handle; + +import java.io.IOException; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; +import com.alibaba.fastjson2.JSON; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.framework.manager.AsyncManager; +import com.ruoyi.framework.manager.factory.AsyncFactory; +import com.ruoyi.framework.web.service.TokenService; + +/** + * 自定义退出处理类 返回成功 + * + * @author #author# + */ +@Configuration +public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler +{ + @Autowired + private TokenService tokenService; + + /** + * 退出处理 + * + * @return + */ + @Override + public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) + throws IOException, ServletException + { + LoginUser loginUser = tokenService.getLoginUser(request); + if (StringUtils.isNotNull(loginUser)) + { + String userName = loginUser.getUsername(); + // 删除用户缓存记录 + tokenService.delLoginUser(loginUser.getToken()); + // 记录用户退出日志 + AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGOUT, "退出成功")); + } + ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.success("退出成功"))); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java new file mode 100644 index 0000000..99165fb --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java @@ -0,0 +1,240 @@ +package com.ruoyi.framework.web.domain; + +import java.net.UnknownHostException; +import java.util.LinkedList; +import java.util.List; +import java.util.Properties; +import com.ruoyi.common.utils.Arith; +import com.ruoyi.common.utils.ip.IpUtils; +import com.ruoyi.framework.web.domain.server.Cpu; +import com.ruoyi.framework.web.domain.server.Jvm; +import com.ruoyi.framework.web.domain.server.Mem; +import com.ruoyi.framework.web.domain.server.Sys; +import com.ruoyi.framework.web.domain.server.SysFile; +import oshi.SystemInfo; +import oshi.hardware.CentralProcessor; +import oshi.hardware.CentralProcessor.TickType; +import oshi.hardware.GlobalMemory; +import oshi.hardware.HardwareAbstractionLayer; +import oshi.software.os.FileSystem; +import oshi.software.os.OSFileStore; +import oshi.software.os.OperatingSystem; +import oshi.util.Util; + +/** + * 服务器相关信息 + * + * @author #author# + */ +public class Server +{ + private static final int OSHI_WAIT_SECOND = 1000; + + /** + * CPU相关信息 + */ + private Cpu cpu = new Cpu(); + + /** + * 內存相关信息 + */ + private Mem mem = new Mem(); + + /** + * JVM相关信息 + */ + private Jvm jvm = new Jvm(); + + /** + * 服务器相关信息 + */ + private Sys sys = new Sys(); + + /** + * 磁盘相关信息 + */ + private List sysFiles = new LinkedList(); + + public Cpu getCpu() + { + return cpu; + } + + public void setCpu(Cpu cpu) + { + this.cpu = cpu; + } + + public Mem getMem() + { + return mem; + } + + public void setMem(Mem mem) + { + this.mem = mem; + } + + public Jvm getJvm() + { + return jvm; + } + + public void setJvm(Jvm jvm) + { + this.jvm = jvm; + } + + public Sys getSys() + { + return sys; + } + + public void setSys(Sys sys) + { + this.sys = sys; + } + + public List getSysFiles() + { + return sysFiles; + } + + public void setSysFiles(List sysFiles) + { + this.sysFiles = sysFiles; + } + + public void copyTo() throws Exception + { + SystemInfo si = new SystemInfo(); + HardwareAbstractionLayer hal = si.getHardware(); + + setCpuInfo(hal.getProcessor()); + + setMemInfo(hal.getMemory()); + + setSysInfo(); + + setJvmInfo(); + + setSysFiles(si.getOperatingSystem()); + } + + /** + * 设置CPU信息 + */ + private void setCpuInfo(CentralProcessor processor) + { + // CPU信息 + long[] prevTicks = processor.getSystemCpuLoadTicks(); + Util.sleep(OSHI_WAIT_SECOND); + long[] ticks = processor.getSystemCpuLoadTicks(); + long nice = ticks[TickType.NICE.getIndex()] - prevTicks[TickType.NICE.getIndex()]; + long irq = ticks[TickType.IRQ.getIndex()] - prevTicks[TickType.IRQ.getIndex()]; + long softirq = ticks[TickType.SOFTIRQ.getIndex()] - prevTicks[TickType.SOFTIRQ.getIndex()]; + long steal = ticks[TickType.STEAL.getIndex()] - prevTicks[TickType.STEAL.getIndex()]; + long cSys = ticks[TickType.SYSTEM.getIndex()] - prevTicks[TickType.SYSTEM.getIndex()]; + long user = ticks[TickType.USER.getIndex()] - prevTicks[TickType.USER.getIndex()]; + long iowait = ticks[TickType.IOWAIT.getIndex()] - prevTicks[TickType.IOWAIT.getIndex()]; + long idle = ticks[TickType.IDLE.getIndex()] - prevTicks[TickType.IDLE.getIndex()]; + long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal; + cpu.setCpuNum(processor.getLogicalProcessorCount()); + cpu.setTotal(totalCpu); + cpu.setSys(cSys); + cpu.setUsed(user); + cpu.setWait(iowait); + cpu.setFree(idle); + } + + /** + * 设置内存信息 + */ + private void setMemInfo(GlobalMemory memory) + { + mem.setTotal(memory.getTotal()); + mem.setUsed(memory.getTotal() - memory.getAvailable()); + mem.setFree(memory.getAvailable()); + } + + /** + * 设置服务器信息 + */ + private void setSysInfo() + { + Properties props = System.getProperties(); + sys.setComputerName(IpUtils.getHostName()); + sys.setComputerIp(IpUtils.getHostIp()); + sys.setOsName(props.getProperty("os.name")); + sys.setOsArch(props.getProperty("os.arch")); + sys.setUserDir(props.getProperty("user.dir")); + } + + /** + * 设置Java虚拟机 + */ + private void setJvmInfo() throws UnknownHostException + { + Properties props = System.getProperties(); + jvm.setTotal(Runtime.getRuntime().totalMemory()); + jvm.setMax(Runtime.getRuntime().maxMemory()); + jvm.setFree(Runtime.getRuntime().freeMemory()); + jvm.setVersion(props.getProperty("java.version")); + jvm.setHome(props.getProperty("java.home")); + } + + /** + * 设置磁盘信息 + */ + private void setSysFiles(OperatingSystem os) + { + FileSystem fileSystem = os.getFileSystem(); + List fsArray = fileSystem.getFileStores(); + for (OSFileStore fs : fsArray) + { + long free = fs.getUsableSpace(); + long total = fs.getTotalSpace(); + long used = total - free; + SysFile sysFile = new SysFile(); + sysFile.setDirName(fs.getMount()); + sysFile.setSysTypeName(fs.getType()); + sysFile.setTypeName(fs.getName()); + sysFile.setTotal(convertFileSize(total)); + sysFile.setFree(convertFileSize(free)); + sysFile.setUsed(convertFileSize(used)); + sysFile.setUsage(Arith.mul(Arith.div(used, total, 4), 100)); + sysFiles.add(sysFile); + } + } + + /** + * 字节转换 + * + * @param size 字节大小 + * @return 转换后值 + */ + public String convertFileSize(long size) + { + long kb = 1024; + long mb = kb * 1024; + long gb = mb * 1024; + if (size >= gb) + { + return String.format("%.1f GB", (float) size / gb); + } + else if (size >= mb) + { + float f = (float) size / mb; + return String.format(f > 100 ? "%.0f MB" : "%.1f MB", f); + } + else if (size >= kb) + { + float f = (float) size / kb; + return String.format(f > 100 ? "%.0f KB" : "%.1f KB", f); + } + else + { + return String.format("%d B", size); + } + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java new file mode 100644 index 0000000..9a775a3 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java @@ -0,0 +1,101 @@ +package com.ruoyi.framework.web.domain.server; + +import com.ruoyi.common.utils.Arith; + +/** + * CPU相关信息 + * + * @author #author# + */ +public class Cpu +{ + /** + * 核心数 + */ + private int cpuNum; + + /** + * CPU总的使用率 + */ + private double total; + + /** + * CPU系统使用率 + */ + private double sys; + + /** + * CPU用户使用率 + */ + private double used; + + /** + * CPU当前等待率 + */ + private double wait; + + /** + * CPU当前空闲率 + */ + private double free; + + public int getCpuNum() + { + return cpuNum; + } + + public void setCpuNum(int cpuNum) + { + this.cpuNum = cpuNum; + } + + public double getTotal() + { + return Arith.round(Arith.mul(total, 100), 2); + } + + public void setTotal(double total) + { + this.total = total; + } + + public double getSys() + { + return Arith.round(Arith.mul(sys / total, 100), 2); + } + + public void setSys(double sys) + { + this.sys = sys; + } + + public double getUsed() + { + return Arith.round(Arith.mul(used / total, 100), 2); + } + + public void setUsed(double used) + { + this.used = used; + } + + public double getWait() + { + return Arith.round(Arith.mul(wait / total, 100), 2); + } + + public void setWait(double wait) + { + this.wait = wait; + } + + public double getFree() + { + return Arith.round(Arith.mul(free / total, 100), 2); + } + + public void setFree(double free) + { + this.free = free; + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java new file mode 100644 index 0000000..87910e5 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java @@ -0,0 +1,130 @@ +package com.ruoyi.framework.web.domain.server; + +import java.lang.management.ManagementFactory; +import com.ruoyi.common.utils.Arith; +import com.ruoyi.common.utils.DateUtils; + +/** + * JVM相关信息 + * + * @author #author# + */ +public class Jvm +{ + /** + * 当前JVM占用的内存总数(M) + */ + private double total; + + /** + * JVM最大可用内存总数(M) + */ + private double max; + + /** + * JVM空闲内存(M) + */ + private double free; + + /** + * JDK版本 + */ + private String version; + + /** + * JDK路径 + */ + private String home; + + public double getTotal() + { + return Arith.div(total, (1024 * 1024), 2); + } + + public void setTotal(double total) + { + this.total = total; + } + + public double getMax() + { + return Arith.div(max, (1024 * 1024), 2); + } + + public void setMax(double max) + { + this.max = max; + } + + public double getFree() + { + return Arith.div(free, (1024 * 1024), 2); + } + + public void setFree(double free) + { + this.free = free; + } + + public double getUsed() + { + return Arith.div(total - free, (1024 * 1024), 2); + } + + public double getUsage() + { + return Arith.mul(Arith.div(total - free, total, 4), 100); + } + + /** + * 获取JDK名称 + */ + public String getName() + { + return ManagementFactory.getRuntimeMXBean().getVmName(); + } + + public String getVersion() + { + return version; + } + + public void setVersion(String version) + { + this.version = version; + } + + public String getHome() + { + return home; + } + + public void setHome(String home) + { + this.home = home; + } + + /** + * JDK启动时间 + */ + public String getStartTime() + { + return DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, DateUtils.getServerStartDate()); + } + + /** + * JDK运行时间 + */ + public String getRunTime() + { + return DateUtils.getDatePoor(DateUtils.getNowDate(), DateUtils.getServerStartDate()); + } + + /** + * 运行参数 + */ + public String getInputArgs() + { + return ManagementFactory.getRuntimeMXBean().getInputArguments().toString(); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java new file mode 100644 index 0000000..f58afda --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java @@ -0,0 +1,61 @@ +package com.ruoyi.framework.web.domain.server; + +import com.ruoyi.common.utils.Arith; + +/** + * 內存相关信息 + * + * @author #author# + */ +public class Mem +{ + /** + * 内存总量 + */ + private double total; + + /** + * 已用内存 + */ + private double used; + + /** + * 剩余内存 + */ + private double free; + + public double getTotal() + { + return Arith.div(total, (1024 * 1024 * 1024), 2); + } + + public void setTotal(long total) + { + this.total = total; + } + + public double getUsed() + { + return Arith.div(used, (1024 * 1024 * 1024), 2); + } + + public void setUsed(long used) + { + this.used = used; + } + + public double getFree() + { + return Arith.div(free, (1024 * 1024 * 1024), 2); + } + + public void setFree(long free) + { + this.free = free; + } + + public double getUsage() + { + return Arith.mul(Arith.div(used, total, 4), 100); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java new file mode 100644 index 0000000..d401a1c --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java @@ -0,0 +1,84 @@ +package com.ruoyi.framework.web.domain.server; + +/** + * 系统相关信息 + * + * @author #author# + */ +public class Sys +{ + /** + * 服务器名称 + */ + private String computerName; + + /** + * 服务器Ip + */ + private String computerIp; + + /** + * 项目路径 + */ + private String userDir; + + /** + * 操作系统 + */ + private String osName; + + /** + * 系统架构 + */ + private String osArch; + + public String getComputerName() + { + return computerName; + } + + public void setComputerName(String computerName) + { + this.computerName = computerName; + } + + public String getComputerIp() + { + return computerIp; + } + + public void setComputerIp(String computerIp) + { + this.computerIp = computerIp; + } + + public String getUserDir() + { + return userDir; + } + + public void setUserDir(String userDir) + { + this.userDir = userDir; + } + + public String getOsName() + { + return osName; + } + + public void setOsName(String osName) + { + this.osName = osName; + } + + public String getOsArch() + { + return osArch; + } + + public void setOsArch(String osArch) + { + this.osArch = osArch; + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java new file mode 100644 index 0000000..686d4ab --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java @@ -0,0 +1,114 @@ +package com.ruoyi.framework.web.domain.server; + +/** + * 系统文件相关信息 + * + * @author #author# + */ +public class SysFile +{ + /** + * 盘符路径 + */ + private String dirName; + + /** + * 盘符类型 + */ + private String sysTypeName; + + /** + * 文件类型 + */ + private String typeName; + + /** + * 总大小 + */ + private String total; + + /** + * 剩余大小 + */ + private String free; + + /** + * 已经使用量 + */ + private String used; + + /** + * 资源的使用率 + */ + private double usage; + + public String getDirName() + { + return dirName; + } + + public void setDirName(String dirName) + { + this.dirName = dirName; + } + + public String getSysTypeName() + { + return sysTypeName; + } + + public void setSysTypeName(String sysTypeName) + { + this.sysTypeName = sysTypeName; + } + + public String getTypeName() + { + return typeName; + } + + public void setTypeName(String typeName) + { + this.typeName = typeName; + } + + public String getTotal() + { + return total; + } + + public void setTotal(String total) + { + this.total = total; + } + + public String getFree() + { + return free; + } + + public void setFree(String free) + { + this.free = free; + } + + public String getUsed() + { + return used; + } + + public void setUsed(String used) + { + this.used = used; + } + + public double getUsage() + { + return usage; + } + + public void setUsage(double usage) + { + this.usage = usage; + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..bf9731a --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java @@ -0,0 +1,114 @@ +package com.ruoyi.framework.web.exception; + +import javax.servlet.http.HttpServletRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.validation.BindException; +import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import com.ruoyi.common.constant.HttpStatus; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.exception.DemoModeException; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.StringUtils; + +/** + * 全局异常处理器 + * + * @author #author# + */ +@RestControllerAdvice +public class GlobalExceptionHandler +{ + private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class); + + /** + * 权限校验异常 + */ + @ExceptionHandler(AccessDeniedException.class) + public AjaxResult handleAccessDeniedException(AccessDeniedException e, HttpServletRequest request) + { + String requestURI = request.getRequestURI(); + log.error("请求地址'{}',权限校验失败'{}'", requestURI, e.getMessage()); + return AjaxResult.error(HttpStatus.FORBIDDEN, "没有权限,请联系管理员授权"); + } + + /** + * 请求方式不支持 + */ + @ExceptionHandler(HttpRequestMethodNotSupportedException.class) + public AjaxResult handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e, + HttpServletRequest request) + { + String requestURI = request.getRequestURI(); + log.error("请求地址'{}',不支持'{}'请求", requestURI, e.getMethod()); + return AjaxResult.error(e.getMessage()); + } + + /** + * 业务异常 + */ + @ExceptionHandler(ServiceException.class) + public AjaxResult handleServiceException(ServiceException e, HttpServletRequest request) + { + log.error(e.getMessage(), e); + Integer code = e.getCode(); + return StringUtils.isNotNull(code) ? AjaxResult.error(code, e.getMessage()) : AjaxResult.error(e.getMessage()); + } + + /** + * 拦截未知的运行时异常 + */ + @ExceptionHandler(RuntimeException.class) + public AjaxResult handleRuntimeException(RuntimeException e, HttpServletRequest request) + { + String requestURI = request.getRequestURI(); + log.error("请求地址'{}',发生未知异常.", requestURI, e); + return AjaxResult.error(e.getMessage()); + } + + /** + * 系统异常 + */ + @ExceptionHandler(Exception.class) + public AjaxResult handleException(Exception e, HttpServletRequest request) + { + String requestURI = request.getRequestURI(); + log.error("请求地址'{}',发生系统异常.", requestURI, e); + return AjaxResult.error(e.getMessage()); + } + + /** + * 自定义验证异常 + */ + @ExceptionHandler(BindException.class) + public AjaxResult handleBindException(BindException e) + { + log.error(e.getMessage(), e); + String message = e.getAllErrors().get(0).getDefaultMessage(); + return AjaxResult.error(message); + } + + /** + * 自定义验证异常 + */ + @ExceptionHandler(MethodArgumentNotValidException.class) + public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e) + { + log.error(e.getMessage(), e); + String message = e.getBindingResult().getFieldError().getDefaultMessage(); + return AjaxResult.error(message); + } + + /** + * 演示模式异常 + */ + @ExceptionHandler(DemoModeException.class) + public AjaxResult handleDemoModeException(DemoModeException e) + { + return AjaxResult.error("演示模式,不允许操作"); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java new file mode 100644 index 0000000..433139b --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java @@ -0,0 +1,168 @@ +package com.ruoyi.framework.web.service; + +import java.util.Set; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.framework.security.context.PermissionContextHolder; + +/** + * RuoYi首创 自定义权限实现,ss取自SpringSecurity首字母 + * + * @author #author# + */ +@Service("ss") +public class PermissionService +{ + /** 所有权限标识 */ + private static final String ALL_PERMISSION = "*:*:*"; + + /** 管理员角色权限标识 */ + private static final String SUPER_ADMIN = "admin"; + + private static final String ROLE_DELIMETER = ","; + + private static final String PERMISSION_DELIMETER = ","; + + /** + * 验证用户是否具备某权限 + * + * @param permission 权限字符串 + * @return 用户是否具备某权限 + */ + public boolean hasPermi(String permission) + { + if (StringUtils.isEmpty(permission)) + { + return false; + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions())) + { + return false; + } + PermissionContextHolder.setContext(permission); + return hasPermissions(loginUser.getPermissions(), permission); + } + + /** + * 验证用户是否不具备某权限,与 hasPermi逻辑相反 + * + * @param permission 权限字符串 + * @return 用户是否不具备某权限 + */ + public boolean lacksPermi(String permission) + { + return hasPermi(permission) != true; + } + + /** + * 验证用户是否具有以下任意一个权限 + * + * @param permissions 以 PERMISSION_NAMES_DELIMETER 为分隔符的权限列表 + * @return 用户是否具有以下任意一个权限 + */ + public boolean hasAnyPermi(String permissions) + { + if (StringUtils.isEmpty(permissions)) + { + return false; + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions())) + { + return false; + } + PermissionContextHolder.setContext(permissions); + Set authorities = loginUser.getPermissions(); + for (String permission : permissions.split(PERMISSION_DELIMETER)) + { + if (permission != null && hasPermissions(authorities, permission)) + { + return true; + } + } + return false; + } + + /** + * 判断用户是否拥有某个角色 + * + * @param role 角色字符串 + * @return 用户是否具备某角色 + */ + public boolean hasRole(String role) + { + if (StringUtils.isEmpty(role)) + { + return false; + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles())) + { + return false; + } + for (SysRole sysRole : loginUser.getUser().getRoles()) + { + String roleKey = sysRole.getRoleKey(); + if (SUPER_ADMIN.equals(roleKey) || roleKey.equals(StringUtils.trim(role))) + { + return true; + } + } + return false; + } + + /** + * 验证用户是否不具备某角色,与 isRole逻辑相反。 + * + * @param role 角色名称 + * @return 用户是否不具备某角色 + */ + public boolean lacksRole(String role) + { + return hasRole(role) != true; + } + + /** + * 验证用户是否具有以下任意一个角色 + * + * @param roles 以 ROLE_NAMES_DELIMETER 为分隔符的角色列表 + * @return 用户是否具有以下任意一个角色 + */ + public boolean hasAnyRoles(String roles) + { + if (StringUtils.isEmpty(roles)) + { + return false; + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles())) + { + return false; + } + for (String role : roles.split(ROLE_DELIMETER)) + { + if (hasRole(role)) + { + return true; + } + } + return false; + } + + /** + * 判断是否包含权限 + * + * @param permissions 权限列表 + * @param permission 权限字符串 + * @return 用户是否具备某权限 + */ + private boolean hasPermissions(Set permissions, String permission) + { + return permissions.contains(ALL_PERMISSION) || permissions.contains(StringUtils.trim(permission)); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java new file mode 100644 index 0000000..fe137cc --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java @@ -0,0 +1,141 @@ +package com.ruoyi.framework.web.service; + +import javax.annotation.Resource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Component; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.exception.user.CaptchaException; +import com.ruoyi.common.exception.user.CaptchaExpireException; +import com.ruoyi.common.exception.user.UserPasswordNotMatchException; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.MessageUtils; +import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.ip.IpUtils; +import com.ruoyi.framework.manager.AsyncManager; +import com.ruoyi.framework.manager.factory.AsyncFactory; +import com.ruoyi.framework.security.context.AuthenticationContextHolder; +import com.ruoyi.system.service.ISysConfigService; +import com.ruoyi.system.service.ISysUserService; + +/** + * 登录校验方法 + * + * @author #author# + */ +@Component +public class SysLoginService +{ + @Autowired + private TokenService tokenService; + + @Resource + private AuthenticationManager authenticationManager; + + @Autowired + private RedisCache redisCache; + + @Autowired + private ISysUserService userService; + + @Autowired + private ISysConfigService configService; + + /** + * 登录验证 + * + * @param username 用户名 + * @param password 密码 + * @param code 验证码 + * @param uuid 唯一标识 + * @return 结果 + */ + public String login(String username, String password, String code, String uuid) + { + boolean captchaEnabled = configService.selectCaptchaEnabled(); + // 验证码开关 + if (captchaEnabled) + { + validateCaptcha(username, code, uuid); + } + // 用户验证 + Authentication authentication = null; + try + { + UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password); + AuthenticationContextHolder.setContext(authenticationToken); + // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername + authentication = authenticationManager.authenticate(authenticationToken); + } + catch (Exception e) + { + if (e instanceof BadCredentialsException) + { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"))); + throw new UserPasswordNotMatchException(); + } + else + { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage())); + throw new ServiceException(e.getMessage()); + } + } + finally + { + AuthenticationContextHolder.clearContext(); + } + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"))); + LoginUser loginUser = (LoginUser) authentication.getPrincipal(); + recordLoginInfo(loginUser.getUserId()); + // 生成token + return tokenService.createToken(loginUser); + } + + /** + * 校验验证码 + * + * @param username 用户名 + * @param code 验证码 + * @param uuid 唯一标识 + * @return 结果 + */ + public void validateCaptcha(String username, String code, String uuid) + { + String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, ""); + String captcha = redisCache.getCacheObject(verifyKey); + redisCache.deleteObject(verifyKey); + if (captcha == null) + { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"))); + throw new CaptchaExpireException(); + } + if (!code.equalsIgnoreCase(captcha)) + { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"))); + throw new CaptchaException(); + } + } + + /** + * 记录登录信息 + * + * @param userId 用户ID + */ + public void recordLoginInfo(Long userId) + { + SysUser sysUser = new SysUser(); + sysUser.setUserId(userId); + sysUser.setLoginIp(IpUtils.getIpAddr(ServletUtils.getRequest())); + sysUser.setLoginDate(DateUtils.getNowDate()); + userService.updateUserProfile(sysUser); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPasswordService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPasswordService.java new file mode 100644 index 0000000..5c3cf5c --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPasswordService.java @@ -0,0 +1,94 @@ +package com.ruoyi.framework.web.service; + +import java.util.concurrent.TimeUnit; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Component; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.exception.user.UserPasswordNotMatchException; +import com.ruoyi.common.exception.user.UserPasswordRetryLimitExceedException; +import com.ruoyi.common.utils.MessageUtils; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.framework.manager.AsyncManager; +import com.ruoyi.framework.manager.factory.AsyncFactory; +import com.ruoyi.framework.security.context.AuthenticationContextHolder; + +/** + * 登录密码方法 + * + * @author #author# + */ +@Component +public class SysPasswordService +{ + @Autowired + private RedisCache redisCache; + + @Value(value = "${user.password.maxRetryCount}") + private int maxRetryCount; + + @Value(value = "${user.password.lockTime}") + private int lockTime; + + /** + * 登录账户密码错误次数缓存键名 + * + * @param username 用户名 + * @return 缓存键key + */ + private String getCacheKey(String username) + { + return CacheConstants.PWD_ERR_CNT_KEY + username; + } + + public void validate(SysUser user) + { + Authentication usernamePasswordAuthenticationToken = AuthenticationContextHolder.getContext(); + String username = usernamePasswordAuthenticationToken.getName(); + String password = usernamePasswordAuthenticationToken.getCredentials().toString(); + + Integer retryCount = redisCache.getCacheObject(getCacheKey(username)); + + if (retryCount == null) + { + retryCount = 0; + } + + if (retryCount >= Integer.valueOf(maxRetryCount).intValue()) + { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, + MessageUtils.message("user.password.retry.limit.exceed", maxRetryCount, lockTime))); + throw new UserPasswordRetryLimitExceedException(maxRetryCount, lockTime); + } + + if (!matches(user, password)) + { + retryCount = retryCount + 1; + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, + MessageUtils.message("user.password.retry.limit.count", retryCount))); + redisCache.setCacheObject(getCacheKey(username), retryCount, lockTime, TimeUnit.MINUTES); + throw new UserPasswordNotMatchException(); + } + else + { + clearLoginRecordCache(username); + } + } + + public boolean matches(SysUser user, String rawPassword) + { + return SecurityUtils.matchesPassword(rawPassword, user.getPassword()); + } + + public void clearLoginRecordCache(String loginName) + { + if (redisCache.hasKey(getCacheKey(loginName))) + { + redisCache.deleteObject(getCacheKey(loginName)); + } + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPermissionService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPermissionService.java new file mode 100644 index 0000000..06086e5 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPermissionService.java @@ -0,0 +1,82 @@ +package com.ruoyi.framework.web.service; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.system.service.ISysMenuService; +import com.ruoyi.system.service.ISysRoleService; + +/** + * 用户权限处理 + * + * @author #author# + */ +@Component +public class SysPermissionService +{ + @Autowired + private ISysRoleService roleService; + + @Autowired + private ISysMenuService menuService; + + /** + * 获取角色数据权限 + * + * @param user 用户信息 + * @return 角色权限信息 + */ + public Set getRolePermission(SysUser user) + { + Set roles = new HashSet(); + // 管理员拥有所有权限 + if (user.isAdmin()) + { + roles.add("admin"); + } + else + { + roles.addAll(roleService.selectRolePermissionByUserId(user.getUserId())); + } + return roles; + } + + /** + * 获取菜单数据权限 + * + * @param user 用户信息 + * @return 菜单权限信息 + */ + public Set getMenuPermission(SysUser user) + { + Set perms = new HashSet(); + // 管理员拥有所有权限 + if (user.isAdmin()) + { + perms.add("*:*:*"); + } + else + { + List roles = user.getRoles(); + if (!roles.isEmpty() && roles.size() > 1) + { + // 多角色设置permissions属性,以便数据权限匹配权限 + for (SysRole role : roles) + { + Set rolePerms = menuService.selectMenuPermsByRoleId(role.getRoleId()); + role.setPermissions(rolePerms); + perms.addAll(rolePerms); + } + } + else + { + perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId())); + } + } + return perms; + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java new file mode 100644 index 0000000..988c68b --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java @@ -0,0 +1,115 @@ +package com.ruoyi.framework.web.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.domain.model.RegisterBody; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.exception.user.CaptchaException; +import com.ruoyi.common.exception.user.CaptchaExpireException; +import com.ruoyi.common.utils.MessageUtils; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.framework.manager.AsyncManager; +import com.ruoyi.framework.manager.factory.AsyncFactory; +import com.ruoyi.system.service.ISysConfigService; +import com.ruoyi.system.service.ISysUserService; + +/** + * 注册校验方法 + * + * @author #author# + */ +@Component +public class SysRegisterService +{ + @Autowired + private ISysUserService userService; + + @Autowired + private ISysConfigService configService; + + @Autowired + private RedisCache redisCache; + + /** + * 注册 + */ + public String register(RegisterBody registerBody) + { + String msg = "", username = registerBody.getUsername(), password = registerBody.getPassword(); + SysUser sysUser = new SysUser(); + sysUser.setUserName(username); + + // 验证码开关 + boolean captchaEnabled = configService.selectCaptchaEnabled(); + if (captchaEnabled) + { + validateCaptcha(username, registerBody.getCode(), registerBody.getUuid()); + } + + if (StringUtils.isEmpty(username)) + { + msg = "用户名不能为空"; + } + else if (StringUtils.isEmpty(password)) + { + msg = "用户密码不能为空"; + } + else if (username.length() < UserConstants.USERNAME_MIN_LENGTH + || username.length() > UserConstants.USERNAME_MAX_LENGTH) + { + msg = "账户长度必须在2到20个字符之间"; + } + else if (password.length() < UserConstants.PASSWORD_MIN_LENGTH + || password.length() > UserConstants.PASSWORD_MAX_LENGTH) + { + msg = "密码长度必须在5到20个字符之间"; + } + else if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(sysUser))) + { + msg = "保存用户'" + username + "'失败,注册账号已存在"; + } + else + { + sysUser.setNickName(username); + sysUser.setPassword(SecurityUtils.encryptPassword(password)); + boolean regFlag = userService.registerUser(sysUser); + if (!regFlag) + { + msg = "注册失败,请联系系统管理人员"; + } + else + { + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.register.success"))); + } + } + return msg; + } + + /** + * 校验验证码 + * + * @param username 用户名 + * @param code 验证码 + * @param uuid 唯一标识 + * @return 结果 + */ + public void validateCaptcha(String username, String code, String uuid) + { + String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, ""); + String captcha = redisCache.getCacheObject(verifyKey); + redisCache.deleteObject(verifyKey); + if (captcha == null) + { + throw new CaptchaExpireException(); + } + if (!code.equalsIgnoreCase(captcha)) + { + throw new CaptchaException(); + } + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java new file mode 100644 index 0000000..234747d --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java @@ -0,0 +1,226 @@ +package com.ruoyi.framework.web.service; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import javax.servlet.http.HttpServletRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.ip.AddressUtils; +import com.ruoyi.common.utils.ip.IpUtils; +import com.ruoyi.common.utils.uuid.IdUtils; +import eu.bitwalker.useragentutils.UserAgent; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; + +/** + * token验证处理 + * + * @author #author# + */ +@Component +public class TokenService +{ + // 令牌自定义标识 + @Value("${token.header}") + private String header; + + // 令牌秘钥 + @Value("${token.secret}") + private String secret; + + // 令牌有效期(默认30分钟) + @Value("${token.expireTime}") + private int expireTime; + + protected static final long MILLIS_SECOND = 1000; + + protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND; + + private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L; + + @Autowired + private RedisCache redisCache; + + /** + * 获取用户身份信息 + * + * @return 用户信息 + */ + public LoginUser getLoginUser(HttpServletRequest request) + { + // 获取请求携带的令牌 + String token = getToken(request); + if (StringUtils.isNotEmpty(token)) + { + try + { + Claims claims = parseToken(token); + // 解析对应的权限以及用户信息 + String uuid = (String) claims.get(Constants.LOGIN_USER_KEY); + String userKey = getTokenKey(uuid); + LoginUser user = redisCache.getCacheObject(userKey); + return user; + } + catch (Exception e) + { + } + } + return null; + } + + /** + * 设置用户身份信息 + */ + public void setLoginUser(LoginUser loginUser) + { + if (StringUtils.isNotNull(loginUser) && StringUtils.isNotEmpty(loginUser.getToken())) + { + refreshToken(loginUser); + } + } + + /** + * 删除用户身份信息 + */ + public void delLoginUser(String token) + { + if (StringUtils.isNotEmpty(token)) + { + String userKey = getTokenKey(token); + redisCache.deleteObject(userKey); + } + } + + /** + * 创建令牌 + * + * @param loginUser 用户信息 + * @return 令牌 + */ + public String createToken(LoginUser loginUser) + { + String token = IdUtils.fastUUID(); + loginUser.setToken(token); + setUserAgent(loginUser); + refreshToken(loginUser); + + Map claims = new HashMap<>(); + claims.put(Constants.LOGIN_USER_KEY, token); + return createToken(claims); + } + + /** + * 验证令牌有效期,相差不足20分钟,自动刷新缓存 + * + * @param loginUser + * @return 令牌 + */ + public void verifyToken(LoginUser loginUser) + { + long expireTime = loginUser.getExpireTime(); + long currentTime = System.currentTimeMillis(); + if (expireTime - currentTime <= MILLIS_MINUTE_TEN) + { + refreshToken(loginUser); + } + } + + /** + * 刷新令牌有效期 + * + * @param loginUser 登录信息 + */ + public void refreshToken(LoginUser loginUser) + { + loginUser.setLoginTime(System.currentTimeMillis()); + loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE); + // 根据uuid将loginUser缓存 + String userKey = getTokenKey(loginUser.getToken()); + redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES); + } + + /** + * 设置用户代理信息 + * + * @param loginUser 登录信息 + */ + public void setUserAgent(LoginUser loginUser) + { + UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent")); + String ip = IpUtils.getIpAddr(ServletUtils.getRequest()); + loginUser.setIpaddr(ip); + loginUser.setLoginLocation(AddressUtils.getRealAddressByIP(ip)); + loginUser.setBrowser(userAgent.getBrowser().getName()); + loginUser.setOs(userAgent.getOperatingSystem().getName()); + } + + /** + * 从数据声明生成令牌 + * + * @param claims 数据声明 + * @return 令牌 + */ + private String createToken(Map claims) + { + String token = Jwts.builder() + .setClaims(claims) + .signWith(SignatureAlgorithm.HS512, secret).compact(); + return token; + } + + /** + * 从令牌中获取数据声明 + * + * @param token 令牌 + * @return 数据声明 + */ + private Claims parseToken(String token) + { + return Jwts.parser() + .setSigningKey(secret) + .parseClaimsJws(token) + .getBody(); + } + + /** + * 从令牌中获取用户名 + * + * @param token 令牌 + * @return 用户名 + */ + public String getUsernameFromToken(String token) + { + Claims claims = parseToken(token); + return claims.getSubject(); + } + + /** + * 获取请求token + * + * @param request + * @return token + */ + private String getToken(HttpServletRequest request) + { + String token = request.getHeader(header); + if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX)) + { + token = token.replace(Constants.TOKEN_PREFIX, ""); + } + return token; + } + + private String getTokenKey(String uuid) + { + return CacheConstants.LOGIN_TOKEN_KEY + uuid; + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java new file mode 100644 index 0000000..39c7e34 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java @@ -0,0 +1,65 @@ +package com.ruoyi.framework.web.service; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.enums.UserStatus; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.system.service.ISysUserService; + +/** + * 用户验证处理 + * + * @author #author# + */ +@Service +public class UserDetailsServiceImpl implements UserDetailsService +{ + private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class); + + @Autowired + private ISysUserService userService; + + @Autowired + private SysPasswordService passwordService; + + @Autowired + private SysPermissionService permissionService; + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException + { + SysUser user = userService.selectUserByUserName(username); + if (StringUtils.isNull(user)) + { + log.info("登录用户:{} 不存在.", username); + throw new ServiceException("登录用户:" + username + " 不存在"); + } + else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) + { + log.info("登录用户:{} 已被删除.", username); + throw new ServiceException("对不起,您的账号:" + username + " 已被删除"); + } + else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) + { + log.info("登录用户:{} 已被停用.", username); + throw new ServiceException("对不起,您的账号:" + username + " 已停用"); + } + + passwordService.validate(user); + + return createLoginUser(user); + } + + public UserDetails createLoginUser(SysUser user) + { + return new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user)); + } +} diff --git a/ruoyi-generator/pom.xml b/ruoyi-generator/pom.xml new file mode 100644 index 0000000..10bda90 --- /dev/null +++ b/ruoyi-generator/pom.xml @@ -0,0 +1,40 @@ + + + + ruoyi + com.ruoyi + 3.8.5 + + 4.0.0 + + ruoyi-generator + + + generator代码生成 + + + + + + + org.apache.velocity + velocity-engine-core + + + + + commons-collections + commons-collections + + + + + com.ruoyi + ruoyi-common + + + + + \ No newline at end of file diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java new file mode 100644 index 0000000..c08f00e --- /dev/null +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java @@ -0,0 +1,73 @@ +package com.ruoyi.generator.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.PropertySource; +import org.springframework.stereotype.Component; + +/** + * 读取代码生成相关配置 + * + * @author zhihuiwuliu + */ +@Component +@ConfigurationProperties(prefix = "gen") +@PropertySource(value = { "classpath:generator.yml" }) +public class GenConfig +{ + /** 作者 */ + public static String author; + + /** 生成包路径 */ + public static String packageName; + + /** 自动去除表前缀,默认是false */ + public static boolean autoRemovePre; + + /** 表前缀(类名不会包含表前缀) */ + public static String tablePrefix; + + public static String getAuthor() + { + return author; + } + + @Value("${author}") + public void setAuthor(String author) + { + GenConfig.author = author; + } + + public static String getPackageName() + { + return packageName; + } + + @Value("${packageName}") + public void setPackageName(String packageName) + { + GenConfig.packageName = packageName; + } + + public static boolean getAutoRemovePre() + { + return autoRemovePre; + } + + @Value("${autoRemovePre}") + public void setAutoRemovePre(boolean autoRemovePre) + { + GenConfig.autoRemovePre = autoRemovePre; + } + + public static String getTablePrefix() + { + return tablePrefix; + } + + @Value("${tablePrefix}") + public void setTablePrefix(String tablePrefix) + { + GenConfig.tablePrefix = tablePrefix; + } +} diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java new file mode 100644 index 0000000..8ce7a3f --- /dev/null +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java @@ -0,0 +1,214 @@ +package com.ruoyi.generator.controller; + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.servlet.http.HttpServletResponse; +import org.apache.commons.io.IOUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.core.text.Convert; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.generator.domain.GenTable; +import com.ruoyi.generator.domain.GenTableColumn; +import com.ruoyi.generator.service.IGenTableColumnService; +import com.ruoyi.generator.service.IGenTableService; + +/** + * 代码生成 操作处理 + * + * @author zhihuiwuliu + */ +@RestController +@RequestMapping("/tool/gen") +public class GenController extends BaseController +{ + @Autowired + private IGenTableService genTableService; + + @Autowired + private IGenTableColumnService genTableColumnService; + + /** + * 查询代码生成列表 + */ + @PreAuthorize("@ss.hasPermi('tool:gen:list')") + @GetMapping("/list") + public TableDataInfo genList(GenTable genTable) + { + startPage(); + List list = genTableService.selectGenTableList(genTable); + return getDataTable(list); + } + + /** + * 修改代码生成业务 + */ + @PreAuthorize("@ss.hasPermi('tool:gen:query')") + @GetMapping(value = "/{tableId}") + public AjaxResult getInfo(@PathVariable Long tableId) + { + GenTable table = genTableService.selectGenTableById(tableId); + List tables = genTableService.selectGenTableAll(); + List list = genTableColumnService.selectGenTableColumnListByTableId(tableId); + Map map = new HashMap(); + map.put("info", table); + map.put("rows", list); + map.put("tables", tables); + return success(map); + } + + /** + * 查询数据库列表 + */ + @PreAuthorize("@ss.hasPermi('tool:gen:list')") + @GetMapping("/db/list") + public TableDataInfo dataList(GenTable genTable) + { + startPage(); + List list = genTableService.selectDbTableList(genTable); + return getDataTable(list); + } + + /** + * 查询数据表字段列表 + */ + @PreAuthorize("@ss.hasPermi('tool:gen:list')") + @GetMapping(value = "/column/{tableId}") + public TableDataInfo columnList(Long tableId) + { + TableDataInfo dataInfo = new TableDataInfo(); + List list = genTableColumnService.selectGenTableColumnListByTableId(tableId); + dataInfo.setRows(list); + dataInfo.setTotal(list.size()); + return dataInfo; + } + + /** + * 导入表结构(保存) + */ + @PreAuthorize("@ss.hasPermi('tool:gen:import')") + @Log(title = "代码生成", businessType = BusinessType.IMPORT) + @PostMapping("/importTable") + public AjaxResult importTableSave(String tables) + { + String[] tableNames = Convert.toStrArray(tables); + // 查询表信息 + List tableList = genTableService.selectDbTableListByNames(tableNames); + genTableService.importGenTable(tableList); + return success(); + } + + /** + * 修改保存代码生成业务 + */ + @PreAuthorize("@ss.hasPermi('tool:gen:edit')") + @Log(title = "代码生成", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult editSave(@Validated @RequestBody GenTable genTable) + { + genTableService.validateEdit(genTable); + genTableService.updateGenTable(genTable); + return success(); + } + + /** + * 删除代码生成 + */ + @PreAuthorize("@ss.hasPermi('tool:gen:remove')") + @Log(title = "代码生成", businessType = BusinessType.DELETE) + @DeleteMapping("/{tableIds}") + public AjaxResult remove(@PathVariable Long[] tableIds) + { + genTableService.deleteGenTableByIds(tableIds); + return success(); + } + + /** + * 预览代码 + */ + @PreAuthorize("@ss.hasPermi('tool:gen:preview')") + @GetMapping("/preview/{tableId}") + public AjaxResult preview(@PathVariable("tableId") Long tableId) throws IOException + { + Map dataMap = genTableService.previewCode(tableId); + return success(dataMap); + } + + /** + * 生成代码(下载方式) + */ + @PreAuthorize("@ss.hasPermi('tool:gen:code')") + @Log(title = "代码生成", businessType = BusinessType.GENCODE) + @GetMapping("/download/{tableName}") + public void download(HttpServletResponse response, @PathVariable("tableName") String tableName) throws IOException + { + byte[] data = genTableService.downloadCode(tableName); + genCode(response, data); + } + + /** + * 生成代码(自定义路径) + */ + @PreAuthorize("@ss.hasPermi('tool:gen:code')") + @Log(title = "代码生成", businessType = BusinessType.GENCODE) + @GetMapping("/genCode/{tableName}") + public AjaxResult genCode(@PathVariable("tableName") String tableName) + { + genTableService.generatorCode(tableName); + return success(); + } + + /** + * 同步数据库 + */ + @PreAuthorize("@ss.hasPermi('tool:gen:edit')") + @Log(title = "代码生成", businessType = BusinessType.UPDATE) + @GetMapping("/synchDb/{tableName}") + public AjaxResult synchDb(@PathVariable("tableName") String tableName) + { + genTableService.synchDb(tableName); + return success(); + } + + /** + * 批量生成代码 + */ + @PreAuthorize("@ss.hasPermi('tool:gen:code')") + @Log(title = "代码生成", businessType = BusinessType.GENCODE) + @GetMapping("/batchGenCode") + public void batchGenCode(HttpServletResponse response, String tables) throws IOException + { + String[] tableNames = Convert.toStrArray(tables); + byte[] data = genTableService.downloadCode(tableNames); + genCode(response, data); + } + + /** + * 生成zip文件 + */ + private void genCode(HttpServletResponse response, byte[] data) throws IOException + { + response.reset(); + response.addHeader("Access-Control-Allow-Origin", "*"); + response.addHeader("Access-Control-Expose-Headers", "Content-Disposition"); + response.setHeader("Content-Disposition", "attachment; filename=\"ruoyi.zip\""); + response.addHeader("Content-Length", "" + data.length); + response.setContentType("application/octet-stream; charset=UTF-8"); + IOUtils.write(data, response.getOutputStream()); + } +} \ No newline at end of file diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java new file mode 100644 index 0000000..702c580 --- /dev/null +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java @@ -0,0 +1,372 @@ +package com.ruoyi.generator.domain; + +import java.util.List; +import javax.validation.Valid; +import javax.validation.constraints.NotBlank; +import org.apache.commons.lang3.ArrayUtils; +import com.ruoyi.common.constant.GenConstants; +import com.ruoyi.common.core.domain.BaseEntity; +import com.ruoyi.common.utils.StringUtils; + +/** + * 业务表 gen_table + * + * @author zhihuiwuliu + */ +public class GenTable extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 编号 */ + private Long tableId; + + /** 表名称 */ + @NotBlank(message = "表名称不能为空") + private String tableName; + + /** 表描述 */ + @NotBlank(message = "表描述不能为空") + private String tableComment; + + /** 关联父表的表名 */ + private String subTableName; + + /** 本表关联父表的外键名 */ + private String subTableFkName; + + /** 实体类名称(首字母大写) */ + @NotBlank(message = "实体类名称不能为空") + private String className; + + /** 使用的模板(crud单表操作 tree树表操作 sub主子表操作) */ + private String tplCategory; + + /** 生成包路径 */ + @NotBlank(message = "生成包路径不能为空") + private String packageName; + + /** 生成模块名 */ + @NotBlank(message = "生成模块名不能为空") + private String moduleName; + + /** 生成业务名 */ + @NotBlank(message = "生成业务名不能为空") + private String businessName; + + /** 生成功能名 */ + @NotBlank(message = "生成功能名不能为空") + private String functionName; + + /** 生成作者 */ + @NotBlank(message = "作者不能为空") + private String functionAuthor; + + /** 生成代码方式(0zip压缩包 1自定义路径) */ + private String genType; + + /** 生成路径(不填默认项目路径) */ + private String genPath; + + /** 主键信息 */ + private GenTableColumn pkColumn; + + /** 子表信息 */ + private GenTable subTable; + + /** 表列信息 */ + @Valid + private List columns; + + /** 其它生成选项 */ + private String options; + + /** 树编码字段 */ + private String treeCode; + + /** 树父编码字段 */ + private String treeParentCode; + + /** 树名称字段 */ + private String treeName; + + /** 上级菜单ID字段 */ + private String parentMenuId; + + /** 上级菜单名称字段 */ + private String parentMenuName; + + public Long getTableId() + { + return tableId; + } + + public void setTableId(Long tableId) + { + this.tableId = tableId; + } + + public String getTableName() + { + return tableName; + } + + public void setTableName(String tableName) + { + this.tableName = tableName; + } + + public String getTableComment() + { + return tableComment; + } + + public void setTableComment(String tableComment) + { + this.tableComment = tableComment; + } + + public String getSubTableName() + { + return subTableName; + } + + public void setSubTableName(String subTableName) + { + this.subTableName = subTableName; + } + + public String getSubTableFkName() + { + return subTableFkName; + } + + public void setSubTableFkName(String subTableFkName) + { + this.subTableFkName = subTableFkName; + } + + public String getClassName() + { + return className; + } + + public void setClassName(String className) + { + this.className = className; + } + + public String getTplCategory() + { + return tplCategory; + } + + public void setTplCategory(String tplCategory) + { + this.tplCategory = tplCategory; + } + + public String getPackageName() + { + return packageName; + } + + public void setPackageName(String packageName) + { + this.packageName = packageName; + } + + public String getModuleName() + { + return moduleName; + } + + public void setModuleName(String moduleName) + { + this.moduleName = moduleName; + } + + public String getBusinessName() + { + return businessName; + } + + public void setBusinessName(String businessName) + { + this.businessName = businessName; + } + + public String getFunctionName() + { + return functionName; + } + + public void setFunctionName(String functionName) + { + this.functionName = functionName; + } + + public String getFunctionAuthor() + { + return functionAuthor; + } + + public void setFunctionAuthor(String functionAuthor) + { + this.functionAuthor = functionAuthor; + } + + public String getGenType() + { + return genType; + } + + public void setGenType(String genType) + { + this.genType = genType; + } + + public String getGenPath() + { + return genPath; + } + + public void setGenPath(String genPath) + { + this.genPath = genPath; + } + + public GenTableColumn getPkColumn() + { + return pkColumn; + } + + public void setPkColumn(GenTableColumn pkColumn) + { + this.pkColumn = pkColumn; + } + + public GenTable getSubTable() + { + return subTable; + } + + public void setSubTable(GenTable subTable) + { + this.subTable = subTable; + } + + public List getColumns() + { + return columns; + } + + public void setColumns(List columns) + { + this.columns = columns; + } + + public String getOptions() + { + return options; + } + + public void setOptions(String options) + { + this.options = options; + } + + public String getTreeCode() + { + return treeCode; + } + + public void setTreeCode(String treeCode) + { + this.treeCode = treeCode; + } + + public String getTreeParentCode() + { + return treeParentCode; + } + + public void setTreeParentCode(String treeParentCode) + { + this.treeParentCode = treeParentCode; + } + + public String getTreeName() + { + return treeName; + } + + public void setTreeName(String treeName) + { + this.treeName = treeName; + } + + public String getParentMenuId() + { + return parentMenuId; + } + + public void setParentMenuId(String parentMenuId) + { + this.parentMenuId = parentMenuId; + } + + public String getParentMenuName() + { + return parentMenuName; + } + + public void setParentMenuName(String parentMenuName) + { + this.parentMenuName = parentMenuName; + } + + public boolean isSub() + { + return isSub(this.tplCategory); + } + + public static boolean isSub(String tplCategory) + { + return tplCategory != null && StringUtils.equals(GenConstants.TPL_SUB, tplCategory); + } + + public boolean isTree() + { + return isTree(this.tplCategory); + } + + public static boolean isTree(String tplCategory) + { + return tplCategory != null && StringUtils.equals(GenConstants.TPL_TREE, tplCategory); + } + + public boolean isCrud() + { + return isCrud(this.tplCategory); + } + + public static boolean isCrud(String tplCategory) + { + return tplCategory != null && StringUtils.equals(GenConstants.TPL_CRUD, tplCategory); + } + + public boolean isSuperColumn(String javaField) + { + return isSuperColumn(this.tplCategory, javaField); + } + + public static boolean isSuperColumn(String tplCategory, String javaField) + { + if (isTree(tplCategory)) + { + return StringUtils.equalsAnyIgnoreCase(javaField, + ArrayUtils.addAll(GenConstants.TREE_ENTITY, GenConstants.BASE_ENTITY)); + } + return StringUtils.equalsAnyIgnoreCase(javaField, GenConstants.BASE_ENTITY); + } +} \ No newline at end of file diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java new file mode 100644 index 0000000..d59f271 --- /dev/null +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java @@ -0,0 +1,373 @@ +package com.ruoyi.generator.domain; + +import javax.validation.constraints.NotBlank; +import com.ruoyi.common.core.domain.BaseEntity; +import com.ruoyi.common.utils.StringUtils; + +/** + * 代码生成业务字段表 gen_table_column + * + * @author zhihuiwuliu + */ +public class GenTableColumn extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 编号 */ + private Long columnId; + + /** 归属表编号 */ + private Long tableId; + + /** 列名称 */ + private String columnName; + + /** 列描述 */ + private String columnComment; + + /** 列类型 */ + private String columnType; + + /** JAVA类型 */ + private String javaType; + + /** JAVA字段名 */ + @NotBlank(message = "Java属性不能为空") + private String javaField; + + /** 是否主键(1是) */ + private String isPk; + + /** 是否自增(1是) */ + private String isIncrement; + + /** 是否必填(1是) */ + private String isRequired; + + /** 是否为插入字段(1是) */ + private String isInsert; + + /** 是否编辑字段(1是) */ + private String isEdit; + + /** 是否列表字段(1是) */ + private String isList; + + /** 是否查询字段(1是) */ + private String isQuery; + + /** 查询方式(EQ等于、NE不等于、GT大于、LT小于、LIKE模糊、BETWEEN范围) */ + private String queryType; + + /** 显示类型(input文本框、textarea文本域、select下拉框、checkbox复选框、radio单选框、datetime日期控件、image图片上传控件、upload文件上传控件、editor富文本控件) */ + private String htmlType; + + /** 字典类型 */ + private String dictType; + + /** 排序 */ + private Integer sort; + + public void setColumnId(Long columnId) + { + this.columnId = columnId; + } + + public Long getColumnId() + { + return columnId; + } + + public void setTableId(Long tableId) + { + this.tableId = tableId; + } + + public Long getTableId() + { + return tableId; + } + + public void setColumnName(String columnName) + { + this.columnName = columnName; + } + + public String getColumnName() + { + return columnName; + } + + public void setColumnComment(String columnComment) + { + this.columnComment = columnComment; + } + + public String getColumnComment() + { + return columnComment; + } + + public void setColumnType(String columnType) + { + this.columnType = columnType; + } + + public String getColumnType() + { + return columnType; + } + + public void setJavaType(String javaType) + { + this.javaType = javaType; + } + + public String getJavaType() + { + return javaType; + } + + public void setJavaField(String javaField) + { + this.javaField = javaField; + } + + public String getJavaField() + { + return javaField; + } + + public String getCapJavaField() + { + return StringUtils.capitalize(javaField); + } + + public void setIsPk(String isPk) + { + this.isPk = isPk; + } + + public String getIsPk() + { + return isPk; + } + + public boolean isPk() + { + return isPk(this.isPk); + } + + public boolean isPk(String isPk) + { + return isPk != null && StringUtils.equals("1", isPk); + } + + public String getIsIncrement() + { + return isIncrement; + } + + public void setIsIncrement(String isIncrement) + { + this.isIncrement = isIncrement; + } + + public boolean isIncrement() + { + return isIncrement(this.isIncrement); + } + + public boolean isIncrement(String isIncrement) + { + return isIncrement != null && StringUtils.equals("1", isIncrement); + } + + public void setIsRequired(String isRequired) + { + this.isRequired = isRequired; + } + + public String getIsRequired() + { + return isRequired; + } + + public boolean isRequired() + { + return isRequired(this.isRequired); + } + + public boolean isRequired(String isRequired) + { + return isRequired != null && StringUtils.equals("1", isRequired); + } + + public void setIsInsert(String isInsert) + { + this.isInsert = isInsert; + } + + public String getIsInsert() + { + return isInsert; + } + + public boolean isInsert() + { + return isInsert(this.isInsert); + } + + public boolean isInsert(String isInsert) + { + return isInsert != null && StringUtils.equals("1", isInsert); + } + + public void setIsEdit(String isEdit) + { + this.isEdit = isEdit; + } + + public String getIsEdit() + { + return isEdit; + } + + public boolean isEdit() + { + return isInsert(this.isEdit); + } + + public boolean isEdit(String isEdit) + { + return isEdit != null && StringUtils.equals("1", isEdit); + } + + public void setIsList(String isList) + { + this.isList = isList; + } + + public String getIsList() + { + return isList; + } + + public boolean isList() + { + return isList(this.isList); + } + + public boolean isList(String isList) + { + return isList != null && StringUtils.equals("1", isList); + } + + public void setIsQuery(String isQuery) + { + this.isQuery = isQuery; + } + + public String getIsQuery() + { + return isQuery; + } + + public boolean isQuery() + { + return isQuery(this.isQuery); + } + + public boolean isQuery(String isQuery) + { + return isQuery != null && StringUtils.equals("1", isQuery); + } + + public void setQueryType(String queryType) + { + this.queryType = queryType; + } + + public String getQueryType() + { + return queryType; + } + + public String getHtmlType() + { + return htmlType; + } + + public void setHtmlType(String htmlType) + { + this.htmlType = htmlType; + } + + public void setDictType(String dictType) + { + this.dictType = dictType; + } + + public String getDictType() + { + return dictType; + } + + public void setSort(Integer sort) + { + this.sort = sort; + } + + public Integer getSort() + { + return sort; + } + + public boolean isSuperColumn() + { + return isSuperColumn(this.javaField); + } + + public static boolean isSuperColumn(String javaField) + { + return StringUtils.equalsAnyIgnoreCase(javaField, + // BaseEntity + "createBy", "createTime", "updateBy", "updateTime", "remark", + // TreeEntity + "parentName", "parentId", "orderNum", "ancestors"); + } + + public boolean isUsableColumn() + { + return isUsableColumn(javaField); + } + + public static boolean isUsableColumn(String javaField) + { + // isSuperColumn()中的名单用于避免生成多余Domain属性,若某些属性在生成页面时需要用到不能忽略,则放在此处白名单 + return StringUtils.equalsAnyIgnoreCase(javaField, "parentId", "orderNum", "remark"); + } + + public String readConverterExp() + { + String remarks = StringUtils.substringBetween(this.columnComment, "(", ")"); + StringBuffer sb = new StringBuffer(); + if (StringUtils.isNotEmpty(remarks)) + { + for (String value : remarks.split(" ")) + { + if (StringUtils.isNotEmpty(value)) + { + Object startStr = value.subSequence(0, 1); + String endStr = value.substring(1); + sb.append("").append(startStr).append("=").append(endStr).append(","); + } + } + return sb.deleteCharAt(sb.length() - 1).toString(); + } + else + { + return this.columnComment; + } + } +} diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java new file mode 100644 index 0000000..f9d506a --- /dev/null +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java @@ -0,0 +1,60 @@ +package com.ruoyi.generator.mapper; + +import java.util.List; +import com.ruoyi.generator.domain.GenTableColumn; + +/** + * 业务字段 数据层 + * + * @author zhihuiwuliu + */ +public interface GenTableColumnMapper +{ + /** + * 根据表名称查询列信息 + * + * @param tableName 表名称 + * @return 列信息 + */ + public List selectDbTableColumnsByName(String tableName); + + /** + * 查询业务字段列表 + * + * @param tableId 业务字段编号 + * @return 业务字段集合 + */ + public List selectGenTableColumnListByTableId(Long tableId); + + /** + * 新增业务字段 + * + * @param genTableColumn 业务字段信息 + * @return 结果 + */ + public int insertGenTableColumn(GenTableColumn genTableColumn); + + /** + * 修改业务字段 + * + * @param genTableColumn 业务字段信息 + * @return 结果 + */ + public int updateGenTableColumn(GenTableColumn genTableColumn); + + /** + * 删除业务字段 + * + * @param genTableColumns 列数据 + * @return 结果 + */ + public int deleteGenTableColumns(List genTableColumns); + + /** + * 批量删除业务字段 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteGenTableColumnByIds(Long[] ids); +} diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java new file mode 100644 index 0000000..c0197d3 --- /dev/null +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java @@ -0,0 +1,83 @@ +package com.ruoyi.generator.mapper; + +import java.util.List; +import com.ruoyi.generator.domain.GenTable; + +/** + * 业务 数据层 + * + * @author zhihuiwuliu + */ +public interface GenTableMapper +{ + /** + * 查询业务列表 + * + * @param genTable 业务信息 + * @return 业务集合 + */ + public List selectGenTableList(GenTable genTable); + + /** + * 查询据库列表 + * + * @param genTable 业务信息 + * @return 数据库表集合 + */ + public List selectDbTableList(GenTable genTable); + + /** + * 查询据库列表 + * + * @param tableNames 表名称组 + * @return 数据库表集合 + */ + public List selectDbTableListByNames(String[] tableNames); + + /** + * 查询所有表信息 + * + * @return 表信息集合 + */ + public List selectGenTableAll(); + + /** + * 查询表ID业务信息 + * + * @param id 业务ID + * @return 业务信息 + */ + public GenTable selectGenTableById(Long id); + + /** + * 查询表名称业务信息 + * + * @param tableName 表名称 + * @return 业务信息 + */ + public GenTable selectGenTableByName(String tableName); + + /** + * 新增业务 + * + * @param genTable 业务信息 + * @return 结果 + */ + public int insertGenTable(GenTable genTable); + + /** + * 修改业务 + * + * @param genTable 业务信息 + * @return 结果 + */ + public int updateGenTable(GenTable genTable); + + /** + * 批量删除业务 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteGenTableByIds(Long[] ids); +} diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableColumnServiceImpl.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableColumnServiceImpl.java new file mode 100644 index 0000000..633d71f --- /dev/null +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableColumnServiceImpl.java @@ -0,0 +1,68 @@ +package com.ruoyi.generator.service; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.common.core.text.Convert; +import com.ruoyi.generator.domain.GenTableColumn; +import com.ruoyi.generator.mapper.GenTableColumnMapper; + +/** + * 业务字段 服务层实现 + * + * @author zhihuiwuliu + */ +@Service +public class GenTableColumnServiceImpl implements IGenTableColumnService +{ + @Autowired + private GenTableColumnMapper genTableColumnMapper; + + /** + * 查询业务字段列表 + * + * @param tableId 业务字段编号 + * @return 业务字段集合 + */ + @Override + public List selectGenTableColumnListByTableId(Long tableId) + { + return genTableColumnMapper.selectGenTableColumnListByTableId(tableId); + } + + /** + * 新增业务字段 + * + * @param genTableColumn 业务字段信息 + * @return 结果 + */ + @Override + public int insertGenTableColumn(GenTableColumn genTableColumn) + { + return genTableColumnMapper.insertGenTableColumn(genTableColumn); + } + + /** + * 修改业务字段 + * + * @param genTableColumn 业务字段信息 + * @return 结果 + */ + @Override + public int updateGenTableColumn(GenTableColumn genTableColumn) + { + return genTableColumnMapper.updateGenTableColumn(genTableColumn); + } + + /** + * 删除业务字段对象 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + @Override + public int deleteGenTableColumnByIds(String ids) + { + return genTableColumnMapper.deleteGenTableColumnByIds(Convert.toLongArray(ids)); + } +} diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java new file mode 100644 index 0000000..b6958ee --- /dev/null +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java @@ -0,0 +1,521 @@ +package com.ruoyi.generator.service; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.StringWriter; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.Velocity; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.constant.GenConstants; +import com.ruoyi.common.core.text.CharsetKit; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.generator.domain.GenTable; +import com.ruoyi.generator.domain.GenTableColumn; +import com.ruoyi.generator.mapper.GenTableColumnMapper; +import com.ruoyi.generator.mapper.GenTableMapper; +import com.ruoyi.generator.util.GenUtils; +import com.ruoyi.generator.util.VelocityInitializer; +import com.ruoyi.generator.util.VelocityUtils; + +/** + * 业务 服务层实现 + * + * @author zhihuiwuliu + */ +@Service +public class GenTableServiceImpl implements IGenTableService +{ + private static final Logger log = LoggerFactory.getLogger(GenTableServiceImpl.class); + + @Autowired + private GenTableMapper genTableMapper; + + @Autowired + private GenTableColumnMapper genTableColumnMapper; + + /** + * 查询业务信息 + * + * @param id 业务ID + * @return 业务信息 + */ + @Override + public GenTable selectGenTableById(Long id) + { + GenTable genTable = genTableMapper.selectGenTableById(id); + setTableFromOptions(genTable); + return genTable; + } + + /** + * 查询业务列表 + * + * @param genTable 业务信息 + * @return 业务集合 + */ + @Override + public List selectGenTableList(GenTable genTable) + { + return genTableMapper.selectGenTableList(genTable); + } + + /** + * 查询据库列表 + * + * @param genTable 业务信息 + * @return 数据库表集合 + */ + @Override + public List selectDbTableList(GenTable genTable) + { + return genTableMapper.selectDbTableList(genTable); + } + + /** + * 查询据库列表 + * + * @param tableNames 表名称组 + * @return 数据库表集合 + */ + @Override + public List selectDbTableListByNames(String[] tableNames) + { + return genTableMapper.selectDbTableListByNames(tableNames); + } + + /** + * 查询所有表信息 + * + * @return 表信息集合 + */ + @Override + public List selectGenTableAll() + { + return genTableMapper.selectGenTableAll(); + } + + /** + * 修改业务 + * + * @param genTable 业务信息 + * @return 结果 + */ + @Override + @Transactional + public void updateGenTable(GenTable genTable) + { + String options = JSON.toJSONString(genTable.getParams()); + genTable.setOptions(options); + int row = genTableMapper.updateGenTable(genTable); + if (row > 0) + { + for (GenTableColumn cenTableColumn : genTable.getColumns()) + { + genTableColumnMapper.updateGenTableColumn(cenTableColumn); + } + } + } + + /** + * 删除业务对象 + * + * @param tableIds 需要删除的数据ID + * @return 结果 + */ + @Override + @Transactional + public void deleteGenTableByIds(Long[] tableIds) + { + genTableMapper.deleteGenTableByIds(tableIds); + genTableColumnMapper.deleteGenTableColumnByIds(tableIds); + } + + /** + * 导入表结构 + * + * @param tableList 导入表列表 + */ + @Override + @Transactional + public void importGenTable(List tableList) + { + String operName = SecurityUtils.getUsername(); + try + { + for (GenTable table : tableList) + { + String tableName = table.getTableName(); + GenUtils.initTable(table, operName); + int row = genTableMapper.insertGenTable(table); + if (row > 0) + { + // 保存列信息 + List genTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName); + for (GenTableColumn column : genTableColumns) + { + GenUtils.initColumnField(column, table); + genTableColumnMapper.insertGenTableColumn(column); + } + } + } + } + catch (Exception e) + { + throw new ServiceException("导入失败:" + e.getMessage()); + } + } + + /** + * 预览代码 + * + * @param tableId 表编号 + * @return 预览数据列表 + */ + @Override + public Map previewCode(Long tableId) + { + Map dataMap = new LinkedHashMap<>(); + // 查询表信息 + GenTable table = genTableMapper.selectGenTableById(tableId); + // 设置主子表信息 + setSubTable(table); + // 设置主键列信息 + setPkColumn(table); + VelocityInitializer.initVelocity(); + + VelocityContext context = VelocityUtils.prepareContext(table); + + // 获取模板列表 + List templates = VelocityUtils.getTemplateList(table.getTplCategory()); + for (String template : templates) + { + // 渲染模板 + StringWriter sw = new StringWriter(); + Template tpl = Velocity.getTemplate(template, Constants.UTF8); + tpl.merge(context, sw); + dataMap.put(template, sw.toString()); + } + return dataMap; + } + + /** + * 生成代码(下载方式) + * + * @param tableName 表名称 + * @return 数据 + */ + @Override + public byte[] downloadCode(String tableName) + { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + ZipOutputStream zip = new ZipOutputStream(outputStream); + generatorCode(tableName, zip); + IOUtils.closeQuietly(zip); + return outputStream.toByteArray(); + } + + /** + * 生成代码(自定义路径) + * + * @param tableName 表名称 + */ + @Override + public void generatorCode(String tableName) + { + // 查询表信息 + GenTable table = genTableMapper.selectGenTableByName(tableName); + // 设置主子表信息 + setSubTable(table); + // 设置主键列信息 + setPkColumn(table); + + VelocityInitializer.initVelocity(); + + VelocityContext context = VelocityUtils.prepareContext(table); + + // 获取模板列表 + List templates = VelocityUtils.getTemplateList(table.getTplCategory()); + for (String template : templates) + { + if (!StringUtils.containsAny(template, "sql.vm", "api.js.vm", "index.vue.vm", "index-tree.vue.vm")) + { + // 渲染模板 + StringWriter sw = new StringWriter(); + Template tpl = Velocity.getTemplate(template, Constants.UTF8); + tpl.merge(context, sw); + try + { + String path = getGenPath(table, template); + FileUtils.writeStringToFile(new File(path), sw.toString(), CharsetKit.UTF_8); + } + catch (IOException e) + { + throw new ServiceException("渲染模板失败,表名:" + table.getTableName()); + } + } + } + } + + /** + * 同步数据库 + * + * @param tableName 表名称 + */ + @Override + @Transactional + public void synchDb(String tableName) + { + GenTable table = genTableMapper.selectGenTableByName(tableName); + List tableColumns = table.getColumns(); + Map tableColumnMap = tableColumns.stream().collect(Collectors.toMap(GenTableColumn::getColumnName, Function.identity())); + + List dbTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName); + if (StringUtils.isEmpty(dbTableColumns)) + { + throw new ServiceException("同步数据失败,原表结构不存在"); + } + List dbTableColumnNames = dbTableColumns.stream().map(GenTableColumn::getColumnName).collect(Collectors.toList()); + + dbTableColumns.forEach(column -> { + GenUtils.initColumnField(column, table); + if (tableColumnMap.containsKey(column.getColumnName())) + { + GenTableColumn prevColumn = tableColumnMap.get(column.getColumnName()); + column.setColumnId(prevColumn.getColumnId()); + if (column.isList()) + { + // 如果是列表,继续保留查询方式/字典类型选项 + column.setDictType(prevColumn.getDictType()); + column.setQueryType(prevColumn.getQueryType()); + } + if (StringUtils.isNotEmpty(prevColumn.getIsRequired()) && !column.isPk() + && (column.isInsert() || column.isEdit()) + && ((column.isUsableColumn()) || (!column.isSuperColumn()))) + { + // 如果是(新增/修改&非主键/非忽略及父属性),继续保留必填/显示类型选项 + column.setIsRequired(prevColumn.getIsRequired()); + column.setHtmlType(prevColumn.getHtmlType()); + } + genTableColumnMapper.updateGenTableColumn(column); + } + else + { + genTableColumnMapper.insertGenTableColumn(column); + } + }); + + List delColumns = tableColumns.stream().filter(column -> !dbTableColumnNames.contains(column.getColumnName())).collect(Collectors.toList()); + if (StringUtils.isNotEmpty(delColumns)) + { + genTableColumnMapper.deleteGenTableColumns(delColumns); + } + } + + /** + * 批量生成代码(下载方式) + * + * @param tableNames 表数组 + * @return 数据 + */ + @Override + public byte[] downloadCode(String[] tableNames) + { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + ZipOutputStream zip = new ZipOutputStream(outputStream); + for (String tableName : tableNames) + { + generatorCode(tableName, zip); + } + IOUtils.closeQuietly(zip); + return outputStream.toByteArray(); + } + + /** + * 查询表信息并生成代码 + */ + private void generatorCode(String tableName, ZipOutputStream zip) + { + // 查询表信息 + GenTable table = genTableMapper.selectGenTableByName(tableName); + // 设置主子表信息 + setSubTable(table); + // 设置主键列信息 + setPkColumn(table); + + VelocityInitializer.initVelocity(); + + VelocityContext context = VelocityUtils.prepareContext(table); + + // 获取模板列表 + List templates = VelocityUtils.getTemplateList(table.getTplCategory()); + for (String template : templates) + { + // 渲染模板 + StringWriter sw = new StringWriter(); + Template tpl = Velocity.getTemplate(template, Constants.UTF8); + tpl.merge(context, sw); + try + { + // 添加到zip + zip.putNextEntry(new ZipEntry(VelocityUtils.getFileName(template, table))); + IOUtils.write(sw.toString(), zip, Constants.UTF8); + IOUtils.closeQuietly(sw); + zip.flush(); + zip.closeEntry(); + } + catch (IOException e) + { + log.error("渲染模板失败,表名:" + table.getTableName(), e); + } + } + } + + /** + * 修改保存参数校验 + * + * @param genTable 业务信息 + */ + @Override + public void validateEdit(GenTable genTable) + { + if (GenConstants.TPL_TREE.equals(genTable.getTplCategory())) + { + String options = JSON.toJSONString(genTable.getParams()); + JSONObject paramsObj = JSON.parseObject(options); + if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_CODE))) + { + throw new ServiceException("树编码字段不能为空"); + } + else if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_PARENT_CODE))) + { + throw new ServiceException("树父编码字段不能为空"); + } + else if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_NAME))) + { + throw new ServiceException("树名称字段不能为空"); + } + else if (GenConstants.TPL_SUB.equals(genTable.getTplCategory())) + { + if (StringUtils.isEmpty(genTable.getSubTableName())) + { + throw new ServiceException("关联子表的表名不能为空"); + } + else if (StringUtils.isEmpty(genTable.getSubTableFkName())) + { + throw new ServiceException("子表关联的外键名不能为空"); + } + } + } + } + + /** + * 设置主键列信息 + * + * @param table 业务表信息 + */ + public void setPkColumn(GenTable table) + { + for (GenTableColumn column : table.getColumns()) + { + if (column.isPk()) + { + table.setPkColumn(column); + break; + } + } + if (StringUtils.isNull(table.getPkColumn())) + { + table.setPkColumn(table.getColumns().get(0)); + } + if (GenConstants.TPL_SUB.equals(table.getTplCategory())) + { + for (GenTableColumn column : table.getSubTable().getColumns()) + { + if (column.isPk()) + { + table.getSubTable().setPkColumn(column); + break; + } + } + if (StringUtils.isNull(table.getSubTable().getPkColumn())) + { + table.getSubTable().setPkColumn(table.getSubTable().getColumns().get(0)); + } + } + } + + /** + * 设置主子表信息 + * + * @param table 业务表信息 + */ + public void setSubTable(GenTable table) + { + String subTableName = table.getSubTableName(); + if (StringUtils.isNotEmpty(subTableName)) + { + table.setSubTable(genTableMapper.selectGenTableByName(subTableName)); + } + } + + /** + * 设置代码生成其他选项值 + * + * @param genTable 设置后的生成对象 + */ + public void setTableFromOptions(GenTable genTable) + { + JSONObject paramsObj = JSON.parseObject(genTable.getOptions()); + if (StringUtils.isNotNull(paramsObj)) + { + String treeCode = paramsObj.getString(GenConstants.TREE_CODE); + String treeParentCode = paramsObj.getString(GenConstants.TREE_PARENT_CODE); + String treeName = paramsObj.getString(GenConstants.TREE_NAME); + String parentMenuId = paramsObj.getString(GenConstants.PARENT_MENU_ID); + String parentMenuName = paramsObj.getString(GenConstants.PARENT_MENU_NAME); + + genTable.setTreeCode(treeCode); + genTable.setTreeParentCode(treeParentCode); + genTable.setTreeName(treeName); + genTable.setParentMenuId(parentMenuId); + genTable.setParentMenuName(parentMenuName); + } + } + + /** + * 获取代码生成地址 + * + * @param table 业务表信息 + * @param template 模板文件路径 + * @return 生成地址 + */ + public static String getGenPath(GenTable table, String template) + { + String genPath = table.getGenPath(); + if (StringUtils.equals(genPath, "/")) + { + return System.getProperty("user.dir") + File.separator + "src" + File.separator + VelocityUtils.getFileName(template, table); + } + return genPath + File.separator + VelocityUtils.getFileName(template, table); + } +} \ No newline at end of file diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java new file mode 100644 index 0000000..0f4ff3c --- /dev/null +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java @@ -0,0 +1,44 @@ +package com.ruoyi.generator.service; + +import java.util.List; +import com.ruoyi.generator.domain.GenTableColumn; + +/** + * 业务字段 服务层 + * + * @author zhihuiwuliu + */ +public interface IGenTableColumnService +{ + /** + * 查询业务字段列表 + * + * @param tableId 业务字段编号 + * @return 业务字段集合 + */ + public List selectGenTableColumnListByTableId(Long tableId); + + /** + * 新增业务字段 + * + * @param genTableColumn 业务字段信息 + * @return 结果 + */ + public int insertGenTableColumn(GenTableColumn genTableColumn); + + /** + * 修改业务字段 + * + * @param genTableColumn 业务字段信息 + * @return 结果 + */ + public int updateGenTableColumn(GenTableColumn genTableColumn); + + /** + * 删除业务字段信息 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteGenTableColumnByIds(String ids); +} diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java new file mode 100644 index 0000000..0e4d02d --- /dev/null +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java @@ -0,0 +1,121 @@ +package com.ruoyi.generator.service; + +import java.util.List; +import java.util.Map; +import com.ruoyi.generator.domain.GenTable; + +/** + * 业务 服务层 + * + * @author zhihuiwuliu + */ +public interface IGenTableService +{ + /** + * 查询业务列表 + * + * @param genTable 业务信息 + * @return 业务集合 + */ + public List selectGenTableList(GenTable genTable); + + /** + * 查询据库列表 + * + * @param genTable 业务信息 + * @return 数据库表集合 + */ + public List selectDbTableList(GenTable genTable); + + /** + * 查询据库列表 + * + * @param tableNames 表名称组 + * @return 数据库表集合 + */ + public List selectDbTableListByNames(String[] tableNames); + + /** + * 查询所有表信息 + * + * @return 表信息集合 + */ + public List selectGenTableAll(); + + /** + * 查询业务信息 + * + * @param id 业务ID + * @return 业务信息 + */ + public GenTable selectGenTableById(Long id); + + /** + * 修改业务 + * + * @param genTable 业务信息 + * @return 结果 + */ + public void updateGenTable(GenTable genTable); + + /** + * 删除业务信息 + * + * @param tableIds 需要删除的表数据ID + * @return 结果 + */ + public void deleteGenTableByIds(Long[] tableIds); + + /** + * 导入表结构 + * + * @param tableList 导入表列表 + */ + public void importGenTable(List tableList); + + /** + * 预览代码 + * + * @param tableId 表编号 + * @return 预览数据列表 + */ + public Map previewCode(Long tableId); + + /** + * 生成代码(下载方式) + * + * @param tableName 表名称 + * @return 数据 + */ + public byte[] downloadCode(String tableName); + + /** + * 生成代码(自定义路径) + * + * @param tableName 表名称 + * @return 数据 + */ + public void generatorCode(String tableName); + + /** + * 同步数据库 + * + * @param tableName 表名称 + */ + public void synchDb(String tableName); + + /** + * 批量生成代码(下载方式) + * + * @param tableNames 表数组 + * @return 数据 + */ + public byte[] downloadCode(String[] tableNames); + + /** + * 修改保存参数校验 + * + * @param genTable 业务信息 + */ + public void validateEdit(GenTable genTable); +} diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java new file mode 100644 index 0000000..e5edcee --- /dev/null +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java @@ -0,0 +1,257 @@ +package com.ruoyi.generator.util; + +import java.util.Arrays; +import org.apache.commons.lang3.RegExUtils; +import com.ruoyi.common.constant.GenConstants; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.generator.config.GenConfig; +import com.ruoyi.generator.domain.GenTable; +import com.ruoyi.generator.domain.GenTableColumn; + +/** + * 代码生成器 工具类 + * + * @author zhihuiwuliu + */ +public class GenUtils +{ + /** + * 初始化表信息 + */ + public static void initTable(GenTable genTable, String operName) + { + genTable.setClassName(convertClassName(genTable.getTableName())); + genTable.setPackageName(GenConfig.getPackageName()); + genTable.setModuleName(getModuleName(GenConfig.getPackageName())); + genTable.setBusinessName(getBusinessName(genTable.getTableName())); + genTable.setFunctionName(replaceText(genTable.getTableComment())); + genTable.setFunctionAuthor(GenConfig.getAuthor()); + genTable.setCreateBy(operName); + } + + /** + * 初始化列属性字段 + */ + public static void initColumnField(GenTableColumn column, GenTable table) + { + String dataType = getDbType(column.getColumnType()); + String columnName = column.getColumnName(); + column.setTableId(table.getTableId()); + column.setCreateBy(table.getCreateBy()); + // 设置java字段名 + column.setJavaField(StringUtils.toCamelCase(columnName)); + // 设置默认类型 + column.setJavaType(GenConstants.TYPE_STRING); + column.setQueryType(GenConstants.QUERY_EQ); + + if (arraysContains(GenConstants.COLUMNTYPE_STR, dataType) || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType)) + { + // 字符串长度超过500设置为文本域 + Integer columnLength = getColumnLength(column.getColumnType()); + String htmlType = columnLength >= 500 || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType) ? GenConstants.HTML_TEXTAREA : GenConstants.HTML_INPUT; + column.setHtmlType(htmlType); + } + else if (arraysContains(GenConstants.COLUMNTYPE_TIME, dataType)) + { + column.setJavaType(GenConstants.TYPE_DATE); + column.setHtmlType(GenConstants.HTML_DATETIME); + } + else if (arraysContains(GenConstants.COLUMNTYPE_NUMBER, dataType)) + { + column.setHtmlType(GenConstants.HTML_INPUT); + + // 如果是浮点型 统一用BigDecimal + String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), ","); + if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0) + { + column.setJavaType(GenConstants.TYPE_BIGDECIMAL); + } + // 如果是整形 + else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10) + { + column.setJavaType(GenConstants.TYPE_INTEGER); + } + // 长整形 + else + { + column.setJavaType(GenConstants.TYPE_LONG); + } + } + + // 插入字段(默认所有字段都需要插入) + column.setIsInsert(GenConstants.REQUIRE); + + // 编辑字段 + if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName) && !column.isPk()) + { + column.setIsEdit(GenConstants.REQUIRE); + } + // 列表字段 + if (!arraysContains(GenConstants.COLUMNNAME_NOT_LIST, columnName) && !column.isPk()) + { + column.setIsList(GenConstants.REQUIRE); + } + // 查询字段 + if (!arraysContains(GenConstants.COLUMNNAME_NOT_QUERY, columnName) && !column.isPk()) + { + column.setIsQuery(GenConstants.REQUIRE); + } + + // 查询字段类型 + if (StringUtils.endsWithIgnoreCase(columnName, "name")) + { + column.setQueryType(GenConstants.QUERY_LIKE); + } + // 状态字段设置单选框 + if (StringUtils.endsWithIgnoreCase(columnName, "status")) + { + column.setHtmlType(GenConstants.HTML_RADIO); + } + // 类型&性别字段设置下拉框 + else if (StringUtils.endsWithIgnoreCase(columnName, "type") + || StringUtils.endsWithIgnoreCase(columnName, "sex")) + { + column.setHtmlType(GenConstants.HTML_SELECT); + } + // 图片字段设置图片上传控件 + else if (StringUtils.endsWithIgnoreCase(columnName, "image")) + { + column.setHtmlType(GenConstants.HTML_IMAGE_UPLOAD); + } + // 文件字段设置文件上传控件 + else if (StringUtils.endsWithIgnoreCase(columnName, "file")) + { + column.setHtmlType(GenConstants.HTML_FILE_UPLOAD); + } + // 内容字段设置富文本控件 + else if (StringUtils.endsWithIgnoreCase(columnName, "content")) + { + column.setHtmlType(GenConstants.HTML_EDITOR); + } + } + + /** + * 校验数组是否包含指定值 + * + * @param arr 数组 + * @param targetValue 值 + * @return 是否包含 + */ + public static boolean arraysContains(String[] arr, String targetValue) + { + return Arrays.asList(arr).contains(targetValue); + } + + /** + * 获取模块名 + * + * @param packageName 包名 + * @return 模块名 + */ + public static String getModuleName(String packageName) + { + int lastIndex = packageName.lastIndexOf("."); + int nameLength = packageName.length(); + return StringUtils.substring(packageName, lastIndex + 1, nameLength); + } + + /** + * 获取业务名 + * + * @param tableName 表名 + * @return 业务名 + */ + public static String getBusinessName(String tableName) + { + int lastIndex = tableName.lastIndexOf("_"); + int nameLength = tableName.length(); + return StringUtils.substring(tableName, lastIndex + 1, nameLength); + } + + /** + * 表名转换成Java类名 + * + * @param tableName 表名称 + * @return 类名 + */ + public static String convertClassName(String tableName) + { + boolean autoRemovePre = GenConfig.getAutoRemovePre(); + String tablePrefix = GenConfig.getTablePrefix(); + if (autoRemovePre && StringUtils.isNotEmpty(tablePrefix)) + { + String[] searchList = StringUtils.split(tablePrefix, ","); + tableName = replaceFirst(tableName, searchList); + } + return StringUtils.convertToCamelCase(tableName); + } + + /** + * 批量替换前缀 + * + * @param replacementm 替换值 + * @param searchList 替换列表 + * @return + */ + public static String replaceFirst(String replacementm, String[] searchList) + { + String text = replacementm; + for (String searchString : searchList) + { + if (replacementm.startsWith(searchString)) + { + text = replacementm.replaceFirst(searchString, ""); + break; + } + } + return text; + } + + /** + * 关键字替换 + * + * @param text 需要被替换的名字 + * @return 替换后的名字 + */ + public static String replaceText(String text) + { + return RegExUtils.replaceAll(text, "(?:表|智慧物流数据中心)", ""); + } + + /** + * 获取数据库类型字段 + * + * @param columnType 列类型 + * @return 截取后的列类型 + */ + public static String getDbType(String columnType) + { + if (StringUtils.indexOf(columnType, "(") > 0) + { + return StringUtils.substringBefore(columnType, "("); + } + else + { + return columnType; + } + } + + /** + * 获取字段长度 + * + * @param columnType 列类型 + * @return 截取后的列类型 + */ + public static Integer getColumnLength(String columnType) + { + if (StringUtils.indexOf(columnType, "(") > 0) + { + String length = StringUtils.substringBetween(columnType, "(", ")"); + return Integer.valueOf(length); + } + else + { + return 0; + } + } +} diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java new file mode 100644 index 0000000..f9a7852 --- /dev/null +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java @@ -0,0 +1,34 @@ +package com.ruoyi.generator.util; + +import java.util.Properties; +import org.apache.velocity.app.Velocity; +import com.ruoyi.common.constant.Constants; + +/** + * VelocityEngine工厂 + * + * @author zhihuiwuliu + */ +public class VelocityInitializer +{ + /** + * 初始化vm方法 + */ + public static void initVelocity() + { + Properties p = new Properties(); + try + { + // 加载classpath目录下的vm文件 + p.setProperty("resource.loader.file.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); + // 定义字符集 + p.setProperty(Velocity.INPUT_ENCODING, Constants.UTF8); + // 初始化Velocity引擎,指定配置Properties + Velocity.init(p); + } + catch (Exception e) + { + throw new RuntimeException(e); + } + } +} diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java new file mode 100644 index 0000000..9488e72 --- /dev/null +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java @@ -0,0 +1,402 @@ +package com.ruoyi.generator.util; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.apache.velocity.VelocityContext; +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.ruoyi.common.constant.GenConstants; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.generator.domain.GenTable; +import com.ruoyi.generator.domain.GenTableColumn; + +/** + * 模板处理工具类 + * + * @author zhihuiwuliu + */ +public class VelocityUtils +{ + /** 项目空间路径 */ + private static final String PROJECT_PATH = "main/java"; + + /** mybatis空间路径 */ + private static final String MYBATIS_PATH = "main/resources/mapper"; + + /** 默认上级菜单,系统工具 */ + private static final String DEFAULT_PARENT_MENU_ID = "3"; + + /** + * 设置模板变量信息 + * + * @return 模板列表 + */ + public static VelocityContext prepareContext(GenTable genTable) + { + String moduleName = genTable.getModuleName(); + String businessName = genTable.getBusinessName(); + String packageName = genTable.getPackageName(); + String tplCategory = genTable.getTplCategory(); + String functionName = genTable.getFunctionName(); + + VelocityContext velocityContext = new VelocityContext(); + velocityContext.put("tplCategory", genTable.getTplCategory()); + velocityContext.put("tableName", genTable.getTableName()); + velocityContext.put("functionName", StringUtils.isNotEmpty(functionName) ? functionName : "【请填写功能名称】"); + velocityContext.put("ClassName", genTable.getClassName()); + velocityContext.put("className", StringUtils.uncapitalize(genTable.getClassName())); + velocityContext.put("moduleName", genTable.getModuleName()); + velocityContext.put("BusinessName", StringUtils.capitalize(genTable.getBusinessName())); + velocityContext.put("businessName", genTable.getBusinessName()); + velocityContext.put("basePackage", getPackagePrefix(packageName)); + velocityContext.put("packageName", packageName); + velocityContext.put("author", genTable.getFunctionAuthor()); + velocityContext.put("datetime", DateUtils.getDate()); + velocityContext.put("pkColumn", genTable.getPkColumn()); + velocityContext.put("importList", getImportList(genTable)); + velocityContext.put("permissionPrefix", getPermissionPrefix(moduleName, businessName)); + velocityContext.put("columns", genTable.getColumns()); + velocityContext.put("table", genTable); + velocityContext.put("dicts", getDicts(genTable)); + setMenuVelocityContext(velocityContext, genTable); + if (GenConstants.TPL_TREE.equals(tplCategory)) + { + setTreeVelocityContext(velocityContext, genTable); + } + if (GenConstants.TPL_SUB.equals(tplCategory)) + { + setSubVelocityContext(velocityContext, genTable); + } + return velocityContext; + } + + public static void setMenuVelocityContext(VelocityContext context, GenTable genTable) + { + String options = genTable.getOptions(); + JSONObject paramsObj = JSON.parseObject(options); + String parentMenuId = getParentMenuId(paramsObj); + context.put("parentMenuId", parentMenuId); + } + + public static void setTreeVelocityContext(VelocityContext context, GenTable genTable) + { + String options = genTable.getOptions(); + JSONObject paramsObj = JSON.parseObject(options); + String treeCode = getTreecode(paramsObj); + String treeParentCode = getTreeParentCode(paramsObj); + String treeName = getTreeName(paramsObj); + + context.put("treeCode", treeCode); + context.put("treeParentCode", treeParentCode); + context.put("treeName", treeName); + context.put("expandColumn", getExpandColumn(genTable)); + if (paramsObj.containsKey(GenConstants.TREE_PARENT_CODE)) + { + context.put("tree_parent_code", paramsObj.getString(GenConstants.TREE_PARENT_CODE)); + } + if (paramsObj.containsKey(GenConstants.TREE_NAME)) + { + context.put("tree_name", paramsObj.getString(GenConstants.TREE_NAME)); + } + } + + public static void setSubVelocityContext(VelocityContext context, GenTable genTable) + { + GenTable subTable = genTable.getSubTable(); + String subTableName = genTable.getSubTableName(); + String subTableFkName = genTable.getSubTableFkName(); + String subClassName = genTable.getSubTable().getClassName(); + String subTableFkClassName = StringUtils.convertToCamelCase(subTableFkName); + + context.put("subTable", subTable); + context.put("subTableName", subTableName); + context.put("subTableFkName", subTableFkName); + context.put("subTableFkClassName", subTableFkClassName); + context.put("subTableFkclassName", StringUtils.uncapitalize(subTableFkClassName)); + context.put("subClassName", subClassName); + context.put("subclassName", StringUtils.uncapitalize(subClassName)); + context.put("subImportList", getImportList(genTable.getSubTable())); + } + + /** + * 获取模板信息 + * + * @return 模板列表 + */ + public static List getTemplateList(String tplCategory) + { + List templates = new ArrayList(); + templates.add("vm/java/domain.java.vm"); + templates.add("vm/java/mapper.java.vm"); + templates.add("vm/java/service.java.vm"); + templates.add("vm/java/serviceImpl.java.vm"); + templates.add("vm/java/controller.java.vm"); + templates.add("vm/xml/mapper.xml.vm"); + templates.add("vm/sql/sql.vm"); + templates.add("vm/js/api.js.vm"); + if (GenConstants.TPL_CRUD.equals(tplCategory)) + { + templates.add("vm/vue/index.vue.vm"); + } + else if (GenConstants.TPL_TREE.equals(tplCategory)) + { + templates.add("vm/vue/index-tree.vue.vm"); + } + else if (GenConstants.TPL_SUB.equals(tplCategory)) + { + templates.add("vm/vue/index.vue.vm"); + templates.add("vm/java/sub-domain.java.vm"); + } + return templates; + } + + /** + * 获取文件名 + */ + public static String getFileName(String template, GenTable genTable) + { + // 文件名称 + String fileName = ""; + // 包路径 + String packageName = genTable.getPackageName(); + // 模块名 + String moduleName = genTable.getModuleName(); + // 大写类名 + String className = genTable.getClassName(); + // 业务名称 + String businessName = genTable.getBusinessName(); + + String javaPath = PROJECT_PATH + "/" + StringUtils.replace(packageName, ".", "/"); + String mybatisPath = MYBATIS_PATH + "/" + moduleName; + String vuePath = "vue"; + + if (template.contains("domain.java.vm")) + { + fileName = StringUtils.format("{}/domain/{}.java", javaPath, className); + } + if (template.contains("sub-domain.java.vm") && StringUtils.equals(GenConstants.TPL_SUB, genTable.getTplCategory())) + { + fileName = StringUtils.format("{}/domain/{}.java", javaPath, genTable.getSubTable().getClassName()); + } + else if (template.contains("mapper.java.vm")) + { + fileName = StringUtils.format("{}/mapper/{}Mapper.java", javaPath, className); + } + else if (template.contains("service.java.vm")) + { + fileName = StringUtils.format("{}/service/I{}Service.java", javaPath, className); + } + else if (template.contains("serviceImpl.java.vm")) + { + fileName = StringUtils.format("{}/service/impl/{}ServiceImpl.java", javaPath, className); + } + else if (template.contains("controller.java.vm")) + { + fileName = StringUtils.format("{}/controller/{}Controller.java", javaPath, className); + } + else if (template.contains("mapper.xml.vm")) + { + fileName = StringUtils.format("{}/{}Mapper.xml", mybatisPath, className); + } + else if (template.contains("sql.vm")) + { + fileName = businessName + "Menu.sql"; + } + else if (template.contains("api.js.vm")) + { + fileName = StringUtils.format("{}/api/{}/{}.js", vuePath, moduleName, businessName); + } + else if (template.contains("index.vue.vm")) + { + fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName); + } + else if (template.contains("index-tree.vue.vm")) + { + fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName); + } + return fileName; + } + + /** + * 获取包前缀 + * + * @param packageName 包名称 + * @return 包前缀名称 + */ + public static String getPackagePrefix(String packageName) + { + int lastIndex = packageName.lastIndexOf("."); + return StringUtils.substring(packageName, 0, lastIndex); + } + + /** + * 根据列类型获取导入包 + * + * @param genTable 业务表对象 + * @return 返回需要导入的包列表 + */ + public static HashSet getImportList(GenTable genTable) + { + List columns = genTable.getColumns(); + GenTable subGenTable = genTable.getSubTable(); + HashSet importList = new HashSet(); + if (StringUtils.isNotNull(subGenTable)) + { + importList.add("java.util.List"); + } + for (GenTableColumn column : columns) + { + if (!column.isSuperColumn() && GenConstants.TYPE_DATE.equals(column.getJavaType())) + { + importList.add("java.util.Date"); + importList.add("com.fasterxml.jackson.annotation.JsonFormat"); + } + else if (!column.isSuperColumn() && GenConstants.TYPE_BIGDECIMAL.equals(column.getJavaType())) + { + importList.add("java.math.BigDecimal"); + } + } + return importList; + } + + /** + * 根据列类型获取字典组 + * + * @param genTable 业务表对象 + * @return 返回字典组 + */ + public static String getDicts(GenTable genTable) + { + List columns = genTable.getColumns(); + Set dicts = new HashSet(); + addDicts(dicts, columns); + if (StringUtils.isNotNull(genTable.getSubTable())) + { + List subColumns = genTable.getSubTable().getColumns(); + addDicts(dicts, subColumns); + } + return StringUtils.join(dicts, ", "); + } + + /** + * 添加字典列表 + * + * @param dicts 字典列表 + * @param columns 列集合 + */ + public static void addDicts(Set dicts, List columns) + { + for (GenTableColumn column : columns) + { + if (!column.isSuperColumn() && StringUtils.isNotEmpty(column.getDictType()) && StringUtils.equalsAny( + column.getHtmlType(), + new String[] { GenConstants.HTML_SELECT, GenConstants.HTML_RADIO, GenConstants.HTML_CHECKBOX })) + { + dicts.add("'" + column.getDictType() + "'"); + } + } + } + + /** + * 获取权限前缀 + * + * @param moduleName 模块名称 + * @param businessName 业务名称 + * @return 返回权限前缀 + */ + public static String getPermissionPrefix(String moduleName, String businessName) + { + return StringUtils.format("{}:{}", moduleName, businessName); + } + + /** + * 获取上级菜单ID字段 + * + * @param paramsObj 生成其他选项 + * @return 上级菜单ID字段 + */ + public static String getParentMenuId(JSONObject paramsObj) + { + if (StringUtils.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.PARENT_MENU_ID) + && StringUtils.isNotEmpty(paramsObj.getString(GenConstants.PARENT_MENU_ID))) + { + return paramsObj.getString(GenConstants.PARENT_MENU_ID); + } + return DEFAULT_PARENT_MENU_ID; + } + + /** + * 获取树编码 + * + * @param paramsObj 生成其他选项 + * @return 树编码 + */ + public static String getTreecode(JSONObject paramsObj) + { + if (paramsObj.containsKey(GenConstants.TREE_CODE)) + { + return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_CODE)); + } + return StringUtils.EMPTY; + } + + /** + * 获取树父编码 + * + * @param paramsObj 生成其他选项 + * @return 树父编码 + */ + public static String getTreeParentCode(JSONObject paramsObj) + { + if (paramsObj.containsKey(GenConstants.TREE_PARENT_CODE)) + { + return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_PARENT_CODE)); + } + return StringUtils.EMPTY; + } + + /** + * 获取树名称 + * + * @param paramsObj 生成其他选项 + * @return 树名称 + */ + public static String getTreeName(JSONObject paramsObj) + { + if (paramsObj.containsKey(GenConstants.TREE_NAME)) + { + return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_NAME)); + } + return StringUtils.EMPTY; + } + + /** + * 获取需要在哪一列上面显示展开按钮 + * + * @param genTable 业务表对象 + * @return 展开按钮列序号 + */ + public static int getExpandColumn(GenTable genTable) + { + String options = genTable.getOptions(); + JSONObject paramsObj = JSON.parseObject(options); + String treeName = paramsObj.getString(GenConstants.TREE_NAME); + int num = 0; + for (GenTableColumn column : genTable.getColumns()) + { + if (column.isList()) + { + num++; + String columnName = column.getColumnName(); + if (columnName.equals(treeName)) + { + break; + } + } + } + return num; + } +} diff --git a/ruoyi-generator/src/main/resources/generator.yml b/ruoyi-generator/src/main/resources/generator.yml new file mode 100644 index 0000000..69a13cf --- /dev/null +++ b/ruoyi-generator/src/main/resources/generator.yml @@ -0,0 +1,10 @@ +# 代码生成 +gen: + # 作者 + author: ruoyi + # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool + packageName: com.ruoyi.business + # 自动去除表前缀,默认是false + autoRemovePre: false + # 表前缀(生成类名不会包含表前缀,多个用逗号分隔) + tablePrefix: sys_ \ No newline at end of file diff --git a/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml b/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml new file mode 100644 index 0000000..11b2b96 --- /dev/null +++ b/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select column_id, table_id, column_name, column_comment, column_type, java_type, java_field, is_pk, is_increment, is_required, is_insert, is_edit, is_list, is_query, query_type, html_type, dict_type, sort, create_by, create_time, update_by, update_time from gen_table_column + + + + + + + + insert into gen_table_column ( + table_id, + column_name, + column_comment, + column_type, + java_type, + java_field, + is_pk, + is_increment, + is_required, + is_insert, + is_edit, + is_list, + is_query, + query_type, + html_type, + dict_type, + sort, + create_by, + create_time + )values( + #{tableId}, + #{columnName}, + #{columnComment}, + #{columnType}, + #{javaType}, + #{javaField}, + #{isPk}, + #{isIncrement}, + #{isRequired}, + #{isInsert}, + #{isEdit}, + #{isList}, + #{isQuery}, + #{queryType}, + #{htmlType}, + #{dictType}, + #{sort}, + #{createBy}, + sysdate() + ) + + + + update gen_table_column + + column_comment = #{columnComment}, + java_type = #{javaType}, + java_field = #{javaField}, + is_insert = #{isInsert}, + is_edit = #{isEdit}, + is_list = #{isList}, + is_query = #{isQuery}, + is_required = #{isRequired}, + query_type = #{queryType}, + html_type = #{htmlType}, + dict_type = #{dictType}, + sort = #{sort}, + update_by = #{updateBy}, + update_time = sysdate() + + where column_id = #{columnId} + + + + delete from gen_table_column where table_id in + + #{tableId} + + + + + delete from gen_table_column where column_id in + + #{item.columnId} + + + + \ No newline at end of file diff --git a/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml b/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml new file mode 100644 index 0000000..b605e90 --- /dev/null +++ b/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml @@ -0,0 +1,202 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select table_id, table_name, table_comment, sub_table_name, sub_table_fk_name, class_name, tpl_category, package_name, module_name, business_name, function_name, function_author, gen_type, gen_path, options, create_by, create_time, update_by, update_time, remark from gen_table + + + + + + + + + + + + + + + + + + insert into gen_table ( + table_name, + table_comment, + class_name, + tpl_category, + package_name, + module_name, + business_name, + function_name, + function_author, + gen_type, + gen_path, + remark, + create_by, + create_time + )values( + #{tableName}, + #{tableComment}, + #{className}, + #{tplCategory}, + #{packageName}, + #{moduleName}, + #{businessName}, + #{functionName}, + #{functionAuthor}, + #{genType}, + #{genPath}, + #{remark}, + #{createBy}, + sysdate() + ) + + + + update gen_table + + table_name = #{tableName}, + table_comment = #{tableComment}, + sub_table_name = #{subTableName}, + sub_table_fk_name = #{subTableFkName}, + class_name = #{className}, + function_author = #{functionAuthor}, + gen_type = #{genType}, + gen_path = #{genPath}, + tpl_category = #{tplCategory}, + package_name = #{packageName}, + module_name = #{moduleName}, + business_name = #{businessName}, + function_name = #{functionName}, + options = #{options}, + update_by = #{updateBy}, + remark = #{remark}, + update_time = sysdate() + + where table_id = #{tableId} + + + + delete from gen_table where table_id in + + #{tableId} + + + + \ No newline at end of file diff --git a/ruoyi-generator/src/main/resources/vm/java/controller.java.vm b/ruoyi-generator/src/main/resources/vm/java/controller.java.vm new file mode 100644 index 0000000..88e6c2d --- /dev/null +++ b/ruoyi-generator/src/main/resources/vm/java/controller.java.vm @@ -0,0 +1,116 @@ +package ${packageName}.controller; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import ${packageName}.domain.${ClassName}; +import ${packageName}.service.I${ClassName}Service; +import com.ruoyi.common.utils.poi.ExcelUtil; +import java.util.Arrays; +#if($table.crud || $table.sub) +import com.ruoyi.common.core.page.TableDataInfo; +#elseif($table.tree) +#end + +/** + * ${functionName}Controller + * + * @author ${author} + * @date ${datetime} + */ +@RestController +@RequestMapping("/${moduleName}/${businessName}") +public class ${ClassName}Controller extends BaseController +{ + @Autowired + private I${ClassName}Service ${className}Service; + + /** + * 查询${functionName}列表 + */ + @PreAuthorize("@ss.hasPermi('${permissionPrefix}:list')") + @GetMapping("/list") +#if($table.crud || $table.sub) + public TableDataInfo list(${ClassName} ${className}) + { + startPage(); + List<${ClassName}> list = ${className}Service.list(); + return getDataTable(list); + } +#elseif($table.tree) + public AjaxResult list(${ClassName} ${className}) + { + List<${ClassName}> list = ${className}Service.list(); + return success(list); + } +#end + + /** + * 导出${functionName}列表 + */ + @PreAuthorize("@ss.hasPermi('${permissionPrefix}:export')") + @Log(title = "${functionName}", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HttpServletResponse response, ${ClassName} ${className}) + { + List<${ClassName}> list = ${className}Service.list(); + ExcelUtil<${ClassName}> util = new ExcelUtil<${ClassName}>(${ClassName}.class); + util.exportExcel(response, list, "${functionName}数据"); + } + + /** + * 获取${functionName}详细信息 + */ + @PreAuthorize("@ss.hasPermi('${permissionPrefix}:query')") + @GetMapping(value = "/{${pkColumn.javaField}}") + public AjaxResult getInfo(@PathVariable("${pkColumn.javaField}") ${pkColumn.javaType} ${pkColumn.javaField}) + { + return success(${className}Service.getById(${pkColumn.javaField})); + } + + /** + * 新增${functionName} + */ + @PreAuthorize("@ss.hasPermi('${permissionPrefix}:add')") + @Log(title = "${functionName}", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody ${ClassName} ${className}) + { + return toAjax(${className}Service.save(${className})); + } + + /** + * 修改${functionName} + */ + @PreAuthorize("@ss.hasPermi('${permissionPrefix}:edit')") + @Log(title = "${functionName}", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody ${ClassName} ${className}) + { + return toAjax(${className}Service.updateById(${className})); + } + + /** + * 删除${functionName} + */ + @PreAuthorize("@ss.hasPermi('${permissionPrefix}:remove')") + @Log(title = "${functionName}", businessType = BusinessType.DELETE) + @DeleteMapping("/{${pkColumn.javaField}s}") + public AjaxResult remove(@PathVariable ${pkColumn.javaType}[] ${pkColumn.javaField}s) + { + return toAjax(${className}Service.removeByIds(Arrays.asList(${pkColumn.javaField}s))); + } +} diff --git a/ruoyi-generator/src/main/resources/vm/java/domain.java.vm b/ruoyi-generator/src/main/resources/vm/java/domain.java.vm new file mode 100644 index 0000000..e7fb12e --- /dev/null +++ b/ruoyi-generator/src/main/resources/vm/java/domain.java.vm @@ -0,0 +1,109 @@ +package ${packageName}.domain; + +#foreach ($import in $importList) +import ${import}; +#end +import lombok.Data; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import java.util.ArrayList; +#if($table.crud || $table.sub) +import com.ruoyi.common.core.domain.BaseEntity; +#elseif($table.tree) +import com.ruoyi.common.core.domain.TreeEntity; +#end + +/** + * ${functionName}对象 ${tableName} + * + * @author ${author} + * @date ${datetime} + */ +#if($table.crud || $table.sub) +#set($Entity="BaseEntity") +#elseif($table.tree) +#set($Entity="TreeEntity") +#end +@Data +public class ${ClassName} extends ${Entity} +{ + private static final long serialVersionUID = 1L; + +#foreach ($column in $columns) + +#if(!$table.isSuperColumn($column.javaField)) + /** $column.columnComment */ +#if($column.list) +#set($parentheseIndex=$column.columnComment.indexOf("(")) +#if($parentheseIndex != -1) +#set($comment=$column.columnComment.substring(0, $parentheseIndex)) +#else +#set($comment=$column.columnComment) +#end +#if($parentheseIndex != -1) + @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()") +#elseif($column.javaType == 'Date') + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "${comment}", width = 30, dateFormat = "yyyy-MM-dd") +#else + @Excel(name = "${comment}") +#end +#end + private $column.javaType $column.javaField; + +#end +#end +#if($table.sub) + /** $table.subTable.functionName信息 */ + private List<${subClassName}> ${subclassName}List = new ArrayList<${subClassName}>(); + +#end +###foreach ($column in $columns) +###if(!$table.isSuperColumn($column.javaField)) +###if($column.javaField.length() > 2 && $column.javaField.substring(1,2).matches("[A-Z]")) +###set($AttrName=$column.javaField) +###else +###set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) +###end +## public void set${AttrName}($column.javaType $column.javaField) +## { +## this.$column.javaField = $column.javaField; +## } +## +## public $column.javaType get${AttrName}() +## { +## return $column.javaField; +## } +###end +###end + +###if($table.sub) +## public List<${subClassName}> get${subClassName}List() +## { +## return ${subclassName}List; +## } +## +## public void set${subClassName}List(List<${subClassName}> ${subclassName}List) +## { +## this.${subclassName}List = ${subclassName}List; +## } +## +###end +## @Override +## public String toString() { +## return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) +###foreach ($column in $columns) +###if($column.javaField.length() > 2 && $column.javaField.substring(1,2).matches("[A-Z]")) +###set($AttrName=$column.javaField) +###else +###set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) +###end +## .append("${column.javaField}", get${AttrName}()) +###end +###if($table.sub) +## .append("${subclassName}List", get${subClassName}List()) +###end +## .toString(); +## } +} diff --git a/ruoyi-generator/src/main/resources/vm/java/mapper.java.vm b/ruoyi-generator/src/main/resources/vm/java/mapper.java.vm new file mode 100644 index 0000000..adb7c90 --- /dev/null +++ b/ruoyi-generator/src/main/resources/vm/java/mapper.java.vm @@ -0,0 +1,19 @@ +package ${packageName}.mapper; + +import java.util.List; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import ${packageName}.domain.${ClassName}; +#if($table.sub) +import ${packageName}.domain.${subClassName}; +#end + +/** + * ${functionName}Mapper接口 + * + * @author ${author} + * @date ${datetime} + */ +public interface ${ClassName}Mapper extends BaseMapper<${ClassName}> +{ + +} diff --git a/ruoyi-generator/src/main/resources/vm/java/service.java.vm b/ruoyi-generator/src/main/resources/vm/java/service.java.vm new file mode 100644 index 0000000..b8af884 --- /dev/null +++ b/ruoyi-generator/src/main/resources/vm/java/service.java.vm @@ -0,0 +1,15 @@ +package ${packageName}.service; + +import java.util.List; +import ${packageName}.domain.${ClassName}; +import com.baomidou.mybatisplus.extension.service.IService; +/** + * ${functionName}Service接口 + * + * @author ${author} + * @date ${datetime} + */ +public interface I${ClassName}Service extends IService<${ClassName}> +{ + +} diff --git a/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm b/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm new file mode 100644 index 0000000..87051f3 --- /dev/null +++ b/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm @@ -0,0 +1,35 @@ +package ${packageName}.service.impl; + +import java.util.List; +#foreach ($column in $columns) +#if($column.javaField == 'createTime' || $column.javaField == 'updateTime') +import com.ruoyi.common.utils.DateUtils; +#break +#end +#end +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +#if($table.sub) +import java.util.ArrayList; +import com.ruoyi.common.utils.StringUtils; +import org.springframework.transaction.annotation.Transactional; +import ${packageName}.domain.${subClassName}; +#end +import ${packageName}.mapper.${ClassName}Mapper; +import ${packageName}.domain.${ClassName}; +import ${packageName}.service.I${ClassName}Service; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; + +/** + * ${functionName}Service业务层处理 + * + * @author ${author} + * @date ${datetime} + */ +@Service +public class ${ClassName}ServiceImpl extends ServiceImpl<${ClassName}Mapper, ${ClassName}> implements I${ClassName}Service +{ + +} diff --git a/ruoyi-generator/src/main/resources/vm/java/sub-domain.java.vm b/ruoyi-generator/src/main/resources/vm/java/sub-domain.java.vm new file mode 100644 index 0000000..a3f53eb --- /dev/null +++ b/ruoyi-generator/src/main/resources/vm/java/sub-domain.java.vm @@ -0,0 +1,76 @@ +package ${packageName}.domain; + +#foreach ($import in $subImportList) +import ${import}; +#end +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * ${subTable.functionName}对象 ${subTableName} + * + * @author ${author} + * @date ${datetime} + */ +public class ${subClassName} extends BaseEntity +{ + private static final long serialVersionUID = 1L; + +#foreach ($column in $subTable.columns) +#if(!$table.isSuperColumn($column.javaField)) + /** $column.columnComment */ +#if($column.list) +#set($parentheseIndex=$column.columnComment.indexOf("(")) +#if($parentheseIndex != -1) +#set($comment=$column.columnComment.substring(0, $parentheseIndex)) +#else +#set($comment=$column.columnComment) +#end +#if($parentheseIndex != -1) + @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()") +#elseif($column.javaType == 'Date') + @JsonFormat(pattern = "yyyy-MM-dd") + @Excel(name = "${comment}", width = 30, dateFormat = "yyyy-MM-dd") +#else + @Excel(name = "${comment}") +#end +#end + private $column.javaType $column.javaField; + +#end +#end +#foreach ($column in $subTable.columns) +#if(!$table.isSuperColumn($column.javaField)) +#if($column.javaField.length() > 2 && $column.javaField.substring(1,2).matches("[A-Z]")) +#set($AttrName=$column.javaField) +#else +#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) +#end + public void set${AttrName}($column.javaType $column.javaField) + { + this.$column.javaField = $column.javaField; + } + + public $column.javaType get${AttrName}() + { + return $column.javaField; + } +#end +#end + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) +#foreach ($column in $subTable.columns) +#if($column.javaField.length() > 2 && $column.javaField.substring(1,2).matches("[A-Z]")) +#set($AttrName=$column.javaField) +#else +#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) +#end + .append("${column.javaField}", get${AttrName}()) +#end + .toString(); + } +} diff --git a/ruoyi-generator/src/main/resources/vm/js/api.js.vm b/ruoyi-generator/src/main/resources/vm/js/api.js.vm new file mode 100644 index 0000000..9295524 --- /dev/null +++ b/ruoyi-generator/src/main/resources/vm/js/api.js.vm @@ -0,0 +1,44 @@ +import request from '@/utils/request' + +// 查询${functionName}列表 +export function list${BusinessName}(query) { + return request({ + url: '/${moduleName}/${businessName}/list', + method: 'get', + params: query + }) +} + +// 查询${functionName}详细 +export function get${BusinessName}(${pkColumn.javaField}) { + return request({ + url: '/${moduleName}/${businessName}/' + ${pkColumn.javaField}, + method: 'get' + }) +} + +// 新增${functionName} +export function add${BusinessName}(data) { + return request({ + url: '/${moduleName}/${businessName}', + method: 'post', + data: data + }) +} + +// 修改${functionName} +export function update${BusinessName}(data) { + return request({ + url: '/${moduleName}/${businessName}', + method: 'put', + data: data + }) +} + +// 删除${functionName} +export function del${BusinessName}(${pkColumn.javaField}) { + return request({ + url: '/${moduleName}/${businessName}/' + ${pkColumn.javaField}, + method: 'delete' + }) +} diff --git a/ruoyi-generator/src/main/resources/vm/sql/sql.vm b/ruoyi-generator/src/main/resources/vm/sql/sql.vm new file mode 100644 index 0000000..0575583 --- /dev/null +++ b/ruoyi-generator/src/main/resources/vm/sql/sql.vm @@ -0,0 +1,22 @@ +-- 菜单 SQL +insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) +values('${functionName}', '${parentMenuId}', '1', '${businessName}', '${moduleName}/${businessName}/index', 1, 0, 'C', '0', '0', '${permissionPrefix}:list', '#', 'admin', sysdate(), '', null, '${functionName}菜单'); + +-- 按钮父菜单ID +SELECT @parentId := LAST_INSERT_ID(); + +-- 按钮 SQL +insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) +values('${functionName}查询', @parentId, '1', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:query', '#', 'admin', sysdate(), '', null, ''); + +insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) +values('${functionName}新增', @parentId, '2', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:add', '#', 'admin', sysdate(), '', null, ''); + +insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) +values('${functionName}修改', @parentId, '3', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:edit', '#', 'admin', sysdate(), '', null, ''); + +insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) +values('${functionName}删除', @parentId, '4', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:remove', '#', 'admin', sysdate(), '', null, ''); + +insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark) +values('${functionName}导出', @parentId, '5', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:export', '#', 'admin', sysdate(), '', null, ''); \ No newline at end of file diff --git a/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm new file mode 100644 index 0000000..a4c64a0 --- /dev/null +++ b/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm @@ -0,0 +1,505 @@ + + + diff --git a/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm new file mode 100644 index 0000000..196233c --- /dev/null +++ b/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm @@ -0,0 +1,607 @@ + + + diff --git a/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm new file mode 100644 index 0000000..7bbd2fc --- /dev/null +++ b/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm @@ -0,0 +1,474 @@ + + + diff --git a/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm new file mode 100644 index 0000000..9cb4176 --- /dev/null +++ b/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm @@ -0,0 +1,595 @@ + + + diff --git a/ruoyi-generator/src/main/resources/vm/vue/v3/readme.txt b/ruoyi-generator/src/main/resources/vm/vue/v3/readme.txt new file mode 100644 index 0000000..99239bb --- /dev/null +++ b/ruoyi-generator/src/main/resources/vm/vue/v3/readme.txt @@ -0,0 +1 @@ +ʹõRuoYi-Vue3ǰˣôҪһ´Ŀ¼ģindex.vue.vmindex-tree.vue.vmļϼvueĿ¼ \ No newline at end of file diff --git a/ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm b/ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm new file mode 100644 index 0000000..0ceb3d8 --- /dev/null +++ b/ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm @@ -0,0 +1,135 @@ + + + + + +#foreach ($column in $columns) + +#end + +#if($table.sub) + + + + + + +#foreach ($column in $subTable.columns) + +#end + +#end + + + select#foreach($column in $columns) $column.columnName#if($foreach.count != $columns.size()),#end#end from ${tableName} + + + + + + + + insert into ${tableName} + +#foreach($column in $columns) +#if($column.columnName != $pkColumn.columnName || !$pkColumn.increment) + $column.columnName, +#end +#end + + +#foreach($column in $columns) +#if($column.columnName != $pkColumn.columnName || !$pkColumn.increment) + #{$column.javaField}, +#end +#end + + + + + update ${tableName} + +#foreach($column in $columns) +#if($column.columnName != $pkColumn.columnName) + $column.columnName = #{$column.javaField}, +#end +#end + + where ${pkColumn.columnName} = #{${pkColumn.javaField}} + + + + delete from ${tableName} where ${pkColumn.columnName} = #{${pkColumn.javaField}} + + + + delete from ${tableName} where ${pkColumn.columnName} in + + #{${pkColumn.javaField}} + + +#if($table.sub) + + + delete from ${subTableName} where ${subTableFkName} in + + #{${subTableFkclassName}} + + + + + delete from ${subTableName} where ${subTableFkName} = #{${subTableFkclassName}} + + + + insert into ${subTableName}(#foreach($column in $subTable.columns) $column.columnName#if($foreach.count != $subTable.columns.size()),#end#end) values + + (#foreach($column in $subTable.columns) #{item.$column.javaField}#if($foreach.count != $subTable.columns.size()),#end#end) + + +#end + \ No newline at end of file diff --git a/ruoyi-quartz/pom.xml b/ruoyi-quartz/pom.xml new file mode 100644 index 0000000..1922bcf --- /dev/null +++ b/ruoyi-quartz/pom.xml @@ -0,0 +1,40 @@ + + + + ruoyi + com.ruoyi + 3.8.5 + + 4.0.0 + + ruoyi-quartz + + + quartz定时任务 + + + + + + + org.quartz-scheduler + quartz + + + com.mchange + c3p0 + + + + + + + com.ruoyi + ruoyi-common + + + + + \ No newline at end of file diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/config/ScheduleConfig.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/config/ScheduleConfig.java new file mode 100644 index 0000000..621001a --- /dev/null +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/config/ScheduleConfig.java @@ -0,0 +1,57 @@ +//package com.ruoyi.quartz.config; +// +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +//import org.springframework.scheduling.quartz.SchedulerFactoryBean; +//import javax.sql.DataSource; +//import java.util.Properties; +// +///** +// * 定时任务配置(单机部署建议删除此类和qrtz数据库表,默认走内存会最高效) +// * +// * @author #author# +// */ +//@Configuration +//public class ScheduleConfig +//{ +// @Bean +// public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) +// { +// SchedulerFactoryBean factory = new SchedulerFactoryBean(); +// factory.setDataSource(dataSource); +// +// // quartz参数 +// Properties prop = new Properties(); +// prop.put("org.quartz.scheduler.instanceName", "RuoyiScheduler"); +// prop.put("org.quartz.scheduler.instanceId", "AUTO"); +// // 线程池配置 +// prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool"); +// prop.put("org.quartz.threadPool.threadCount", "20"); +// prop.put("org.quartz.threadPool.threadPriority", "5"); +// // JobStore配置 +// prop.put("org.quartz.jobStore.class", "org.springframework.scheduling.quartz.LocalDataSourceJobStore"); +// // 集群配置 +// prop.put("org.quartz.jobStore.isClustered", "true"); +// prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000"); +// prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1"); +// prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true"); +// +// // sqlserver 启用 +// // prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?"); +// prop.put("org.quartz.jobStore.misfireThreshold", "12000"); +// prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_"); +// factory.setQuartzProperties(prop); +// +// factory.setSchedulerName("RuoyiScheduler"); +// // 延时启动 +// factory.setStartupDelay(1); +// factory.setApplicationContextSchedulerContextKey("applicationContextKey"); +// // 可选,QuartzScheduler +// // 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了 +// factory.setOverwriteExistingJobs(true); +// // 设置自动启动,默认为true +// factory.setAutoStartup(true); +// +// return factory; +// } +//} diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java new file mode 100644 index 0000000..a1b212f --- /dev/null +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java @@ -0,0 +1,185 @@ +package com.ruoyi.quartz.controller; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.quartz.SchedulerException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.exception.job.TaskException; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.quartz.domain.SysJob; +import com.ruoyi.quartz.service.ISysJobService; +import com.ruoyi.quartz.util.CronUtils; +import com.ruoyi.quartz.util.ScheduleUtils; + +/** + * 调度任务信息操作处理 + * + * @author #author# + */ +@RestController +@RequestMapping("/monitor/job") +public class SysJobController extends BaseController +{ + @Autowired + private ISysJobService jobService; + + /** + * 查询定时任务列表 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:list')") + @GetMapping("/list") + public TableDataInfo list(SysJob sysJob) + { + startPage(); + List list = jobService.selectJobList(sysJob); + return getDataTable(list); + } + + /** + * 导出定时任务列表 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:export')") + @Log(title = "定时任务", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HttpServletResponse response, SysJob sysJob) + { + List list = jobService.selectJobList(sysJob); + ExcelUtil util = new ExcelUtil(SysJob.class); + util.exportExcel(response, list, "定时任务"); + } + + /** + * 获取定时任务详细信息 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:query')") + @GetMapping(value = "/{jobId}") + public AjaxResult getInfo(@PathVariable("jobId") Long jobId) + { + return success(jobService.selectJobById(jobId)); + } + + /** + * 新增定时任务 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:add')") + @Log(title = "定时任务", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SysJob job) throws SchedulerException, TaskException + { + if (!CronUtils.isValid(job.getCronExpression())) + { + return error("新增任务'" + job.getJobName() + "'失败,Cron表达式不正确"); + } + else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI)) + { + return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'rmi'调用"); + } + else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS })) + { + return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'ldap(s)'调用"); + } + else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS })) + { + return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)'调用"); + } + else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR)) + { + return error("新增任务'" + job.getJobName() + "'失败,目标字符串存在违规"); + } + else if (!ScheduleUtils.whiteList(job.getInvokeTarget())) + { + return error("新增任务'" + job.getJobName() + "'失败,目标字符串不在白名单内"); + } + job.setCreateBy(getUsername()); + return toAjax(jobService.insertJob(job)); + } + + /** + * 修改定时任务 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:edit')") + @Log(title = "定时任务", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SysJob job) throws SchedulerException, TaskException + { + if (!CronUtils.isValid(job.getCronExpression())) + { + return error("修改任务'" + job.getJobName() + "'失败,Cron表达式不正确"); + } + else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI)) + { + return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'rmi'调用"); + } + else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS })) + { + return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'ldap(s)'调用"); + } + else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS })) + { + return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)'调用"); + } + else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR)) + { + return error("修改任务'" + job.getJobName() + "'失败,目标字符串存在违规"); + } + else if (!ScheduleUtils.whiteList(job.getInvokeTarget())) + { + return error("修改任务'" + job.getJobName() + "'失败,目标字符串不在白名单内"); + } + job.setUpdateBy(getUsername()); + return toAjax(jobService.updateJob(job)); + } + + /** + * 定时任务状态修改 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:changeStatus')") + @Log(title = "定时任务", businessType = BusinessType.UPDATE) + @PutMapping("/changeStatus") + public AjaxResult changeStatus(@RequestBody SysJob job) throws SchedulerException + { + SysJob newJob = jobService.selectJobById(job.getJobId()); + newJob.setStatus(job.getStatus()); + return toAjax(jobService.changeStatus(newJob)); + } + + /** + * 定时任务立即执行一次 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:changeStatus')") + @Log(title = "定时任务", businessType = BusinessType.UPDATE) + @PutMapping("/run") + public AjaxResult run(@RequestBody SysJob job) throws SchedulerException + { + boolean result = jobService.run(job); + return result ? success() : error("任务不存在或已过期!"); + } + + /** + * 删除定时任务 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:remove')") + @Log(title = "定时任务", businessType = BusinessType.DELETE) + @DeleteMapping("/{jobIds}") + public AjaxResult remove(@PathVariable Long[] jobIds) throws SchedulerException, TaskException + { + jobService.deleteJobByIds(jobIds); + return success(); + } +} diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobLogController.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobLogController.java new file mode 100644 index 0000000..9cfb7e4 --- /dev/null +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobLogController.java @@ -0,0 +1,92 @@ +package com.ruoyi.quartz.controller; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.quartz.domain.SysJobLog; +import com.ruoyi.quartz.service.ISysJobLogService; + +/** + * 调度日志操作处理 + * + * @author #author# + */ +@RestController +@RequestMapping("/monitor/jobLog") +public class SysJobLogController extends BaseController +{ + @Autowired + private ISysJobLogService jobLogService; + + /** + * 查询定时任务调度日志列表 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:list')") + @GetMapping("/list") + public TableDataInfo list(SysJobLog sysJobLog) + { + startPage(); + List list = jobLogService.selectJobLogList(sysJobLog); + return getDataTable(list); + } + + /** + * 导出定时任务调度日志列表 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:export')") + @Log(title = "任务调度日志", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HttpServletResponse response, SysJobLog sysJobLog) + { + List list = jobLogService.selectJobLogList(sysJobLog); + ExcelUtil util = new ExcelUtil(SysJobLog.class); + util.exportExcel(response, list, "调度日志"); + } + + /** + * 根据调度编号获取详细信息 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:query')") + @GetMapping(value = "/{jobLogId}") + public AjaxResult getInfo(@PathVariable Long jobLogId) + { + return success(jobLogService.selectJobLogById(jobLogId)); + } + + + /** + * 删除定时任务调度日志 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:remove')") + @Log(title = "定时任务调度日志", businessType = BusinessType.DELETE) + @DeleteMapping("/{jobLogIds}") + public AjaxResult remove(@PathVariable Long[] jobLogIds) + { + return toAjax(jobLogService.deleteJobLogByIds(jobLogIds)); + } + + /** + * 清空定时任务调度日志 + */ + @PreAuthorize("@ss.hasPermi('monitor:job:remove')") + @Log(title = "调度日志", businessType = BusinessType.CLEAN) + @DeleteMapping("/clean") + public AjaxResult clean() + { + jobLogService.cleanJobLog(); + return success(); + } +} diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJob.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJob.java new file mode 100644 index 0000000..e793925 --- /dev/null +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJob.java @@ -0,0 +1,171 @@ +package com.ruoyi.quartz.domain; + +import java.util.Date; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; +import com.ruoyi.common.constant.ScheduleConstants; +import com.ruoyi.common.core.domain.BaseEntity; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.quartz.util.CronUtils; + +/** + * 定时任务调度表 sys_job + * + * @author #author# + */ +public class SysJob extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 任务ID */ + @Excel(name = "任务序号", cellType = ColumnType.NUMERIC) + private Long jobId; + + /** 任务名称 */ + @Excel(name = "任务名称") + private String jobName; + + /** 任务组名 */ + @Excel(name = "任务组名") + private String jobGroup; + + /** 调用目标字符串 */ + @Excel(name = "调用目标字符串") + private String invokeTarget; + + /** cron执行表达式 */ + @Excel(name = "执行表达式 ") + private String cronExpression; + + /** cron计划策略 */ + @Excel(name = "计划策略 ", readConverterExp = "0=默认,1=立即触发执行,2=触发一次执行,3=不触发立即执行") + private String misfirePolicy = ScheduleConstants.MISFIRE_DEFAULT; + + /** 是否并发执行(0允许 1禁止) */ + @Excel(name = "并发执行", readConverterExp = "0=允许,1=禁止") + private String concurrent; + + /** 任务状态(0正常 1暂停) */ + @Excel(name = "任务状态", readConverterExp = "0=正常,1=暂停") + private String status; + + public Long getJobId() + { + return jobId; + } + + public void setJobId(Long jobId) + { + this.jobId = jobId; + } + + @NotBlank(message = "任务名称不能为空") + @Size(min = 0, max = 64, message = "任务名称不能超过64个字符") + public String getJobName() + { + return jobName; + } + + public void setJobName(String jobName) + { + this.jobName = jobName; + } + + public String getJobGroup() + { + return jobGroup; + } + + public void setJobGroup(String jobGroup) + { + this.jobGroup = jobGroup; + } + + @NotBlank(message = "调用目标字符串不能为空") + @Size(min = 0, max = 500, message = "调用目标字符串长度不能超过500个字符") + public String getInvokeTarget() + { + return invokeTarget; + } + + public void setInvokeTarget(String invokeTarget) + { + this.invokeTarget = invokeTarget; + } + + @NotBlank(message = "Cron执行表达式不能为空") + @Size(min = 0, max = 255, message = "Cron执行表达式不能超过255个字符") + public String getCronExpression() + { + return cronExpression; + } + + public void setCronExpression(String cronExpression) + { + this.cronExpression = cronExpression; + } + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + public Date getNextValidTime() + { + if (StringUtils.isNotEmpty(cronExpression)) + { + return CronUtils.getNextExecution(cronExpression); + } + return null; + } + + public String getMisfirePolicy() + { + return misfirePolicy; + } + + public void setMisfirePolicy(String misfirePolicy) + { + this.misfirePolicy = misfirePolicy; + } + + public String getConcurrent() + { + return concurrent; + } + + public void setConcurrent(String concurrent) + { + this.concurrent = concurrent; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("jobId", getJobId()) + .append("jobName", getJobName()) + .append("jobGroup", getJobGroup()) + .append("cronExpression", getCronExpression()) + .append("nextValidTime", getNextValidTime()) + .append("misfirePolicy", getMisfirePolicy()) + .append("concurrent", getConcurrent()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJobLog.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJobLog.java new file mode 100644 index 0000000..d7338d3 --- /dev/null +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJobLog.java @@ -0,0 +1,155 @@ +package com.ruoyi.quartz.domain; + +import java.util.Date; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 定时任务调度日志表 sys_job_log + * + * @author #author# + */ +public class SysJobLog extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** ID */ + @Excel(name = "日志序号") + private Long jobLogId; + + /** 任务名称 */ + @Excel(name = "任务名称") + private String jobName; + + /** 任务组名 */ + @Excel(name = "任务组名") + private String jobGroup; + + /** 调用目标字符串 */ + @Excel(name = "调用目标字符串") + private String invokeTarget; + + /** 日志信息 */ + @Excel(name = "日志信息") + private String jobMessage; + + /** 执行状态(0正常 1失败) */ + @Excel(name = "执行状态", readConverterExp = "0=正常,1=失败") + private String status; + + /** 异常信息 */ + @Excel(name = "异常信息") + private String exceptionInfo; + + /** 开始时间 */ + private Date startTime; + + /** 停止时间 */ + private Date stopTime; + + public Long getJobLogId() + { + return jobLogId; + } + + public void setJobLogId(Long jobLogId) + { + this.jobLogId = jobLogId; + } + + public String getJobName() + { + return jobName; + } + + public void setJobName(String jobName) + { + this.jobName = jobName; + } + + public String getJobGroup() + { + return jobGroup; + } + + public void setJobGroup(String jobGroup) + { + this.jobGroup = jobGroup; + } + + public String getInvokeTarget() + { + return invokeTarget; + } + + public void setInvokeTarget(String invokeTarget) + { + this.invokeTarget = invokeTarget; + } + + public String getJobMessage() + { + return jobMessage; + } + + public void setJobMessage(String jobMessage) + { + this.jobMessage = jobMessage; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + public String getExceptionInfo() + { + return exceptionInfo; + } + + public void setExceptionInfo(String exceptionInfo) + { + this.exceptionInfo = exceptionInfo; + } + + public Date getStartTime() + { + return startTime; + } + + public void setStartTime(Date startTime) + { + this.startTime = startTime; + } + + public Date getStopTime() + { + return stopTime; + } + + public void setStopTime(Date stopTime) + { + this.stopTime = stopTime; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("jobLogId", getJobLogId()) + .append("jobName", getJobName()) + .append("jobGroup", getJobGroup()) + .append("jobMessage", getJobMessage()) + .append("status", getStatus()) + .append("exceptionInfo", getExceptionInfo()) + .append("startTime", getStartTime()) + .append("stopTime", getStopTime()) + .toString(); + } +} diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobLogMapper.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobLogMapper.java new file mode 100644 index 0000000..91ebc05 --- /dev/null +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobLogMapper.java @@ -0,0 +1,64 @@ +package com.ruoyi.quartz.mapper; + +import java.util.List; +import com.ruoyi.quartz.domain.SysJobLog; + +/** + * 调度任务日志信息 数据层 + * + * @author #author# + */ +public interface SysJobLogMapper +{ + /** + * 获取quartz调度器日志的计划任务 + * + * @param jobLog 调度日志信息 + * @return 调度任务日志集合 + */ + public List selectJobLogList(SysJobLog jobLog); + + /** + * 查询所有调度任务日志 + * + * @return 调度任务日志列表 + */ + public List selectJobLogAll(); + + /** + * 通过调度任务日志ID查询调度信息 + * + * @param jobLogId 调度任务日志ID + * @return 调度任务日志对象信息 + */ + public SysJobLog selectJobLogById(Long jobLogId); + + /** + * 新增任务日志 + * + * @param jobLog 调度日志信息 + * @return 结果 + */ + public int insertJobLog(SysJobLog jobLog); + + /** + * 批量删除调度日志信息 + * + * @param logIds 需要删除的数据ID + * @return 结果 + */ + public int deleteJobLogByIds(Long[] logIds); + + /** + * 删除任务日志 + * + * @param jobId 调度日志ID + * @return 结果 + */ + public int deleteJobLogById(Long jobId); + + /** + * 清空任务日志 + */ + public void cleanJobLog(); +} diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobMapper.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobMapper.java new file mode 100644 index 0000000..eac833b --- /dev/null +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobMapper.java @@ -0,0 +1,67 @@ +package com.ruoyi.quartz.mapper; + +import java.util.List; +import com.ruoyi.quartz.domain.SysJob; + +/** + * 调度任务信息 数据层 + * + * @author #author# + */ +public interface SysJobMapper +{ + /** + * 查询调度任务日志集合 + * + * @param job 调度信息 + * @return 操作日志集合 + */ + public List selectJobList(SysJob job); + + /** + * 查询所有调度任务 + * + * @return 调度任务列表 + */ + public List selectJobAll(); + + /** + * 通过调度ID查询调度任务信息 + * + * @param jobId 调度ID + * @return 角色对象信息 + */ + public SysJob selectJobById(Long jobId); + + /** + * 通过调度ID删除调度任务信息 + * + * @param jobId 调度ID + * @return 结果 + */ + public int deleteJobById(Long jobId); + + /** + * 批量删除调度任务信息 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteJobByIds(Long[] ids); + + /** + * 修改调度任务信息 + * + * @param job 调度任务信息 + * @return 结果 + */ + public int updateJob(SysJob job); + + /** + * 新增调度任务信息 + * + * @param job 调度任务信息 + * @return 结果 + */ + public int insertJob(SysJob job); +} diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobLogService.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobLogService.java new file mode 100644 index 0000000..54a914c --- /dev/null +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobLogService.java @@ -0,0 +1,56 @@ +package com.ruoyi.quartz.service; + +import java.util.List; +import com.ruoyi.quartz.domain.SysJobLog; + +/** + * 定时任务调度日志信息信息 服务层 + * + * @author #author# + */ +public interface ISysJobLogService +{ + /** + * 获取quartz调度器日志的计划任务 + * + * @param jobLog 调度日志信息 + * @return 调度任务日志集合 + */ + public List selectJobLogList(SysJobLog jobLog); + + /** + * 通过调度任务日志ID查询调度信息 + * + * @param jobLogId 调度任务日志ID + * @return 调度任务日志对象信息 + */ + public SysJobLog selectJobLogById(Long jobLogId); + + /** + * 新增任务日志 + * + * @param jobLog 调度日志信息 + */ + public void addJobLog(SysJobLog jobLog); + + /** + * 批量删除调度日志信息 + * + * @param logIds 需要删除的日志ID + * @return 结果 + */ + public int deleteJobLogByIds(Long[] logIds); + + /** + * 删除任务日志 + * + * @param jobId 调度日志ID + * @return 结果 + */ + public int deleteJobLogById(Long jobId); + + /** + * 清空任务日志 + */ + public void cleanJobLog(); +} diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobService.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobService.java new file mode 100644 index 0000000..737ec98 --- /dev/null +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobService.java @@ -0,0 +1,102 @@ +package com.ruoyi.quartz.service; + +import java.util.List; +import org.quartz.SchedulerException; +import com.ruoyi.common.exception.job.TaskException; +import com.ruoyi.quartz.domain.SysJob; + +/** + * 定时任务调度信息信息 服务层 + * + * @author #author# + */ +public interface ISysJobService +{ + /** + * 获取quartz调度器的计划任务 + * + * @param job 调度信息 + * @return 调度任务集合 + */ + public List selectJobList(SysJob job); + + /** + * 通过调度任务ID查询调度信息 + * + * @param jobId 调度任务ID + * @return 调度任务对象信息 + */ + public SysJob selectJobById(Long jobId); + + /** + * 暂停任务 + * + * @param job 调度信息 + * @return 结果 + */ + public int pauseJob(SysJob job) throws SchedulerException; + + /** + * 恢复任务 + * + * @param job 调度信息 + * @return 结果 + */ + public int resumeJob(SysJob job) throws SchedulerException; + + /** + * 删除任务后,所对应的trigger也将被删除 + * + * @param job 调度信息 + * @return 结果 + */ + public int deleteJob(SysJob job) throws SchedulerException; + + /** + * 批量删除调度信息 + * + * @param jobIds 需要删除的任务ID + * @return 结果 + */ + public void deleteJobByIds(Long[] jobIds) throws SchedulerException; + + /** + * 任务调度状态修改 + * + * @param job 调度信息 + * @return 结果 + */ + public int changeStatus(SysJob job) throws SchedulerException; + + /** + * 立即运行任务 + * + * @param job 调度信息 + * @return 结果 + */ + public boolean run(SysJob job) throws SchedulerException; + + /** + * 新增任务 + * + * @param job 调度信息 + * @return 结果 + */ + public int insertJob(SysJob job) throws SchedulerException, TaskException; + + /** + * 更新任务 + * + * @param job 调度信息 + * @return 结果 + */ + public int updateJob(SysJob job) throws SchedulerException, TaskException; + + /** + * 校验cron表达式是否有效 + * + * @param cronExpression 表达式 + * @return 结果 + */ + public boolean checkCronExpressionIsValid(String cronExpression); +} diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobLogServiceImpl.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobLogServiceImpl.java new file mode 100644 index 0000000..3572f4d --- /dev/null +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobLogServiceImpl.java @@ -0,0 +1,87 @@ +package com.ruoyi.quartz.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.quartz.domain.SysJobLog; +import com.ruoyi.quartz.mapper.SysJobLogMapper; +import com.ruoyi.quartz.service.ISysJobLogService; + +/** + * 定时任务调度日志信息 服务层 + * + * @author #author# + */ +@Service +public class SysJobLogServiceImpl implements ISysJobLogService +{ + @Autowired + private SysJobLogMapper jobLogMapper; + + /** + * 获取quartz调度器日志的计划任务 + * + * @param jobLog 调度日志信息 + * @return 调度任务日志集合 + */ + @Override + public List selectJobLogList(SysJobLog jobLog) + { + return jobLogMapper.selectJobLogList(jobLog); + } + + /** + * 通过调度任务日志ID查询调度信息 + * + * @param jobLogId 调度任务日志ID + * @return 调度任务日志对象信息 + */ + @Override + public SysJobLog selectJobLogById(Long jobLogId) + { + return jobLogMapper.selectJobLogById(jobLogId); + } + + /** + * 新增任务日志 + * + * @param jobLog 调度日志信息 + */ + @Override + public void addJobLog(SysJobLog jobLog) + { + jobLogMapper.insertJobLog(jobLog); + } + + /** + * 批量删除调度日志信息 + * + * @param logIds 需要删除的数据ID + * @return 结果 + */ + @Override + public int deleteJobLogByIds(Long[] logIds) + { + return jobLogMapper.deleteJobLogByIds(logIds); + } + + /** + * 删除任务日志 + * + * @param jobId 调度日志ID + */ + @Override + public int deleteJobLogById(Long jobId) + { + return jobLogMapper.deleteJobLogById(jobId); + } + + /** + * 清空任务日志 + */ + @Override + public void cleanJobLog() + { + jobLogMapper.cleanJobLog(); + } +} diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobServiceImpl.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobServiceImpl.java new file mode 100644 index 0000000..43571f1 --- /dev/null +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobServiceImpl.java @@ -0,0 +1,261 @@ +package com.ruoyi.quartz.service.impl; + +import java.util.List; +import javax.annotation.PostConstruct; +import org.quartz.JobDataMap; +import org.quartz.JobKey; +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import com.ruoyi.common.constant.ScheduleConstants; +import com.ruoyi.common.exception.job.TaskException; +import com.ruoyi.quartz.domain.SysJob; +import com.ruoyi.quartz.mapper.SysJobMapper; +import com.ruoyi.quartz.service.ISysJobService; +import com.ruoyi.quartz.util.CronUtils; +import com.ruoyi.quartz.util.ScheduleUtils; + +/** + * 定时任务调度信息 服务层 + * + * @author #author# + */ +@Service +public class SysJobServiceImpl implements ISysJobService +{ + @Autowired + private Scheduler scheduler; + + @Autowired + private SysJobMapper jobMapper; + + /** + * 项目启动时,初始化定时器 主要是防止手动修改数据库导致未同步到定时任务处理(注:不能手动修改数据库ID和任务组名,否则会导致脏数据) + */ + @PostConstruct + public void init() throws SchedulerException, TaskException + { + scheduler.clear(); + List jobList = jobMapper.selectJobAll(); + for (SysJob job : jobList) + { + ScheduleUtils.createScheduleJob(scheduler, job); + } + } + + /** + * 获取quartz调度器的计划任务列表 + * + * @param job 调度信息 + * @return + */ + @Override + public List selectJobList(SysJob job) + { + return jobMapper.selectJobList(job); + } + + /** + * 通过调度任务ID查询调度信息 + * + * @param jobId 调度任务ID + * @return 调度任务对象信息 + */ + @Override + public SysJob selectJobById(Long jobId) + { + return jobMapper.selectJobById(jobId); + } + + /** + * 暂停任务 + * + * @param job 调度信息 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int pauseJob(SysJob job) throws SchedulerException + { + Long jobId = job.getJobId(); + String jobGroup = job.getJobGroup(); + job.setStatus(ScheduleConstants.Status.PAUSE.getValue()); + int rows = jobMapper.updateJob(job); + if (rows > 0) + { + scheduler.pauseJob(ScheduleUtils.getJobKey(jobId, jobGroup)); + } + return rows; + } + + /** + * 恢复任务 + * + * @param job 调度信息 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int resumeJob(SysJob job) throws SchedulerException + { + Long jobId = job.getJobId(); + String jobGroup = job.getJobGroup(); + job.setStatus(ScheduleConstants.Status.NORMAL.getValue()); + int rows = jobMapper.updateJob(job); + if (rows > 0) + { + scheduler.resumeJob(ScheduleUtils.getJobKey(jobId, jobGroup)); + } + return rows; + } + + /** + * 删除任务后,所对应的trigger也将被删除 + * + * @param job 调度信息 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int deleteJob(SysJob job) throws SchedulerException + { + Long jobId = job.getJobId(); + String jobGroup = job.getJobGroup(); + int rows = jobMapper.deleteJobById(jobId); + if (rows > 0) + { + scheduler.deleteJob(ScheduleUtils.getJobKey(jobId, jobGroup)); + } + return rows; + } + + /** + * 批量删除调度信息 + * + * @param jobIds 需要删除的任务ID + * @return 结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteJobByIds(Long[] jobIds) throws SchedulerException + { + for (Long jobId : jobIds) + { + SysJob job = jobMapper.selectJobById(jobId); + deleteJob(job); + } + } + + /** + * 任务调度状态修改 + * + * @param job 调度信息 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int changeStatus(SysJob job) throws SchedulerException + { + int rows = 0; + String status = job.getStatus(); + if (ScheduleConstants.Status.NORMAL.getValue().equals(status)) + { + rows = resumeJob(job); + } + else if (ScheduleConstants.Status.PAUSE.getValue().equals(status)) + { + rows = pauseJob(job); + } + return rows; + } + + /** + * 立即运行任务 + * + * @param job 调度信息 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean run(SysJob job) throws SchedulerException + { + boolean result = false; + Long jobId = job.getJobId(); + String jobGroup = job.getJobGroup(); + SysJob properties = selectJobById(job.getJobId()); + // 参数 + JobDataMap dataMap = new JobDataMap(); + dataMap.put(ScheduleConstants.TASK_PROPERTIES, properties); + JobKey jobKey = ScheduleUtils.getJobKey(jobId, jobGroup); + if (scheduler.checkExists(jobKey)) + { + result = true; + scheduler.triggerJob(jobKey, dataMap); + } + return result; + } + + /** + * 新增任务 + * + * @param job 调度信息 调度信息 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int insertJob(SysJob job) throws SchedulerException, TaskException + { + job.setStatus(ScheduleConstants.Status.PAUSE.getValue()); + int rows = jobMapper.insertJob(job); + if (rows > 0) + { + ScheduleUtils.createScheduleJob(scheduler, job); + } + return rows; + } + + /** + * 更新任务的时间表达式 + * + * @param job 调度信息 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int updateJob(SysJob job) throws SchedulerException, TaskException + { + SysJob properties = selectJobById(job.getJobId()); + int rows = jobMapper.updateJob(job); + if (rows > 0) + { + updateSchedulerJob(job, properties.getJobGroup()); + } + return rows; + } + + /** + * 更新任务 + * + * @param job 任务对象 + * @param jobGroup 任务组名 + */ + public void updateSchedulerJob(SysJob job, String jobGroup) throws SchedulerException, TaskException + { + Long jobId = job.getJobId(); + // 判断是否存在 + JobKey jobKey = ScheduleUtils.getJobKey(jobId, jobGroup); + if (scheduler.checkExists(jobKey)) + { + // 防止创建时存在数据问题 先移除,然后在执行创建操作 + scheduler.deleteJob(jobKey); + } + ScheduleUtils.createScheduleJob(scheduler, job); + } + + /** + * 校验cron表达式是否有效 + * + * @param cronExpression 表达式 + * @return 结果 + */ + @Override + public boolean checkCronExpressionIsValid(String cronExpression) + { + return CronUtils.isValid(cronExpression); + } +} diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java new file mode 100644 index 0000000..086eda4 --- /dev/null +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java @@ -0,0 +1,28 @@ +package com.ruoyi.quartz.task; + +import org.springframework.stereotype.Component; +import com.ruoyi.common.utils.StringUtils; + +/** + * 定时任务调度测试 + * + * @author #author# + */ +@Component("ryTask") +public class RyTask +{ + public void ryMultipleParams(String s, Boolean b, Long l, Double d, Integer i) + { + System.out.println(StringUtils.format("执行多参方法: 字符串类型{},布尔类型{},长整型{},浮点型{},整形{}", s, b, l, d, i)); + } + + public void ryParams(String params) + { + System.out.println("执行有参方法:" + params); + } + + public void ryNoParams() + { + System.out.println("执行无参方法"); + } +} diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/AbstractQuartzJob.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/AbstractQuartzJob.java new file mode 100644 index 0000000..f241c54 --- /dev/null +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/AbstractQuartzJob.java @@ -0,0 +1,107 @@ +package com.ruoyi.quartz.util; + +import java.util.Date; +import org.quartz.Job; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.constant.ScheduleConstants; +import com.ruoyi.common.utils.ExceptionUtil; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.bean.BeanUtils; +import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.quartz.domain.SysJob; +import com.ruoyi.quartz.domain.SysJobLog; +import com.ruoyi.quartz.service.ISysJobLogService; + +/** + * 抽象quartz调用 + * + * @author #author# + */ +public abstract class AbstractQuartzJob implements Job +{ + private static final Logger log = LoggerFactory.getLogger(AbstractQuartzJob.class); + + /** + * 线程本地变量 + */ + private static ThreadLocal threadLocal = new ThreadLocal<>(); + + @Override + public void execute(JobExecutionContext context) throws JobExecutionException + { + SysJob sysJob = new SysJob(); + BeanUtils.copyBeanProp(sysJob, context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES)); + try + { + before(context, sysJob); + if (sysJob != null) + { + doExecute(context, sysJob); + } + after(context, sysJob, null); + } + catch (Exception e) + { + log.error("任务执行异常 - :", e); + after(context, sysJob, e); + } + } + + /** + * 执行前 + * + * @param context 工作执行上下文对象 + * @param sysJob 系统计划任务 + */ + protected void before(JobExecutionContext context, SysJob sysJob) + { + threadLocal.set(new Date()); + } + + /** + * 执行后 + * + * @param context 工作执行上下文对象 + * @param sysJob 系统计划任务 + */ + protected void after(JobExecutionContext context, SysJob sysJob, Exception e) + { + Date startTime = threadLocal.get(); + threadLocal.remove(); + + final SysJobLog sysJobLog = new SysJobLog(); + sysJobLog.setJobName(sysJob.getJobName()); + sysJobLog.setJobGroup(sysJob.getJobGroup()); + sysJobLog.setInvokeTarget(sysJob.getInvokeTarget()); + sysJobLog.setStartTime(startTime); + sysJobLog.setStopTime(new Date()); + long runMs = sysJobLog.getStopTime().getTime() - sysJobLog.getStartTime().getTime(); + sysJobLog.setJobMessage(sysJobLog.getJobName() + " 总共耗时:" + runMs + "毫秒"); + if (e != null) + { + sysJobLog.setStatus(Constants.FAIL); + String errorMsg = StringUtils.substring(ExceptionUtil.getExceptionMessage(e), 0, 2000); + sysJobLog.setExceptionInfo(errorMsg); + } + else + { + sysJobLog.setStatus(Constants.SUCCESS); + } + + // 写入数据库当中 + SpringUtils.getBean(ISysJobLogService.class).addJobLog(sysJobLog); + } + + /** + * 执行方法,由子类重载 + * + * @param context 工作执行上下文对象 + * @param sysJob 系统计划任务 + * @throws Exception 执行过程中的异常 + */ + protected abstract void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception; +} diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/CronUtils.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/CronUtils.java new file mode 100644 index 0000000..6eb0de8 --- /dev/null +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/CronUtils.java @@ -0,0 +1,63 @@ +package com.ruoyi.quartz.util; + +import java.text.ParseException; +import java.util.Date; +import org.quartz.CronExpression; + +/** + * cron表达式工具类 + * + * @author #author# + * + */ +public class CronUtils +{ + /** + * 返回一个布尔值代表一个给定的Cron表达式的有效性 + * + * @param cronExpression Cron表达式 + * @return boolean 表达式是否有效 + */ + public static boolean isValid(String cronExpression) + { + return CronExpression.isValidExpression(cronExpression); + } + + /** + * 返回一个字符串值,表示该消息无效Cron表达式给出有效性 + * + * @param cronExpression Cron表达式 + * @return String 无效时返回表达式错误描述,如果有效返回null + */ + public static String getInvalidMessage(String cronExpression) + { + try + { + new CronExpression(cronExpression); + return null; + } + catch (ParseException pe) + { + return pe.getMessage(); + } + } + + /** + * 返回下一个执行时间根据给定的Cron表达式 + * + * @param cronExpression Cron表达式 + * @return Date 下次Cron表达式执行时间 + */ + public static Date getNextExecution(String cronExpression) + { + try + { + CronExpression cron = new CronExpression(cronExpression); + return cron.getNextValidTimeAfter(new Date(System.currentTimeMillis())); + } + catch (ParseException e) + { + throw new IllegalArgumentException(e.getMessage()); + } + } +} diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/JobInvokeUtil.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/JobInvokeUtil.java new file mode 100644 index 0000000..2d24e15 --- /dev/null +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/JobInvokeUtil.java @@ -0,0 +1,182 @@ +package com.ruoyi.quartz.util; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.LinkedList; +import java.util.List; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.quartz.domain.SysJob; + +/** + * 任务执行工具 + * + * @author #author# + */ +public class JobInvokeUtil +{ + /** + * 执行方法 + * + * @param sysJob 系统任务 + */ + public static void invokeMethod(SysJob sysJob) throws Exception + { + String invokeTarget = sysJob.getInvokeTarget(); + String beanName = getBeanName(invokeTarget); + String methodName = getMethodName(invokeTarget); + List methodParams = getMethodParams(invokeTarget); + + if (!isValidClassName(beanName)) + { + Object bean = SpringUtils.getBean(beanName); + invokeMethod(bean, methodName, methodParams); + } + else + { + Object bean = Class.forName(beanName).newInstance(); + invokeMethod(bean, methodName, methodParams); + } + } + + /** + * 调用任务方法 + * + * @param bean 目标对象 + * @param methodName 方法名称 + * @param methodParams 方法参数 + */ + private static void invokeMethod(Object bean, String methodName, List methodParams) + throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, + InvocationTargetException + { + if (StringUtils.isNotNull(methodParams) && methodParams.size() > 0) + { + Method method = bean.getClass().getMethod(methodName, getMethodParamsType(methodParams)); + method.invoke(bean, getMethodParamsValue(methodParams)); + } + else + { + Method method = bean.getClass().getMethod(methodName); + method.invoke(bean); + } + } + + /** + * 校验是否为为class包名 + * + * @param invokeTarget 名称 + * @return true是 false否 + */ + public static boolean isValidClassName(String invokeTarget) + { + return StringUtils.countMatches(invokeTarget, ".") > 1; + } + + /** + * 获取bean名称 + * + * @param invokeTarget 目标字符串 + * @return bean名称 + */ + public static String getBeanName(String invokeTarget) + { + String beanName = StringUtils.substringBefore(invokeTarget, "("); + return StringUtils.substringBeforeLast(beanName, "."); + } + + /** + * 获取bean方法 + * + * @param invokeTarget 目标字符串 + * @return method方法 + */ + public static String getMethodName(String invokeTarget) + { + String methodName = StringUtils.substringBefore(invokeTarget, "("); + return StringUtils.substringAfterLast(methodName, "."); + } + + /** + * 获取method方法参数相关列表 + * + * @param invokeTarget 目标字符串 + * @return method方法相关参数列表 + */ + public static List getMethodParams(String invokeTarget) + { + String methodStr = StringUtils.substringBetween(invokeTarget, "(", ")"); + if (StringUtils.isEmpty(methodStr)) + { + return null; + } + String[] methodParams = methodStr.split(",(?=([^\"']*[\"'][^\"']*[\"'])*[^\"']*$)"); + List classs = new LinkedList<>(); + for (int i = 0; i < methodParams.length; i++) + { + String str = StringUtils.trimToEmpty(methodParams[i]); + // String字符串类型,以'或"开头 + if (StringUtils.startsWithAny(str, "'", "\"")) + { + classs.add(new Object[] { StringUtils.substring(str, 1, str.length() - 1), String.class }); + } + // boolean布尔类型,等于true或者false + else if ("true".equalsIgnoreCase(str) || "false".equalsIgnoreCase(str)) + { + classs.add(new Object[] { Boolean.valueOf(str), Boolean.class }); + } + // long长整形,以L结尾 + else if (StringUtils.endsWith(str, "L")) + { + classs.add(new Object[] { Long.valueOf(StringUtils.substring(str, 0, str.length() - 1)), Long.class }); + } + // double浮点类型,以D结尾 + else if (StringUtils.endsWith(str, "D")) + { + classs.add(new Object[] { Double.valueOf(StringUtils.substring(str, 0, str.length() - 1)), Double.class }); + } + // 其他类型归类为整形 + else + { + classs.add(new Object[] { Integer.valueOf(str), Integer.class }); + } + } + return classs; + } + + /** + * 获取参数类型 + * + * @param methodParams 参数相关列表 + * @return 参数类型列表 + */ + public static Class[] getMethodParamsType(List methodParams) + { + Class[] classs = new Class[methodParams.size()]; + int index = 0; + for (Object[] os : methodParams) + { + classs[index] = (Class) os[1]; + index++; + } + return classs; + } + + /** + * 获取参数值 + * + * @param methodParams 参数相关列表 + * @return 参数值列表 + */ + public static Object[] getMethodParamsValue(List methodParams) + { + Object[] classs = new Object[methodParams.size()]; + int index = 0; + for (Object[] os : methodParams) + { + classs[index] = (Object) os[0]; + index++; + } + return classs; + } +} diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzDisallowConcurrentExecution.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzDisallowConcurrentExecution.java new file mode 100644 index 0000000..d275667 --- /dev/null +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzDisallowConcurrentExecution.java @@ -0,0 +1,21 @@ +package com.ruoyi.quartz.util; + +import org.quartz.DisallowConcurrentExecution; +import org.quartz.JobExecutionContext; +import com.ruoyi.quartz.domain.SysJob; + +/** + * 定时任务处理(禁止并发执行) + * + * @author #author# + * + */ +@DisallowConcurrentExecution +public class QuartzDisallowConcurrentExecution extends AbstractQuartzJob +{ + @Override + protected void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception + { + JobInvokeUtil.invokeMethod(sysJob); + } +} diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzJobExecution.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzJobExecution.java new file mode 100644 index 0000000..f0e09ab --- /dev/null +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzJobExecution.java @@ -0,0 +1,19 @@ +package com.ruoyi.quartz.util; + +import org.quartz.JobExecutionContext; +import com.ruoyi.quartz.domain.SysJob; + +/** + * 定时任务处理(允许并发执行) + * + * @author #author# + * + */ +public class QuartzJobExecution extends AbstractQuartzJob +{ + @Override + protected void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception + { + JobInvokeUtil.invokeMethod(sysJob); + } +} diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/ScheduleUtils.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/ScheduleUtils.java new file mode 100644 index 0000000..456f945 --- /dev/null +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/ScheduleUtils.java @@ -0,0 +1,139 @@ +package com.ruoyi.quartz.util; + +import org.quartz.CronScheduleBuilder; +import org.quartz.CronTrigger; +import org.quartz.Job; +import org.quartz.JobBuilder; +import org.quartz.JobDetail; +import org.quartz.JobKey; +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.quartz.TriggerBuilder; +import org.quartz.TriggerKey; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.constant.ScheduleConstants; +import com.ruoyi.common.exception.job.TaskException; +import com.ruoyi.common.exception.job.TaskException.Code; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.quartz.domain.SysJob; + +/** + * 定时任务工具类 + * + * @author #author# + * + */ +public class ScheduleUtils +{ + /** + * 得到quartz任务类 + * + * @param sysJob 执行计划 + * @return 具体执行任务类 + */ + private static Class getQuartzJobClass(SysJob sysJob) + { + boolean isConcurrent = "0".equals(sysJob.getConcurrent()); + return isConcurrent ? QuartzJobExecution.class : QuartzDisallowConcurrentExecution.class; + } + + /** + * 构建任务触发对象 + */ + public static TriggerKey getTriggerKey(Long jobId, String jobGroup) + { + return TriggerKey.triggerKey(ScheduleConstants.TASK_CLASS_NAME + jobId, jobGroup); + } + + /** + * 构建任务键对象 + */ + public static JobKey getJobKey(Long jobId, String jobGroup) + { + return JobKey.jobKey(ScheduleConstants.TASK_CLASS_NAME + jobId, jobGroup); + } + + /** + * 创建定时任务 + */ + public static void createScheduleJob(Scheduler scheduler, SysJob job) throws SchedulerException, TaskException + { + Class jobClass = getQuartzJobClass(job); + // 构建job信息 + Long jobId = job.getJobId(); + String jobGroup = job.getJobGroup(); + JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(getJobKey(jobId, jobGroup)).build(); + + // 表达式调度构建器 + CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression()); + cronScheduleBuilder = handleCronScheduleMisfirePolicy(job, cronScheduleBuilder); + + // 按新的cronExpression表达式构建一个新的trigger + CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(jobId, jobGroup)) + .withSchedule(cronScheduleBuilder).build(); + + // 放入参数,运行时的方法可以获取 + jobDetail.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES, job); + + // 判断是否存在 + if (scheduler.checkExists(getJobKey(jobId, jobGroup))) + { + // 防止创建时存在数据问题 先移除,然后在执行创建操作 + scheduler.deleteJob(getJobKey(jobId, jobGroup)); + } + + // 判断任务是否过期 + if (StringUtils.isNotNull(CronUtils.getNextExecution(job.getCronExpression()))) + { + // 执行调度任务 + scheduler.scheduleJob(jobDetail, trigger); + } + + // 暂停任务 + if (job.getStatus().equals(ScheduleConstants.Status.PAUSE.getValue())) + { + scheduler.pauseJob(ScheduleUtils.getJobKey(jobId, jobGroup)); + } + } + + /** + * 设置定时任务策略 + */ + public static CronScheduleBuilder handleCronScheduleMisfirePolicy(SysJob job, CronScheduleBuilder cb) + throws TaskException + { + switch (job.getMisfirePolicy()) + { + case ScheduleConstants.MISFIRE_DEFAULT: + return cb; + case ScheduleConstants.MISFIRE_IGNORE_MISFIRES: + return cb.withMisfireHandlingInstructionIgnoreMisfires(); + case ScheduleConstants.MISFIRE_FIRE_AND_PROCEED: + return cb.withMisfireHandlingInstructionFireAndProceed(); + case ScheduleConstants.MISFIRE_DO_NOTHING: + return cb.withMisfireHandlingInstructionDoNothing(); + default: + throw new TaskException("The task misfire policy '" + job.getMisfirePolicy() + + "' cannot be used in cron schedule tasks", Code.CONFIG_ERROR); + } + } + + /** + * 检查包名是否为白名单配置 + * + * @param invokeTarget 目标字符串 + * @return 结果 + */ + public static boolean whiteList(String invokeTarget) + { + String packageName = StringUtils.substringBefore(invokeTarget, "("); + int count = StringUtils.countMatches(packageName, "."); + if (count > 1) + { + return StringUtils.containsAnyIgnoreCase(invokeTarget, Constants.JOB_WHITELIST_STR); + } + Object obj = SpringUtils.getBean(StringUtils.split(invokeTarget, ".")[0]); + return StringUtils.containsAnyIgnoreCase(obj.getClass().getPackage().getName(), Constants.JOB_WHITELIST_STR); + } +} diff --git a/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml b/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml new file mode 100644 index 0000000..e608e42 --- /dev/null +++ b/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + select job_log_id, job_name, job_group, invoke_target, job_message, status, exception_info, create_time + from sys_job_log + + + + + + + + + + delete from sys_job_log where job_log_id = #{jobLogId} + + + + delete from sys_job_log where job_log_id in + + #{jobLogId} + + + + + truncate table sys_job_log + + + + insert into sys_job_log( + job_log_id, + job_name, + job_group, + invoke_target, + job_message, + status, + exception_info, + create_time + )values( + #{jobLogId}, + #{jobName}, + #{jobGroup}, + #{invokeTarget}, + #{jobMessage}, + #{status}, + #{exceptionInfo}, + sysdate() + ) + + + \ No newline at end of file diff --git a/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml b/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml new file mode 100644 index 0000000..5605c44 --- /dev/null +++ b/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + select job_id, job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status, create_by, create_time, remark + from sys_job + + + + + + + + + + delete from sys_job where job_id = #{jobId} + + + + delete from sys_job where job_id in + + #{jobId} + + + + + update sys_job + + job_name = #{jobName}, + job_group = #{jobGroup}, + invoke_target = #{invokeTarget}, + cron_expression = #{cronExpression}, + misfire_policy = #{misfirePolicy}, + concurrent = #{concurrent}, + status = #{status}, + remark = #{remark}, + update_by = #{updateBy}, + update_time = sysdate() + + where job_id = #{jobId} + + + + insert into sys_job( + job_id, + job_name, + job_group, + invoke_target, + cron_expression, + misfire_policy, + concurrent, + status, + remark, + create_by, + create_time + )values( + #{jobId}, + #{jobName}, + #{jobGroup}, + #{invokeTarget}, + #{cronExpression}, + #{misfirePolicy}, + #{concurrent}, + #{status}, + #{remark}, + #{createBy}, + sysdate() + ) + + + \ No newline at end of file diff --git a/ruoyi-system/pom.xml b/ruoyi-system/pom.xml new file mode 100644 index 0000000..aa268bd --- /dev/null +++ b/ruoyi-system/pom.xml @@ -0,0 +1,28 @@ + + + + ruoyi + com.ruoyi + 3.8.5 + + 4.0.0 + + ruoyi-system + + + system系统模块 + + + + + + + com.ruoyi + ruoyi-common + + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysCache.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysCache.java new file mode 100644 index 0000000..b134b16 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysCache.java @@ -0,0 +1,81 @@ +package com.ruoyi.system.domain; + +import com.ruoyi.common.utils.StringUtils; + +/** + * 缓存信息 + * + * @author #author# + */ +public class SysCache +{ + /** 缓存名称 */ + private String cacheName = ""; + + /** 缓存键名 */ + private String cacheKey = ""; + + /** 缓存内容 */ + private String cacheValue = ""; + + /** 备注 */ + private String remark = ""; + + public SysCache() + { + + } + + public SysCache(String cacheName, String remark) + { + this.cacheName = cacheName; + this.remark = remark; + } + + public SysCache(String cacheName, String cacheKey, String cacheValue) + { + this.cacheName = StringUtils.replace(cacheName, ":", ""); + this.cacheKey = StringUtils.replace(cacheKey, cacheName, ""); + this.cacheValue = cacheValue; + } + + public String getCacheName() + { + return cacheName; + } + + public void setCacheName(String cacheName) + { + this.cacheName = cacheName; + } + + public String getCacheKey() + { + return cacheKey; + } + + public void setCacheKey(String cacheKey) + { + this.cacheKey = cacheKey; + } + + public String getCacheValue() + { + return cacheValue; + } + + public void setCacheValue(String cacheValue) + { + this.cacheValue = cacheValue; + } + + public String getRemark() + { + return remark; + } + + public void setRemark(String remark) + { + this.remark = remark; + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java new file mode 100644 index 0000000..b76d439 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java @@ -0,0 +1,111 @@ +package com.ruoyi.system.domain; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 参数配置表 sys_config + * + * @author #author# + */ +public class SysConfig extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 参数主键 */ + @Excel(name = "参数主键", cellType = ColumnType.NUMERIC) + private Long configId; + + /** 参数名称 */ + @Excel(name = "参数名称") + private String configName; + + /** 参数键名 */ + @Excel(name = "参数键名") + private String configKey; + + /** 参数键值 */ + @Excel(name = "参数键值") + private String configValue; + + /** 系统内置(Y是 N否) */ + @Excel(name = "系统内置", readConverterExp = "Y=是,N=否") + private String configType; + + public Long getConfigId() + { + return configId; + } + + public void setConfigId(Long configId) + { + this.configId = configId; + } + + @NotBlank(message = "参数名称不能为空") + @Size(min = 0, max = 100, message = "参数名称不能超过100个字符") + public String getConfigName() + { + return configName; + } + + public void setConfigName(String configName) + { + this.configName = configName; + } + + @NotBlank(message = "参数键名长度不能为空") + @Size(min = 0, max = 100, message = "参数键名长度不能超过100个字符") + public String getConfigKey() + { + return configKey; + } + + public void setConfigKey(String configKey) + { + this.configKey = configKey; + } + + @NotBlank(message = "参数键值不能为空") + @Size(min = 0, max = 500, message = "参数键值长度不能超过500个字符") + public String getConfigValue() + { + return configValue; + } + + public void setConfigValue(String configValue) + { + this.configValue = configValue; + } + + public String getConfigType() + { + return configType; + } + + public void setConfigType(String configType) + { + this.configType = configType; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("configId", getConfigId()) + .append("configName", getConfigName()) + .append("configKey", getConfigKey()) + .append("configValue", getConfigValue()) + .append("configType", getConfigType()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java new file mode 100644 index 0000000..fec817e --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java @@ -0,0 +1,144 @@ +package com.ruoyi.system.domain; + +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 系统访问记录表 sys_logininfor + * + * @author #author# + */ +public class SysLogininfor extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** ID */ + @Excel(name = "序号", cellType = ColumnType.NUMERIC) + private Long infoId; + + /** 用户账号 */ + @Excel(name = "用户账号") + private String userName; + + /** 登录状态 0成功 1失败 */ + @Excel(name = "登录状态", readConverterExp = "0=成功,1=失败") + private String status; + + /** 登录IP地址 */ + @Excel(name = "登录地址") + private String ipaddr; + + /** 登录地点 */ + @Excel(name = "登录地点") + private String loginLocation; + + /** 浏览器类型 */ + @Excel(name = "浏览器") + private String browser; + + /** 操作系统 */ + @Excel(name = "操作系统") + private String os; + + /** 提示消息 */ + @Excel(name = "提示消息") + private String msg; + + /** 访问时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "访问时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + private Date loginTime; + + public Long getInfoId() + { + return infoId; + } + + public void setInfoId(Long infoId) + { + this.infoId = infoId; + } + + public String getUserName() + { + return userName; + } + + public void setUserName(String userName) + { + this.userName = userName; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + public String getIpaddr() + { + return ipaddr; + } + + public void setIpaddr(String ipaddr) + { + this.ipaddr = ipaddr; + } + + public String getLoginLocation() + { + return loginLocation; + } + + public void setLoginLocation(String loginLocation) + { + this.loginLocation = loginLocation; + } + + public String getBrowser() + { + return browser; + } + + public void setBrowser(String browser) + { + this.browser = browser; + } + + public String getOs() + { + return os; + } + + public void setOs(String os) + { + this.os = os; + } + + public String getMsg() + { + return msg; + } + + public void setMsg(String msg) + { + this.msg = msg; + } + + public Date getLoginTime() + { + return loginTime; + } + + public void setLoginTime(Date loginTime) + { + this.loginTime = loginTime; + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java new file mode 100644 index 0000000..4ce6e7b --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java @@ -0,0 +1,102 @@ +package com.ruoyi.system.domain; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.core.domain.BaseEntity; +import com.ruoyi.common.xss.Xss; + +/** + * 通知公告表 sys_notice + * + * @author #author# + */ +public class SysNotice extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 公告ID */ + private Long noticeId; + + /** 公告标题 */ + private String noticeTitle; + + /** 公告类型(1通知 2公告) */ + private String noticeType; + + /** 公告内容 */ + private String noticeContent; + + /** 公告状态(0正常 1关闭) */ + private String status; + + public Long getNoticeId() + { + return noticeId; + } + + public void setNoticeId(Long noticeId) + { + this.noticeId = noticeId; + } + + public void setNoticeTitle(String noticeTitle) + { + this.noticeTitle = noticeTitle; + } + + @Xss(message = "公告标题不能包含脚本字符") + @NotBlank(message = "公告标题不能为空") + @Size(min = 0, max = 50, message = "公告标题不能超过50个字符") + public String getNoticeTitle() + { + return noticeTitle; + } + + public void setNoticeType(String noticeType) + { + this.noticeType = noticeType; + } + + public String getNoticeType() + { + return noticeType; + } + + public void setNoticeContent(String noticeContent) + { + this.noticeContent = noticeContent; + } + + public String getNoticeContent() + { + return noticeContent; + } + + public void setStatus(String status) + { + this.status = status; + } + + public String getStatus() + { + return status; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("noticeId", getNoticeId()) + .append("noticeTitle", getNoticeTitle()) + .append("noticeType", getNoticeType()) + .append("noticeContent", getNoticeContent()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java new file mode 100644 index 0000000..410c28c --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java @@ -0,0 +1,255 @@ +package com.ruoyi.system.domain; + +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 操作日志记录表 oper_log + * + * @author #author# + */ +public class SysOperLog extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 日志主键 */ + @Excel(name = "操作序号", cellType = ColumnType.NUMERIC) + private Long operId; + + /** 操作模块 */ + @Excel(name = "操作模块") + private String title; + + /** 业务类型(0其它 1新增 2修改 3删除) */ + @Excel(name = "业务类型", readConverterExp = "0=其它,1=新增,2=修改,3=删除,4=授权,5=导出,6=导入,7=强退,8=生成代码,9=清空数据") + private Integer businessType; + + /** 业务类型数组 */ + private Integer[] businessTypes; + + /** 请求方法 */ + @Excel(name = "请求方法") + private String method; + + /** 请求方式 */ + @Excel(name = "请求方式") + private String requestMethod; + + /** 操作类别(0其它 1后台用户 2手机端用户) */ + @Excel(name = "操作类别", readConverterExp = "0=其它,1=后台用户,2=手机端用户") + private Integer operatorType; + + /** 操作人员 */ + @Excel(name = "操作人员") + private String operName; + + /** 部门名称 */ + @Excel(name = "部门名称") + private String deptName; + + /** 请求url */ + @Excel(name = "请求地址") + private String operUrl; + + /** 操作地址 */ + @Excel(name = "操作地址") + private String operIp; + + /** 操作地点 */ + @Excel(name = "操作地点") + private String operLocation; + + /** 请求参数 */ + @Excel(name = "请求参数") + private String operParam; + + /** 返回参数 */ + @Excel(name = "返回参数") + private String jsonResult; + + /** 操作状态(0正常 1异常) */ + @Excel(name = "状态", readConverterExp = "0=正常,1=异常") + private Integer status; + + /** 错误消息 */ + @Excel(name = "错误消息") + private String errorMsg; + + /** 操作时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @Excel(name = "操作时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") + private Date operTime; + + public Long getOperId() + { + return operId; + } + + public void setOperId(Long operId) + { + this.operId = operId; + } + + public String getTitle() + { + return title; + } + + public void setTitle(String title) + { + this.title = title; + } + + public Integer getBusinessType() + { + return businessType; + } + + public void setBusinessType(Integer businessType) + { + this.businessType = businessType; + } + + public Integer[] getBusinessTypes() + { + return businessTypes; + } + + public void setBusinessTypes(Integer[] businessTypes) + { + this.businessTypes = businessTypes; + } + + public String getMethod() + { + return method; + } + + public void setMethod(String method) + { + this.method = method; + } + + public String getRequestMethod() + { + return requestMethod; + } + + public void setRequestMethod(String requestMethod) + { + this.requestMethod = requestMethod; + } + + public Integer getOperatorType() + { + return operatorType; + } + + public void setOperatorType(Integer operatorType) + { + this.operatorType = operatorType; + } + + public String getOperName() + { + return operName; + } + + public void setOperName(String operName) + { + this.operName = operName; + } + + public String getDeptName() + { + return deptName; + } + + public void setDeptName(String deptName) + { + this.deptName = deptName; + } + + public String getOperUrl() + { + return operUrl; + } + + public void setOperUrl(String operUrl) + { + this.operUrl = operUrl; + } + + public String getOperIp() + { + return operIp; + } + + public void setOperIp(String operIp) + { + this.operIp = operIp; + } + + public String getOperLocation() + { + return operLocation; + } + + public void setOperLocation(String operLocation) + { + this.operLocation = operLocation; + } + + public String getOperParam() + { + return operParam; + } + + public void setOperParam(String operParam) + { + this.operParam = operParam; + } + + public String getJsonResult() + { + return jsonResult; + } + + public void setJsonResult(String jsonResult) + { + this.jsonResult = jsonResult; + } + + public Integer getStatus() + { + return status; + } + + public void setStatus(Integer status) + { + this.status = status; + } + + public String getErrorMsg() + { + return errorMsg; + } + + public void setErrorMsg(String errorMsg) + { + this.errorMsg = errorMsg; + } + + public Date getOperTime() + { + return operTime; + } + + public void setOperTime(Date operTime) + { + this.operTime = operTime; + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java new file mode 100644 index 0000000..696bb0c --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java @@ -0,0 +1,124 @@ +package com.ruoyi.system.domain; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.annotation.Excel.ColumnType; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 岗位表 sys_post + * + * @author #author# + */ +public class SysPost extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 岗位序号 */ + @Excel(name = "岗位序号", cellType = ColumnType.NUMERIC) + private Long postId; + + /** 岗位编码 */ + @Excel(name = "岗位编码") + private String postCode; + + /** 岗位名称 */ + @Excel(name = "岗位名称") + private String postName; + + /** 岗位排序 */ + @Excel(name = "岗位排序") + private Integer postSort; + + /** 状态(0正常 1停用) */ + @Excel(name = "状态", readConverterExp = "0=正常,1=停用") + private String status; + + /** 用户是否存在此岗位标识 默认不存在 */ + private boolean flag = false; + + public Long getPostId() + { + return postId; + } + + public void setPostId(Long postId) + { + this.postId = postId; + } + + @NotBlank(message = "岗位编码不能为空") + @Size(min = 0, max = 64, message = "岗位编码长度不能超过64个字符") + public String getPostCode() + { + return postCode; + } + + public void setPostCode(String postCode) + { + this.postCode = postCode; + } + + @NotBlank(message = "岗位名称不能为空") + @Size(min = 0, max = 50, message = "岗位名称长度不能超过50个字符") + public String getPostName() + { + return postName; + } + + public void setPostName(String postName) + { + this.postName = postName; + } + + @NotNull(message = "显示顺序不能为空") + public Integer getPostSort() + { + return postSort; + } + + public void setPostSort(Integer postSort) + { + this.postSort = postSort; + } + + public String getStatus() + { + return status; + } + + public void setStatus(String status) + { + this.status = status; + } + + public boolean isFlag() + { + return flag; + } + + public void setFlag(boolean flag) + { + this.flag = flag; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("postId", getPostId()) + .append("postCode", getPostCode()) + .append("postName", getPostName()) + .append("postSort", getPostSort()) + .append("status", getStatus()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateBy", getUpdateBy()) + .append("updateTime", getUpdateTime()) + .append("remark", getRemark()) + .toString(); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java new file mode 100644 index 0000000..0b3e5c8 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java @@ -0,0 +1,46 @@ +package com.ruoyi.system.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 角色和部门关联 sys_role_dept + * + * @author #author# + */ +public class SysRoleDept +{ + /** 角色ID */ + private Long roleId; + + /** 部门ID */ + private Long deptId; + + public Long getRoleId() + { + return roleId; + } + + public void setRoleId(Long roleId) + { + this.roleId = roleId; + } + + public Long getDeptId() + { + return deptId; + } + + public void setDeptId(Long deptId) + { + this.deptId = deptId; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("roleId", getRoleId()) + .append("deptId", getDeptId()) + .toString(); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java new file mode 100644 index 0000000..61b779b --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java @@ -0,0 +1,46 @@ +package com.ruoyi.system.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 角色和菜单关联 sys_role_menu + * + * @author #author# + */ +public class SysRoleMenu +{ + /** 角色ID */ + private Long roleId; + + /** 菜单ID */ + private Long menuId; + + public Long getRoleId() + { + return roleId; + } + + public void setRoleId(Long roleId) + { + this.roleId = roleId; + } + + public Long getMenuId() + { + return menuId; + } + + public void setMenuId(Long menuId) + { + this.menuId = menuId; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("roleId", getRoleId()) + .append("menuId", getMenuId()) + .toString(); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java new file mode 100644 index 0000000..7242112 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java @@ -0,0 +1,113 @@ +package com.ruoyi.system.domain; + +/** + * 当前在线会话 + * + * @author #author# + */ +public class SysUserOnline +{ + /** 会话编号 */ + private String tokenId; + + /** 部门名称 */ + private String deptName; + + /** 用户名称 */ + private String userName; + + /** 登录IP地址 */ + private String ipaddr; + + /** 登录地址 */ + private String loginLocation; + + /** 浏览器类型 */ + private String browser; + + /** 操作系统 */ + private String os; + + /** 登录时间 */ + private Long loginTime; + + public String getTokenId() + { + return tokenId; + } + + public void setTokenId(String tokenId) + { + this.tokenId = tokenId; + } + + public String getDeptName() + { + return deptName; + } + + public void setDeptName(String deptName) + { + this.deptName = deptName; + } + + public String getUserName() + { + return userName; + } + + public void setUserName(String userName) + { + this.userName = userName; + } + + public String getIpaddr() + { + return ipaddr; + } + + public void setIpaddr(String ipaddr) + { + this.ipaddr = ipaddr; + } + + public String getLoginLocation() + { + return loginLocation; + } + + public void setLoginLocation(String loginLocation) + { + this.loginLocation = loginLocation; + } + + public String getBrowser() + { + return browser; + } + + public void setBrowser(String browser) + { + this.browser = browser; + } + + public String getOs() + { + return os; + } + + public void setOs(String os) + { + this.os = os; + } + + public Long getLoginTime() + { + return loginTime; + } + + public void setLoginTime(Long loginTime) + { + this.loginTime = loginTime; + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java new file mode 100644 index 0000000..5a996f4 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java @@ -0,0 +1,46 @@ +package com.ruoyi.system.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 用户和岗位关联 sys_user_post + * + * @author #author# + */ +public class SysUserPost +{ + /** 用户ID */ + private Long userId; + + /** 岗位ID */ + private Long postId; + + public Long getUserId() + { + return userId; + } + + public void setUserId(Long userId) + { + this.userId = userId; + } + + public Long getPostId() + { + return postId; + } + + public void setPostId(Long postId) + { + this.postId = postId; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("userId", getUserId()) + .append("postId", getPostId()) + .toString(); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java new file mode 100644 index 0000000..d1f28a7 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java @@ -0,0 +1,46 @@ +package com.ruoyi.system.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 用户和角色关联 sys_user_role + * + * @author #author# + */ +public class SysUserRole +{ + /** 用户ID */ + private Long userId; + + /** 角色ID */ + private Long roleId; + + public Long getUserId() + { + return userId; + } + + public void setUserId(Long userId) + { + this.userId = userId; + } + + public Long getRoleId() + { + return roleId; + } + + public void setRoleId(Long roleId) + { + this.roleId = roleId; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("userId", getUserId()) + .append("roleId", getRoleId()) + .toString(); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MetaVo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MetaVo.java new file mode 100644 index 0000000..757b035 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MetaVo.java @@ -0,0 +1,106 @@ +package com.ruoyi.system.domain.vo; + +import com.ruoyi.common.utils.StringUtils; + +/** + * 路由显示信息 + * + * @author #author# + */ +public class MetaVo +{ + /** + * 设置该路由在侧边栏和面包屑中展示的名字 + */ + private String title; + + /** + * 设置该路由的图标,对应路径src/assets/icons/svg + */ + private String icon; + + /** + * 设置为true,则不会被 缓存 + */ + private boolean noCache; + + /** + * 内链地址(http(s)://开头) + */ + private String link; + + public MetaVo() + { + } + + public MetaVo(String title, String icon) + { + this.title = title; + this.icon = icon; + } + + public MetaVo(String title, String icon, boolean noCache) + { + this.title = title; + this.icon = icon; + this.noCache = noCache; + } + + public MetaVo(String title, String icon, String link) + { + this.title = title; + this.icon = icon; + this.link = link; + } + + public MetaVo(String title, String icon, boolean noCache, String link) + { + this.title = title; + this.icon = icon; + this.noCache = noCache; + if (StringUtils.ishttp(link)) + { + this.link = link; + } + } + + public boolean isNoCache() + { + return noCache; + } + + public void setNoCache(boolean noCache) + { + this.noCache = noCache; + } + + public String getTitle() + { + return title; + } + + public void setTitle(String title) + { + this.title = title; + } + + public String getIcon() + { + return icon; + } + + public void setIcon(String icon) + { + this.icon = icon; + } + + public String getLink() + { + return link; + } + + public void setLink(String link) + { + this.link = link; + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RouterVo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RouterVo.java new file mode 100644 index 0000000..5126472 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RouterVo.java @@ -0,0 +1,148 @@ +package com.ruoyi.system.domain.vo; + +import com.fasterxml.jackson.annotation.JsonInclude; +import java.util.List; + +/** + * 路由配置信息 + * + * @author #author# + */ +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public class RouterVo +{ + /** + * 路由名字 + */ + private String name; + + /** + * 路由地址 + */ + private String path; + + /** + * 是否隐藏路由,当设置 true 的时候该路由不会再侧边栏出现 + */ + private boolean hidden; + + /** + * 重定向地址,当设置 noRedirect 的时候该路由在面包屑导航中不可被点击 + */ + private String redirect; + + /** + * 组件地址 + */ + private String component; + + /** + * 路由参数:如 {"id": 1, "name": "ry"} + */ + private String query; + + /** + * 当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式--如组件页面 + */ + private Boolean alwaysShow; + + /** + * 其他元素 + */ + private MetaVo meta; + + /** + * 子路由 + */ + private List children; + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public String getPath() + { + return path; + } + + public void setPath(String path) + { + this.path = path; + } + + public boolean getHidden() + { + return hidden; + } + + public void setHidden(boolean hidden) + { + this.hidden = hidden; + } + + public String getRedirect() + { + return redirect; + } + + public void setRedirect(String redirect) + { + this.redirect = redirect; + } + + public String getComponent() + { + return component; + } + + public void setComponent(String component) + { + this.component = component; + } + + public String getQuery() + { + return query; + } + + public void setQuery(String query) + { + this.query = query; + } + + public Boolean getAlwaysShow() + { + return alwaysShow; + } + + public void setAlwaysShow(Boolean alwaysShow) + { + this.alwaysShow = alwaysShow; + } + + public MetaVo getMeta() + { + return meta; + } + + public void setMeta(MetaVo meta) + { + this.meta = meta; + } + + public List getChildren() + { + return children; + } + + public void setChildren(List children) + { + this.children = children; + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java new file mode 100644 index 0000000..1d6eabe --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java @@ -0,0 +1,76 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import com.ruoyi.system.domain.SysConfig; + +/** + * 参数配置 数据层 + * + * @author #author# + */ +public interface SysConfigMapper +{ + /** + * 查询参数配置信息 + * + * @param config 参数配置信息 + * @return 参数配置信息 + */ + public SysConfig selectConfig(SysConfig config); + + /** + * 通过ID查询配置 + * + * @param configId 参数ID + * @return 参数配置信息 + */ + public SysConfig selectConfigById(Long configId); + + /** + * 查询参数配置列表 + * + * @param config 参数配置信息 + * @return 参数配置集合 + */ + public List selectConfigList(SysConfig config); + + /** + * 根据键名查询参数配置信息 + * + * @param configKey 参数键名 + * @return 参数配置信息 + */ + public SysConfig checkConfigKeyUnique(String configKey); + + /** + * 新增参数配置 + * + * @param config 参数配置信息 + * @return 结果 + */ + public int insertConfig(SysConfig config); + + /** + * 修改参数配置 + * + * @param config 参数配置信息 + * @return 结果 + */ + public int updateConfig(SysConfig config); + + /** + * 删除参数配置 + * + * @param configId 参数ID + * @return 结果 + */ + public int deleteConfigById(Long configId); + + /** + * 批量删除参数信息 + * + * @param configIds 需要删除的参数ID + * @return 结果 + */ + public int deleteConfigByIds(Long[] configIds); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java new file mode 100644 index 0000000..355d7f2 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java @@ -0,0 +1,118 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import org.apache.ibatis.annotations.Param; +import com.ruoyi.common.core.domain.entity.SysDept; + +/** + * 部门管理 数据层 + * + * @author #author# + */ +public interface SysDeptMapper +{ + /** + * 查询部门管理数据 + * + * @param dept 部门信息 + * @return 部门信息集合 + */ + public List selectDeptList(SysDept dept); + + /** + * 根据角色ID查询部门树信息 + * + * @param roleId 角色ID + * @param deptCheckStrictly 部门树选择项是否关联显示 + * @return 选中部门列表 + */ + public List selectDeptListByRoleId(@Param("roleId") Long roleId, @Param("deptCheckStrictly") boolean deptCheckStrictly); + + /** + * 根据部门ID查询信息 + * + * @param deptId 部门ID + * @return 部门信息 + */ + public SysDept selectDeptById(Long deptId); + + /** + * 根据ID查询所有子部门 + * + * @param deptId 部门ID + * @return 部门列表 + */ + public List selectChildrenDeptById(Long deptId); + + /** + * 根据ID查询所有子部门(正常状态) + * + * @param deptId 部门ID + * @return 子部门数 + */ + public int selectNormalChildrenDeptById(Long deptId); + + /** + * 是否存在子节点 + * + * @param deptId 部门ID + * @return 结果 + */ + public int hasChildByDeptId(Long deptId); + + /** + * 查询部门是否存在用户 + * + * @param deptId 部门ID + * @return 结果 + */ + public int checkDeptExistUser(Long deptId); + + /** + * 校验部门名称是否唯一 + * + * @param deptName 部门名称 + * @param parentId 父部门ID + * @return 结果 + */ + public SysDept checkDeptNameUnique(@Param("deptName") String deptName, @Param("parentId") Long parentId); + + /** + * 新增部门信息 + * + * @param dept 部门信息 + * @return 结果 + */ + public int insertDept(SysDept dept); + + /** + * 修改部门信息 + * + * @param dept 部门信息 + * @return 结果 + */ + public int updateDept(SysDept dept); + + /** + * 修改所在部门正常状态 + * + * @param deptIds 部门ID组 + */ + public void updateDeptStatusNormal(Long[] deptIds); + + /** + * 修改子元素关系 + * + * @param depts 子元素 + * @return 结果 + */ + public int updateDeptChildren(@Param("depts") List depts); + + /** + * 删除部门管理信息 + * + * @param deptId 部门ID + * @return 结果 + */ + public int deleteDeptById(Long deptId); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java new file mode 100644 index 0000000..26dc3c7 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java @@ -0,0 +1,95 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import org.apache.ibatis.annotations.Param; +import com.ruoyi.common.core.domain.entity.SysDictData; + +/** + * 字典表 数据层 + * + * @author #author# + */ +public interface SysDictDataMapper +{ + /** + * 根据条件分页查询字典数据 + * + * @param dictData 字典数据信息 + * @return 字典数据集合信息 + */ + public List selectDictDataList(SysDictData dictData); + + /** + * 根据字典类型查询字典数据 + * + * @param dictType 字典类型 + * @return 字典数据集合信息 + */ + public List selectDictDataByType(String dictType); + + /** + * 根据字典类型和字典键值查询字典数据信息 + * + * @param dictType 字典类型 + * @param dictValue 字典键值 + * @return 字典标签 + */ + public String selectDictLabel(@Param("dictType") String dictType, @Param("dictValue") String dictValue); + + /** + * 根据字典数据ID查询信息 + * + * @param dictCode 字典数据ID + * @return 字典数据 + */ + public SysDictData selectDictDataById(Long dictCode); + + /** + * 查询字典数据 + * + * @param dictType 字典类型 + * @return 字典数据 + */ + public int countDictDataByType(String dictType); + + /** + * 通过字典ID删除字典数据信息 + * + * @param dictCode 字典数据ID + * @return 结果 + */ + public int deleteDictDataById(Long dictCode); + + /** + * 批量删除字典数据信息 + * + * @param dictCodes 需要删除的字典数据ID + * @return 结果 + */ + public int deleteDictDataByIds(Long[] dictCodes); + + /** + * 新增字典数据信息 + * + * @param dictData 字典数据信息 + * @return 结果 + */ + public int insertDictData(SysDictData dictData); + + /** + * 修改字典数据信息 + * + * @param dictData 字典数据信息 + * @return 结果 + */ + public int updateDictData(SysDictData dictData); + + /** + * 同步修改字典类型 + * + * @param oldDictType 旧字典类型 + * @param newDictType 新旧字典类型 + * @return 结果 + */ + public int updateDictDataType(@Param("oldDictType") String oldDictType, @Param("newDictType") String newDictType); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java new file mode 100644 index 0000000..ee4469f --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java @@ -0,0 +1,83 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import com.ruoyi.common.core.domain.entity.SysDictType; + +/** + * 字典表 数据层 + * + * @author #author# + */ +public interface SysDictTypeMapper +{ + /** + * 根据条件分页查询字典类型 + * + * @param dictType 字典类型信息 + * @return 字典类型集合信息 + */ + public List selectDictTypeList(SysDictType dictType); + + /** + * 根据所有字典类型 + * + * @return 字典类型集合信息 + */ + public List selectDictTypeAll(); + + /** + * 根据字典类型ID查询信息 + * + * @param dictId 字典类型ID + * @return 字典类型 + */ + public SysDictType selectDictTypeById(Long dictId); + + /** + * 根据字典类型查询信息 + * + * @param dictType 字典类型 + * @return 字典类型 + */ + public SysDictType selectDictTypeByType(String dictType); + + /** + * 通过字典ID删除字典信息 + * + * @param dictId 字典ID + * @return 结果 + */ + public int deleteDictTypeById(Long dictId); + + /** + * 批量删除字典类型信息 + * + * @param dictIds 需要删除的字典ID + * @return 结果 + */ + public int deleteDictTypeByIds(Long[] dictIds); + + /** + * 新增字典类型信息 + * + * @param dictType 字典类型信息 + * @return 结果 + */ + public int insertDictType(SysDictType dictType); + + /** + * 修改字典类型信息 + * + * @param dictType 字典类型信息 + * @return 结果 + */ + public int updateDictType(SysDictType dictType); + + /** + * 校验字典类型称是否唯一 + * + * @param dictType 字典类型 + * @return 结果 + */ + public SysDictType checkDictTypeUnique(String dictType); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java new file mode 100644 index 0000000..de507cd --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java @@ -0,0 +1,42 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import com.ruoyi.system.domain.SysLogininfor; + +/** + * 系统访问日志情况信息 数据层 + * + * @author #author# + */ +public interface SysLogininforMapper +{ + /** + * 新增系统登录日志 + * + * @param logininfor 访问日志对象 + */ + public void insertLogininfor(SysLogininfor logininfor); + + /** + * 查询系统登录日志集合 + * + * @param logininfor 访问日志对象 + * @return 登录记录集合 + */ + public List selectLogininforList(SysLogininfor logininfor); + + /** + * 批量删除系统登录日志 + * + * @param infoIds 需要删除的登录日志ID + * @return 结果 + */ + public int deleteLogininforByIds(Long[] infoIds); + + /** + * 清空系统登录日志 + * + * @return 结果 + */ + public int cleanLogininfor(); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java new file mode 100644 index 0000000..ced9fa0 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java @@ -0,0 +1,125 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import org.apache.ibatis.annotations.Param; +import com.ruoyi.common.core.domain.entity.SysMenu; + +/** + * 菜单表 数据层 + * + * @author #author# + */ +public interface SysMenuMapper +{ + /** + * 查询系统菜单列表 + * + * @param menu 菜单信息 + * @return 菜单列表 + */ + public List selectMenuList(SysMenu menu); + + /** + * 根据用户所有权限 + * + * @return 权限列表 + */ + public List selectMenuPerms(); + + /** + * 根据用户查询系统菜单列表 + * + * @param menu 菜单信息 + * @return 菜单列表 + */ + public List selectMenuListByUserId(SysMenu menu); + + /** + * 根据角色ID查询权限 + * + * @param roleId 角色ID + * @return 权限列表 + */ + public List selectMenuPermsByRoleId(Long roleId); + + /** + * 根据用户ID查询权限 + * + * @param userId 用户ID + * @return 权限列表 + */ + public List selectMenuPermsByUserId(Long userId); + + /** + * 根据用户ID查询菜单 + * + * @return 菜单列表 + */ + public List selectMenuTreeAll(); + + /** + * 根据用户ID查询菜单 + * + * @param userId 用户ID + * @return 菜单列表 + */ + public List selectMenuTreeByUserId(Long userId); + + /** + * 根据角色ID查询菜单树信息 + * + * @param roleId 角色ID + * @param menuCheckStrictly 菜单树选择项是否关联显示 + * @return 选中菜单列表 + */ + public List selectMenuListByRoleId(@Param("roleId") Long roleId, @Param("menuCheckStrictly") boolean menuCheckStrictly); + + /** + * 根据菜单ID查询信息 + * + * @param menuId 菜单ID + * @return 菜单信息 + */ + public SysMenu selectMenuById(Long menuId); + + /** + * 是否存在菜单子节点 + * + * @param menuId 菜单ID + * @return 结果 + */ + public int hasChildByMenuId(Long menuId); + + /** + * 新增菜单信息 + * + * @param menu 菜单信息 + * @return 结果 + */ + public int insertMenu(SysMenu menu); + + /** + * 修改菜单信息 + * + * @param menu 菜单信息 + * @return 结果 + */ + public int updateMenu(SysMenu menu); + + /** + * 删除菜单管理信息 + * + * @param menuId 菜单ID + * @return 结果 + */ + public int deleteMenuById(Long menuId); + + /** + * 校验菜单名称是否唯一 + * + * @param menuName 菜单名称 + * @param parentId 父菜单ID + * @return 结果 + */ + public SysMenu checkMenuNameUnique(@Param("menuName") String menuName, @Param("parentId") Long parentId); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java new file mode 100644 index 0000000..df5ef57 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java @@ -0,0 +1,60 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import com.ruoyi.system.domain.SysNotice; + +/** + * 通知公告表 数据层 + * + * @author #author# + */ +public interface SysNoticeMapper +{ + /** + * 查询公告信息 + * + * @param noticeId 公告ID + * @return 公告信息 + */ + public SysNotice selectNoticeById(Long noticeId); + + /** + * 查询公告列表 + * + * @param notice 公告信息 + * @return 公告集合 + */ + public List selectNoticeList(SysNotice notice); + + /** + * 新增公告 + * + * @param notice 公告信息 + * @return 结果 + */ + public int insertNotice(SysNotice notice); + + /** + * 修改公告 + * + * @param notice 公告信息 + * @return 结果 + */ + public int updateNotice(SysNotice notice); + + /** + * 批量删除公告 + * + * @param noticeId 公告ID + * @return 结果 + */ + public int deleteNoticeById(Long noticeId); + + /** + * 批量删除公告信息 + * + * @param noticeIds 需要删除的公告ID + * @return 结果 + */ + public int deleteNoticeByIds(Long[] noticeIds); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java new file mode 100644 index 0000000..40cce80 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java @@ -0,0 +1,48 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import com.ruoyi.system.domain.SysOperLog; + +/** + * 操作日志 数据层 + * + * @author #author# + */ +public interface SysOperLogMapper +{ + /** + * 新增操作日志 + * + * @param operLog 操作日志对象 + */ + public void insertOperlog(SysOperLog operLog); + + /** + * 查询系统操作日志集合 + * + * @param operLog 操作日志对象 + * @return 操作日志集合 + */ + public List selectOperLogList(SysOperLog operLog); + + /** + * 批量删除系统操作日志 + * + * @param operIds 需要删除的操作日志ID + * @return 结果 + */ + public int deleteOperLogByIds(Long[] operIds); + + /** + * 查询操作日志详细 + * + * @param operId 操作ID + * @return 操作日志对象 + */ + public SysOperLog selectOperLogById(Long operId); + + /** + * 清空操作日志 + */ + public void cleanOperLog(); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java new file mode 100644 index 0000000..04912fb --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java @@ -0,0 +1,99 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import com.ruoyi.system.domain.SysPost; + +/** + * 岗位信息 数据层 + * + * @author #author# + */ +public interface SysPostMapper +{ + /** + * 查询岗位数据集合 + * + * @param post 岗位信息 + * @return 岗位数据集合 + */ + public List selectPostList(SysPost post); + + /** + * 查询所有岗位 + * + * @return 岗位列表 + */ + public List selectPostAll(); + + /** + * 通过岗位ID查询岗位信息 + * + * @param postId 岗位ID + * @return 角色对象信息 + */ + public SysPost selectPostById(Long postId); + + /** + * 根据用户ID获取岗位选择框列表 + * + * @param userId 用户ID + * @return 选中岗位ID列表 + */ + public List selectPostListByUserId(Long userId); + + /** + * 查询用户所属岗位组 + * + * @param userName 用户名 + * @return 结果 + */ + public List selectPostsByUserName(String userName); + + /** + * 删除岗位信息 + * + * @param postId 岗位ID + * @return 结果 + */ + public int deletePostById(Long postId); + + /** + * 批量删除岗位信息 + * + * @param postIds 需要删除的岗位ID + * @return 结果 + */ + public int deletePostByIds(Long[] postIds); + + /** + * 修改岗位信息 + * + * @param post 岗位信息 + * @return 结果 + */ + public int updatePost(SysPost post); + + /** + * 新增岗位信息 + * + * @param post 岗位信息 + * @return 结果 + */ + public int insertPost(SysPost post); + + /** + * 校验岗位名称 + * + * @param postName 岗位名称 + * @return 结果 + */ + public SysPost checkPostNameUnique(String postName); + + /** + * 校验岗位编码 + * + * @param postCode 岗位编码 + * @return 结果 + */ + public SysPost checkPostCodeUnique(String postCode); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java new file mode 100644 index 0000000..13d5eb3 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java @@ -0,0 +1,44 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import com.ruoyi.system.domain.SysRoleDept; + +/** + * 角色与部门关联表 数据层 + * + * @author #author# + */ +public interface SysRoleDeptMapper +{ + /** + * 通过角色ID删除角色和部门关联 + * + * @param roleId 角色ID + * @return 结果 + */ + public int deleteRoleDeptByRoleId(Long roleId); + + /** + * 批量删除角色部门关联信息 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteRoleDept(Long[] ids); + + /** + * 查询部门使用数量 + * + * @param deptId 部门ID + * @return 结果 + */ + public int selectCountRoleDeptByDeptId(Long deptId); + + /** + * 批量新增角色部门信息 + * + * @param roleDeptList 角色部门列表 + * @return 结果 + */ + public int batchRoleDept(List roleDeptList); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java new file mode 100644 index 0000000..64d0719 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java @@ -0,0 +1,107 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import com.ruoyi.common.core.domain.entity.SysRole; + +/** + * 角色表 数据层 + * + * @author #author# + */ +public interface SysRoleMapper +{ + /** + * 根据条件分页查询角色数据 + * + * @param role 角色信息 + * @return 角色数据集合信息 + */ + public List selectRoleList(SysRole role); + + /** + * 根据用户ID查询角色 + * + * @param userId 用户ID + * @return 角色列表 + */ + public List selectRolePermissionByUserId(Long userId); + + /** + * 查询所有角色 + * + * @return 角色列表 + */ + public List selectRoleAll(); + + /** + * 根据用户ID获取角色选择框列表 + * + * @param userId 用户ID + * @return 选中角色ID列表 + */ + public List selectRoleListByUserId(Long userId); + + /** + * 通过角色ID查询角色 + * + * @param roleId 角色ID + * @return 角色对象信息 + */ + public SysRole selectRoleById(Long roleId); + + /** + * 根据用户ID查询角色 + * + * @param userName 用户名 + * @return 角色列表 + */ + public List selectRolesByUserName(String userName); + + /** + * 校验角色名称是否唯一 + * + * @param roleName 角色名称 + * @return 角色信息 + */ + public SysRole checkRoleNameUnique(String roleName); + + /** + * 校验角色权限是否唯一 + * + * @param roleKey 角色权限 + * @return 角色信息 + */ + public SysRole checkRoleKeyUnique(String roleKey); + + /** + * 修改角色信息 + * + * @param role 角色信息 + * @return 结果 + */ + public int updateRole(SysRole role); + + /** + * 新增角色信息 + * + * @param role 角色信息 + * @return 结果 + */ + public int insertRole(SysRole role); + + /** + * 通过角色ID删除角色 + * + * @param roleId 角色ID + * @return 结果 + */ + public int deleteRoleById(Long roleId); + + /** + * 批量删除角色信息 + * + * @param roleIds 需要删除的角色ID + * @return 结果 + */ + public int deleteRoleByIds(Long[] roleIds); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java new file mode 100644 index 0000000..6ccf87d --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java @@ -0,0 +1,44 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import com.ruoyi.system.domain.SysRoleMenu; + +/** + * 角色与菜单关联表 数据层 + * + * @author #author# + */ +public interface SysRoleMenuMapper +{ + /** + * 查询菜单使用数量 + * + * @param menuId 菜单ID + * @return 结果 + */ + public int checkMenuExistRole(Long menuId); + + /** + * 通过角色ID删除角色和菜单关联 + * + * @param roleId 角色ID + * @return 结果 + */ + public int deleteRoleMenuByRoleId(Long roleId); + + /** + * 批量删除角色菜单关联信息 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteRoleMenu(Long[] ids); + + /** + * 批量新增角色菜单信息 + * + * @param roleMenuList 角色菜单列表 + * @return 结果 + */ + public int batchRoleMenu(List roleMenuList); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java new file mode 100644 index 0000000..e1fd9ff --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java @@ -0,0 +1,127 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import org.apache.ibatis.annotations.Param; +import com.ruoyi.common.core.domain.entity.SysUser; + +/** + * 用户表 数据层 + * + * @author #author# + */ +public interface SysUserMapper +{ + /** + * 根据条件分页查询用户列表 + * + * @param sysUser 用户信息 + * @return 用户信息集合信息 + */ + public List selectUserList(SysUser sysUser); + + /** + * 根据条件分页查询已配用户角色列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + public List selectAllocatedList(SysUser user); + + /** + * 根据条件分页查询未分配用户角色列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + public List selectUnallocatedList(SysUser user); + + /** + * 通过用户名查询用户 + * + * @param userName 用户名 + * @return 用户对象信息 + */ + public SysUser selectUserByUserName(String userName); + + /** + * 通过用户ID查询用户 + * + * @param userId 用户ID + * @return 用户对象信息 + */ + public SysUser selectUserById(Long userId); + + /** + * 新增用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + public int insertUser(SysUser user); + + /** + * 修改用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + public int updateUser(SysUser user); + + /** + * 修改用户头像 + * + * @param userName 用户名 + * @param avatar 头像地址 + * @return 结果 + */ + public int updateUserAvatar(@Param("userName") String userName, @Param("avatar") String avatar); + + /** + * 重置用户密码 + * + * @param userName 用户名 + * @param password 密码 + * @return 结果 + */ + public int resetUserPwd(@Param("userName") String userName, @Param("password") String password); + + /** + * 通过用户ID删除用户 + * + * @param userId 用户ID + * @return 结果 + */ + public int deleteUserById(Long userId); + + /** + * 批量删除用户信息 + * + * @param userIds 需要删除的用户ID + * @return 结果 + */ + public int deleteUserByIds(Long[] userIds); + + /** + * 校验用户名称是否唯一 + * + * @param userName 用户名称 + * @return 结果 + */ + public SysUser checkUserNameUnique(String userName); + + /** + * 校验手机号码是否唯一 + * + * @param phonenumber 手机号码 + * @return 结果 + */ + public SysUser checkPhoneUnique(String phonenumber); + + /** + * 校验email是否唯一 + * + * @param email 用户邮箱 + * @return 结果 + */ + public SysUser checkEmailUnique(String email); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java new file mode 100644 index 0000000..650e8e6 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java @@ -0,0 +1,44 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import com.ruoyi.system.domain.SysUserPost; + +/** + * 用户与岗位关联表 数据层 + * + * @author #author# + */ +public interface SysUserPostMapper +{ + /** + * 通过用户ID删除用户和岗位关联 + * + * @param userId 用户ID + * @return 结果 + */ + public int deleteUserPostByUserId(Long userId); + + /** + * 通过岗位ID查询岗位使用数量 + * + * @param postId 岗位ID + * @return 结果 + */ + public int countUserPostById(Long postId); + + /** + * 批量删除用户和岗位关联 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteUserPost(Long[] ids); + + /** + * 批量新增用户岗位信息 + * + * @param userPostList 用户角色列表 + * @return 结果 + */ + public int batchUserPost(List userPostList); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java new file mode 100644 index 0000000..d38b9ae --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java @@ -0,0 +1,62 @@ +package com.ruoyi.system.mapper; + +import java.util.List; +import org.apache.ibatis.annotations.Param; +import com.ruoyi.system.domain.SysUserRole; + +/** + * 用户与角色关联表 数据层 + * + * @author #author# + */ +public interface SysUserRoleMapper +{ + /** + * 通过用户ID删除用户和角色关联 + * + * @param userId 用户ID + * @return 结果 + */ + public int deleteUserRoleByUserId(Long userId); + + /** + * 批量删除用户和角色关联 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + public int deleteUserRole(Long[] ids); + + /** + * 通过角色ID查询角色使用数量 + * + * @param roleId 角色ID + * @return 结果 + */ + public int countUserRoleByRoleId(Long roleId); + + /** + * 批量新增用户角色信息 + * + * @param userRoleList 用户角色列表 + * @return 结果 + */ + public int batchUserRole(List userRoleList); + + /** + * 删除用户和角色关联信息 + * + * @param userRole 用户和角色关联信息 + * @return 结果 + */ + public int deleteUserRoleInfo(SysUserRole userRole); + + /** + * 批量取消授权用户角色 + * + * @param roleId 角色ID + * @param userIds 需要删除的用户数据ID + * @return 结果 + */ + public int deleteUserRoleInfos(@Param("roleId") Long roleId, @Param("userIds") Long[] userIds); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java new file mode 100644 index 0000000..0ee9c07 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java @@ -0,0 +1,89 @@ +package com.ruoyi.system.service; + +import java.util.List; +import com.ruoyi.system.domain.SysConfig; + +/** + * 参数配置 服务层 + * + * @author #author# + */ +public interface ISysConfigService +{ + /** + * 查询参数配置信息 + * + * @param configId 参数配置ID + * @return 参数配置信息 + */ + public SysConfig selectConfigById(Long configId); + + /** + * 根据键名查询参数配置信息 + * + * @param configKey 参数键名 + * @return 参数键值 + */ + public String selectConfigByKey(String configKey); + + /** + * 获取验证码开关 + * + * @return true开启,false关闭 + */ + public boolean selectCaptchaEnabled(); + + /** + * 查询参数配置列表 + * + * @param config 参数配置信息 + * @return 参数配置集合 + */ + public List selectConfigList(SysConfig config); + + /** + * 新增参数配置 + * + * @param config 参数配置信息 + * @return 结果 + */ + public int insertConfig(SysConfig config); + + /** + * 修改参数配置 + * + * @param config 参数配置信息 + * @return 结果 + */ + public int updateConfig(SysConfig config); + + /** + * 批量删除参数信息 + * + * @param configIds 需要删除的参数ID + */ + public void deleteConfigByIds(Long[] configIds); + + /** + * 加载参数缓存数据 + */ + public void loadingConfigCache(); + + /** + * 清空参数缓存数据 + */ + public void clearConfigCache(); + + /** + * 重置参数缓存数据 + */ + public void resetConfigCache(); + + /** + * 校验参数键名是否唯一 + * + * @param config 参数信息 + * @return 结果 + */ + public String checkConfigKeyUnique(SysConfig config); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java new file mode 100644 index 0000000..42f7cbe --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java @@ -0,0 +1,124 @@ +package com.ruoyi.system.service; + +import java.util.List; +import com.ruoyi.common.core.domain.TreeSelect; +import com.ruoyi.common.core.domain.entity.SysDept; + +/** + * 部门管理 服务层 + * + * @author #author# + */ +public interface ISysDeptService +{ + /** + * 查询部门管理数据 + * + * @param dept 部门信息 + * @return 部门信息集合 + */ + public List selectDeptList(SysDept dept); + + /** + * 查询部门树结构信息 + * + * @param dept 部门信息 + * @return 部门树信息集合 + */ + public List selectDeptTreeList(SysDept dept); + + /** + * 构建前端所需要树结构 + * + * @param depts 部门列表 + * @return 树结构列表 + */ + public List buildDeptTree(List depts); + + /** + * 构建前端所需要下拉树结构 + * + * @param depts 部门列表 + * @return 下拉树结构列表 + */ + public List buildDeptTreeSelect(List depts); + + /** + * 根据角色ID查询部门树信息 + * + * @param roleId 角色ID + * @return 选中部门列表 + */ + public List selectDeptListByRoleId(Long roleId); + + /** + * 根据部门ID查询信息 + * + * @param deptId 部门ID + * @return 部门信息 + */ + public SysDept selectDeptById(Long deptId); + + /** + * 根据ID查询所有子部门(正常状态) + * + * @param deptId 部门ID + * @return 子部门数 + */ + public int selectNormalChildrenDeptById(Long deptId); + + /** + * 是否存在部门子节点 + * + * @param deptId 部门ID + * @return 结果 + */ + public boolean hasChildByDeptId(Long deptId); + + /** + * 查询部门是否存在用户 + * + * @param deptId 部门ID + * @return 结果 true 存在 false 不存在 + */ + public boolean checkDeptExistUser(Long deptId); + + /** + * 校验部门名称是否唯一 + * + * @param dept 部门信息 + * @return 结果 + */ + public String checkDeptNameUnique(SysDept dept); + + /** + * 校验部门是否有数据权限 + * + * @param deptId 部门id + */ + public void checkDeptDataScope(Long deptId); + + /** + * 新增保存部门信息 + * + * @param dept 部门信息 + * @return 结果 + */ + public int insertDept(SysDept dept); + + /** + * 修改保存部门信息 + * + * @param dept 部门信息 + * @return 结果 + */ + public int updateDept(SysDept dept); + + /** + * 删除部门管理信息 + * + * @param deptId 部门ID + * @return 结果 + */ + public int deleteDeptById(Long deptId); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java new file mode 100644 index 0000000..edc85f9 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java @@ -0,0 +1,60 @@ +package com.ruoyi.system.service; + +import java.util.List; +import com.ruoyi.common.core.domain.entity.SysDictData; + +/** + * 字典 业务层 + * + * @author #author# + */ +public interface ISysDictDataService +{ + /** + * 根据条件分页查询字典数据 + * + * @param dictData 字典数据信息 + * @return 字典数据集合信息 + */ + public List selectDictDataList(SysDictData dictData); + + /** + * 根据字典类型和字典键值查询字典数据信息 + * + * @param dictType 字典类型 + * @param dictValue 字典键值 + * @return 字典标签 + */ + public String selectDictLabel(String dictType, String dictValue); + + /** + * 根据字典数据ID查询信息 + * + * @param dictCode 字典数据ID + * @return 字典数据 + */ + public SysDictData selectDictDataById(Long dictCode); + + /** + * 批量删除字典数据信息 + * + * @param dictCodes 需要删除的字典数据ID + */ + public void deleteDictDataByIds(Long[] dictCodes); + + /** + * 新增保存字典数据信息 + * + * @param dictData 字典数据信息 + * @return 结果 + */ + public int insertDictData(SysDictData dictData); + + /** + * 修改保存字典数据信息 + * + * @param dictData 字典数据信息 + * @return 结果 + */ + public int updateDictData(SysDictData dictData); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java new file mode 100644 index 0000000..92b97bf --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java @@ -0,0 +1,98 @@ +package com.ruoyi.system.service; + +import java.util.List; +import com.ruoyi.common.core.domain.entity.SysDictData; +import com.ruoyi.common.core.domain.entity.SysDictType; + +/** + * 字典 业务层 + * + * @author #author# + */ +public interface ISysDictTypeService +{ + /** + * 根据条件分页查询字典类型 + * + * @param dictType 字典类型信息 + * @return 字典类型集合信息 + */ + public List selectDictTypeList(SysDictType dictType); + + /** + * 根据所有字典类型 + * + * @return 字典类型集合信息 + */ + public List selectDictTypeAll(); + + /** + * 根据字典类型查询字典数据 + * + * @param dictType 字典类型 + * @return 字典数据集合信息 + */ + public List selectDictDataByType(String dictType); + + /** + * 根据字典类型ID查询信息 + * + * @param dictId 字典类型ID + * @return 字典类型 + */ + public SysDictType selectDictTypeById(Long dictId); + + /** + * 根据字典类型查询信息 + * + * @param dictType 字典类型 + * @return 字典类型 + */ + public SysDictType selectDictTypeByType(String dictType); + + /** + * 批量删除字典信息 + * + * @param dictIds 需要删除的字典ID + */ + public void deleteDictTypeByIds(Long[] dictIds); + + /** + * 加载字典缓存数据 + */ + public void loadingDictCache(); + + /** + * 清空字典缓存数据 + */ + public void clearDictCache(); + + /** + * 重置字典缓存数据 + */ + public void resetDictCache(); + + /** + * 新增保存字典类型信息 + * + * @param dictType 字典类型信息 + * @return 结果 + */ + public int insertDictType(SysDictType dictType); + + /** + * 修改保存字典类型信息 + * + * @param dictType 字典类型信息 + * @return 结果 + */ + public int updateDictType(SysDictType dictType); + + /** + * 校验字典类型称是否唯一 + * + * @param dictType 字典类型 + * @return 结果 + */ + public String checkDictTypeUnique(SysDictType dictType); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java new file mode 100644 index 0000000..dd3786c --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java @@ -0,0 +1,40 @@ +package com.ruoyi.system.service; + +import java.util.List; +import com.ruoyi.system.domain.SysLogininfor; + +/** + * 系统访问日志情况信息 服务层 + * + * @author #author# + */ +public interface ISysLogininforService +{ + /** + * 新增系统登录日志 + * + * @param logininfor 访问日志对象 + */ + public void insertLogininfor(SysLogininfor logininfor); + + /** + * 查询系统登录日志集合 + * + * @param logininfor 访问日志对象 + * @return 登录记录集合 + */ + public List selectLogininforList(SysLogininfor logininfor); + + /** + * 批量删除系统登录日志 + * + * @param infoIds 需要删除的登录日志ID + * @return 结果 + */ + public int deleteLogininforByIds(Long[] infoIds); + + /** + * 清空系统登录日志 + */ + public void cleanLogininfor(); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java new file mode 100644 index 0000000..1407df4 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java @@ -0,0 +1,144 @@ +package com.ruoyi.system.service; + +import java.util.List; +import java.util.Set; +import com.ruoyi.common.core.domain.TreeSelect; +import com.ruoyi.common.core.domain.entity.SysMenu; +import com.ruoyi.system.domain.vo.RouterVo; + +/** + * 菜单 业务层 + * + * @author #author# + */ +public interface ISysMenuService +{ + /** + * 根据用户查询系统菜单列表 + * + * @param userId 用户ID + * @return 菜单列表 + */ + public List selectMenuList(Long userId); + + /** + * 根据用户查询系统菜单列表 + * + * @param menu 菜单信息 + * @param userId 用户ID + * @return 菜单列表 + */ + public List selectMenuList(SysMenu menu, Long userId); + + /** + * 根据用户ID查询权限 + * + * @param userId 用户ID + * @return 权限列表 + */ + public Set selectMenuPermsByUserId(Long userId); + + /** + * 根据角色ID查询权限 + * + * @param roleId 角色ID + * @return 权限列表 + */ + public Set selectMenuPermsByRoleId(Long roleId); + + /** + * 根据用户ID查询菜单树信息 + * + * @param userId 用户ID + * @return 菜单列表 + */ + public List selectMenuTreeByUserId(Long userId); + + /** + * 根据角色ID查询菜单树信息 + * + * @param roleId 角色ID + * @return 选中菜单列表 + */ + public List selectMenuListByRoleId(Long roleId); + + /** + * 构建前端路由所需要的菜单 + * + * @param menus 菜单列表 + * @return 路由列表 + */ + public List buildMenus(List menus); + + /** + * 构建前端所需要树结构 + * + * @param menus 菜单列表 + * @return 树结构列表 + */ + public List buildMenuTree(List menus); + + /** + * 构建前端所需要下拉树结构 + * + * @param menus 菜单列表 + * @return 下拉树结构列表 + */ + public List buildMenuTreeSelect(List menus); + + /** + * 根据菜单ID查询信息 + * + * @param menuId 菜单ID + * @return 菜单信息 + */ + public SysMenu selectMenuById(Long menuId); + + /** + * 是否存在菜单子节点 + * + * @param menuId 菜单ID + * @return 结果 true 存在 false 不存在 + */ + public boolean hasChildByMenuId(Long menuId); + + /** + * 查询菜单是否存在角色 + * + * @param menuId 菜单ID + * @return 结果 true 存在 false 不存在 + */ + public boolean checkMenuExistRole(Long menuId); + + /** + * 新增保存菜单信息 + * + * @param menu 菜单信息 + * @return 结果 + */ + public int insertMenu(SysMenu menu); + + /** + * 修改保存菜单信息 + * + * @param menu 菜单信息 + * @return 结果 + */ + public int updateMenu(SysMenu menu); + + /** + * 删除菜单管理信息 + * + * @param menuId 菜单ID + * @return 结果 + */ + public int deleteMenuById(Long menuId); + + /** + * 校验菜单名称是否唯一 + * + * @param menu 菜单信息 + * @return 结果 + */ + public String checkMenuNameUnique(SysMenu menu); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java new file mode 100644 index 0000000..01c9b7a --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java @@ -0,0 +1,60 @@ +package com.ruoyi.system.service; + +import java.util.List; +import com.ruoyi.system.domain.SysNotice; + +/** + * 公告 服务层 + * + * @author #author# + */ +public interface ISysNoticeService +{ + /** + * 查询公告信息 + * + * @param noticeId 公告ID + * @return 公告信息 + */ + public SysNotice selectNoticeById(Long noticeId); + + /** + * 查询公告列表 + * + * @param notice 公告信息 + * @return 公告集合 + */ + public List selectNoticeList(SysNotice notice); + + /** + * 新增公告 + * + * @param notice 公告信息 + * @return 结果 + */ + public int insertNotice(SysNotice notice); + + /** + * 修改公告 + * + * @param notice 公告信息 + * @return 结果 + */ + public int updateNotice(SysNotice notice); + + /** + * 删除公告信息 + * + * @param noticeId 公告ID + * @return 结果 + */ + public int deleteNoticeById(Long noticeId); + + /** + * 批量删除公告信息 + * + * @param noticeIds 需要删除的公告ID + * @return 结果 + */ + public int deleteNoticeByIds(Long[] noticeIds); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java new file mode 100644 index 0000000..f438184 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java @@ -0,0 +1,48 @@ +package com.ruoyi.system.service; + +import java.util.List; +import com.ruoyi.system.domain.SysOperLog; + +/** + * 操作日志 服务层 + * + * @author #author# + */ +public interface ISysOperLogService +{ + /** + * 新增操作日志 + * + * @param operLog 操作日志对象 + */ + public void insertOperlog(SysOperLog operLog); + + /** + * 查询系统操作日志集合 + * + * @param operLog 操作日志对象 + * @return 操作日志集合 + */ + public List selectOperLogList(SysOperLog operLog); + + /** + * 批量删除系统操作日志 + * + * @param operIds 需要删除的操作日志ID + * @return 结果 + */ + public int deleteOperLogByIds(Long[] operIds); + + /** + * 查询操作日志详细 + * + * @param operId 操作ID + * @return 操作日志对象 + */ + public SysOperLog selectOperLogById(Long operId); + + /** + * 清空操作日志 + */ + public void cleanOperLog(); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java new file mode 100644 index 0000000..296a85c --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java @@ -0,0 +1,99 @@ +package com.ruoyi.system.service; + +import java.util.List; +import com.ruoyi.system.domain.SysPost; + +/** + * 岗位信息 服务层 + * + * @author #author# + */ +public interface ISysPostService +{ + /** + * 查询岗位信息集合 + * + * @param post 岗位信息 + * @return 岗位列表 + */ + public List selectPostList(SysPost post); + + /** + * 查询所有岗位 + * + * @return 岗位列表 + */ + public List selectPostAll(); + + /** + * 通过岗位ID查询岗位信息 + * + * @param postId 岗位ID + * @return 角色对象信息 + */ + public SysPost selectPostById(Long postId); + + /** + * 根据用户ID获取岗位选择框列表 + * + * @param userId 用户ID + * @return 选中岗位ID列表 + */ + public List selectPostListByUserId(Long userId); + + /** + * 校验岗位名称 + * + * @param post 岗位信息 + * @return 结果 + */ + public String checkPostNameUnique(SysPost post); + + /** + * 校验岗位编码 + * + * @param post 岗位信息 + * @return 结果 + */ + public String checkPostCodeUnique(SysPost post); + + /** + * 通过岗位ID查询岗位使用数量 + * + * @param postId 岗位ID + * @return 结果 + */ + public int countUserPostById(Long postId); + + /** + * 删除岗位信息 + * + * @param postId 岗位ID + * @return 结果 + */ + public int deletePostById(Long postId); + + /** + * 批量删除岗位信息 + * + * @param postIds 需要删除的岗位ID + * @return 结果 + */ + public int deletePostByIds(Long[] postIds); + + /** + * 新增保存岗位信息 + * + * @param post 岗位信息 + * @return 结果 + */ + public int insertPost(SysPost post); + + /** + * 修改保存岗位信息 + * + * @param post 岗位信息 + * @return 结果 + */ + public int updatePost(SysPost post); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java new file mode 100644 index 0000000..0db73d4 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java @@ -0,0 +1,173 @@ +package com.ruoyi.system.service; + +import java.util.List; +import java.util.Set; +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.system.domain.SysUserRole; + +/** + * 角色业务层 + * + * @author #author# + */ +public interface ISysRoleService +{ + /** + * 根据条件分页查询角色数据 + * + * @param role 角色信息 + * @return 角色数据集合信息 + */ + public List selectRoleList(SysRole role); + + /** + * 根据用户ID查询角色列表 + * + * @param userId 用户ID + * @return 角色列表 + */ + public List selectRolesByUserId(Long userId); + + /** + * 根据用户ID查询角色权限 + * + * @param userId 用户ID + * @return 权限列表 + */ + public Set selectRolePermissionByUserId(Long userId); + + /** + * 查询所有角色 + * + * @return 角色列表 + */ + public List selectRoleAll(); + + /** + * 根据用户ID获取角色选择框列表 + * + * @param userId 用户ID + * @return 选中角色ID列表 + */ + public List selectRoleListByUserId(Long userId); + + /** + * 通过角色ID查询角色 + * + * @param roleId 角色ID + * @return 角色对象信息 + */ + public SysRole selectRoleById(Long roleId); + + /** + * 校验角色名称是否唯一 + * + * @param role 角色信息 + * @return 结果 + */ + public String checkRoleNameUnique(SysRole role); + + /** + * 校验角色权限是否唯一 + * + * @param role 角色信息 + * @return 结果 + */ + public String checkRoleKeyUnique(SysRole role); + + /** + * 校验角色是否允许操作 + * + * @param role 角色信息 + */ + public void checkRoleAllowed(SysRole role); + + /** + * 校验角色是否有数据权限 + * + * @param roleId 角色id + */ + public void checkRoleDataScope(Long roleId); + + /** + * 通过角色ID查询角色使用数量 + * + * @param roleId 角色ID + * @return 结果 + */ + public int countUserRoleByRoleId(Long roleId); + + /** + * 新增保存角色信息 + * + * @param role 角色信息 + * @return 结果 + */ + public int insertRole(SysRole role); + + /** + * 修改保存角色信息 + * + * @param role 角色信息 + * @return 结果 + */ + public int updateRole(SysRole role); + + /** + * 修改角色状态 + * + * @param role 角色信息 + * @return 结果 + */ + public int updateRoleStatus(SysRole role); + + /** + * 修改数据权限信息 + * + * @param role 角色信息 + * @return 结果 + */ + public int authDataScope(SysRole role); + + /** + * 通过角色ID删除角色 + * + * @param roleId 角色ID + * @return 结果 + */ + public int deleteRoleById(Long roleId); + + /** + * 批量删除角色信息 + * + * @param roleIds 需要删除的角色ID + * @return 结果 + */ + public int deleteRoleByIds(Long[] roleIds); + + /** + * 取消授权用户角色 + * + * @param userRole 用户和角色关联信息 + * @return 结果 + */ + public int deleteAuthUser(SysUserRole userRole); + + /** + * 批量取消授权用户角色 + * + * @param roleId 角色ID + * @param userIds 需要取消授权的用户数据ID + * @return 结果 + */ + public int deleteAuthUsers(Long roleId, Long[] userIds); + + /** + * 批量选择授权用户角色 + * + * @param roleId 角色ID + * @param userIds 需要删除的用户数据ID + * @return 结果 + */ + public int insertAuthUsers(Long roleId, Long[] userIds); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserOnlineService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserOnlineService.java new file mode 100644 index 0000000..9d60a6e --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserOnlineService.java @@ -0,0 +1,48 @@ +package com.ruoyi.system.service; + +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.system.domain.SysUserOnline; + +/** + * 在线用户 服务层 + * + * @author #author# + */ +public interface ISysUserOnlineService +{ + /** + * 通过登录地址查询信息 + * + * @param ipaddr 登录地址 + * @param user 用户信息 + * @return 在线用户信息 + */ + public SysUserOnline selectOnlineByIpaddr(String ipaddr, LoginUser user); + + /** + * 通过用户名称查询信息 + * + * @param userName 用户名称 + * @param user 用户信息 + * @return 在线用户信息 + */ + public SysUserOnline selectOnlineByUserName(String userName, LoginUser user); + + /** + * 通过登录地址/用户名称查询信息 + * + * @param ipaddr 登录地址 + * @param userName 用户名称 + * @param user 用户信息 + * @return 在线用户信息 + */ + public SysUserOnline selectOnlineByInfo(String ipaddr, String userName, LoginUser user); + + /** + * 设置在线用户信息 + * + * @param user 用户信息 + * @return 在线用户 + */ + public SysUserOnline loginUserToUserOnline(LoginUser user); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java new file mode 100644 index 0000000..fb777b8 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java @@ -0,0 +1,206 @@ +package com.ruoyi.system.service; + +import java.util.List; +import com.ruoyi.common.core.domain.entity.SysUser; + +/** + * 用户 业务层 + * + * @author #author# + */ +public interface ISysUserService +{ + /** + * 根据条件分页查询用户列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + public List selectUserList(SysUser user); + + /** + * 根据条件分页查询已分配用户角色列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + public List selectAllocatedList(SysUser user); + + /** + * 根据条件分页查询未分配用户角色列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + public List selectUnallocatedList(SysUser user); + + /** + * 通过用户名查询用户 + * + * @param userName 用户名 + * @return 用户对象信息 + */ + public SysUser selectUserByUserName(String userName); + + /** + * 通过用户ID查询用户 + * + * @param userId 用户ID + * @return 用户对象信息 + */ + public SysUser selectUserById(Long userId); + + /** + * 根据用户ID查询用户所属角色组 + * + * @param userName 用户名 + * @return 结果 + */ + public String selectUserRoleGroup(String userName); + + /** + * 根据用户ID查询用户所属岗位组 + * + * @param userName 用户名 + * @return 结果 + */ + public String selectUserPostGroup(String userName); + + /** + * 校验用户名称是否唯一 + * + * @param user 用户信息 + * @return 结果 + */ + public String checkUserNameUnique(SysUser user); + + /** + * 校验手机号码是否唯一 + * + * @param user 用户信息 + * @return 结果 + */ + public String checkPhoneUnique(SysUser user); + + /** + * 校验email是否唯一 + * + * @param user 用户信息 + * @return 结果 + */ + public String checkEmailUnique(SysUser user); + + /** + * 校验用户是否允许操作 + * + * @param user 用户信息 + */ + public void checkUserAllowed(SysUser user); + + /** + * 校验用户是否有数据权限 + * + * @param userId 用户id + */ + public void checkUserDataScope(Long userId); + + /** + * 新增用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + public int insertUser(SysUser user); + + /** + * 注册用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + public boolean registerUser(SysUser user); + + /** + * 修改用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + public int updateUser(SysUser user); + + /** + * 用户授权角色 + * + * @param userId 用户ID + * @param roleIds 角色组 + */ + public void insertUserAuth(Long userId, Long[] roleIds); + + /** + * 修改用户状态 + * + * @param user 用户信息 + * @return 结果 + */ + public int updateUserStatus(SysUser user); + + /** + * 修改用户基本信息 + * + * @param user 用户信息 + * @return 结果 + */ + public int updateUserProfile(SysUser user); + + /** + * 修改用户头像 + * + * @param userName 用户名 + * @param avatar 头像地址 + * @return 结果 + */ + public boolean updateUserAvatar(String userName, String avatar); + + /** + * 重置用户密码 + * + * @param user 用户信息 + * @return 结果 + */ + public int resetPwd(SysUser user); + + /** + * 重置用户密码 + * + * @param userName 用户名 + * @param password 密码 + * @return 结果 + */ + public int resetUserPwd(String userName, String password); + + /** + * 通过用户ID删除用户 + * + * @param userId 用户ID + * @return 结果 + */ + public int deleteUserById(Long userId); + + /** + * 批量删除用户信息 + * + * @param userIds 需要删除的用户ID + * @return 结果 + */ + public int deleteUserByIds(Long[] userIds); + + /** + * 导入用户数据 + * + * @param userList 用户数据列表 + * @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据 + * @param operName 操作用户 + * @return 结果 + */ + public String importUser(List userList, Boolean isUpdateSupport, String operName); +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java new file mode 100644 index 0000000..bc76d04 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java @@ -0,0 +1,232 @@ +package com.ruoyi.system.service.impl; + +import java.util.Collection; +import java.util.List; +import javax.annotation.PostConstruct; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.common.annotation.DataSource; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.core.text.Convert; +import com.ruoyi.common.enums.DataSourceType; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.system.domain.SysConfig; +import com.ruoyi.system.mapper.SysConfigMapper; +import com.ruoyi.system.service.ISysConfigService; + +/** + * 参数配置 服务层实现 + * + * @author #author# + */ +@Service +public class SysConfigServiceImpl implements ISysConfigService +{ + @Autowired + private SysConfigMapper configMapper; + + @Autowired + private RedisCache redisCache; + + /** + * 项目启动时,初始化参数到缓存 + */ + @PostConstruct + public void init() + { + loadingConfigCache(); + } + + /** + * 查询参数配置信息 + * + * @param configId 参数配置ID + * @return 参数配置信息 + */ + @Override + @DataSource(DataSourceType.MASTER) + public SysConfig selectConfigById(Long configId) + { + SysConfig config = new SysConfig(); + config.setConfigId(configId); + return configMapper.selectConfig(config); + } + + /** + * 根据键名查询参数配置信息 + * + * @param configKey 参数key + * @return 参数键值 + */ + @Override + public String selectConfigByKey(String configKey) + { + String configValue = Convert.toStr(redisCache.getCacheObject(getCacheKey(configKey))); + if (StringUtils.isNotEmpty(configValue)) + { + return configValue; + } + SysConfig config = new SysConfig(); + config.setConfigKey(configKey); + SysConfig retConfig = configMapper.selectConfig(config); + if (StringUtils.isNotNull(retConfig)) + { + redisCache.setCacheObject(getCacheKey(configKey), retConfig.getConfigValue()); + return retConfig.getConfigValue(); + } + return StringUtils.EMPTY; + } + + /** + * 获取验证码开关 + * + * @return true开启,false关闭 + */ + @Override + public boolean selectCaptchaEnabled() + { + String captchaEnabled = selectConfigByKey("sys.account.captchaEnabled"); + if (StringUtils.isEmpty(captchaEnabled)) + { + return true; + } + return Convert.toBool(captchaEnabled); + } + + /** + * 查询参数配置列表 + * + * @param config 参数配置信息 + * @return 参数配置集合 + */ + @Override + public List selectConfigList(SysConfig config) + { + return configMapper.selectConfigList(config); + } + + /** + * 新增参数配置 + * + * @param config 参数配置信息 + * @return 结果 + */ + @Override + public int insertConfig(SysConfig config) + { + int row = configMapper.insertConfig(config); + if (row > 0) + { + redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()); + } + return row; + } + + /** + * 修改参数配置 + * + * @param config 参数配置信息 + * @return 结果 + */ + @Override + public int updateConfig(SysConfig config) + { + SysConfig temp = configMapper.selectConfigById(config.getConfigId()); + if (!StringUtils.equals(temp.getConfigKey(), config.getConfigKey())) + { + redisCache.deleteObject(getCacheKey(temp.getConfigKey())); + } + + int row = configMapper.updateConfig(config); + if (row > 0) + { + redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()); + } + return row; + } + + /** + * 批量删除参数信息 + * + * @param configIds 需要删除的参数ID + */ + @Override + public void deleteConfigByIds(Long[] configIds) + { + for (Long configId : configIds) + { + SysConfig config = selectConfigById(configId); + if (StringUtils.equals(UserConstants.YES, config.getConfigType())) + { + throw new ServiceException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey())); + } + configMapper.deleteConfigById(configId); + redisCache.deleteObject(getCacheKey(config.getConfigKey())); + } + } + + /** + * 加载参数缓存数据 + */ + @Override + public void loadingConfigCache() + { + List configsList = configMapper.selectConfigList(new SysConfig()); + for (SysConfig config : configsList) + { + redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()); + } + } + + /** + * 清空参数缓存数据 + */ + @Override + public void clearConfigCache() + { + Collection keys = redisCache.keys(CacheConstants.SYS_CONFIG_KEY + "*"); + redisCache.deleteObject(keys); + } + + /** + * 重置参数缓存数据 + */ + @Override + public void resetConfigCache() + { + clearConfigCache(); + loadingConfigCache(); + } + + /** + * 校验参数键名是否唯一 + * + * @param config 参数配置信息 + * @return 结果 + */ + @Override + public String checkConfigKeyUnique(SysConfig config) + { + Long configId = StringUtils.isNull(config.getConfigId()) ? -1L : config.getConfigId(); + SysConfig info = configMapper.checkConfigKeyUnique(config.getConfigKey()); + if (StringUtils.isNotNull(info) && info.getConfigId().longValue() != configId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 设置cache key + * + * @param configKey 参数键 + * @return 缓存键key + */ + private String getCacheKey(String configKey) + { + return CacheConstants.SYS_CONFIG_KEY + configKey; + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java new file mode 100644 index 0000000..fd65555 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java @@ -0,0 +1,338 @@ +package com.ruoyi.system.service.impl; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.common.annotation.DataScope; +import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.domain.TreeSelect; +import com.ruoyi.common.core.domain.entity.SysDept; +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.text.Convert; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.system.mapper.SysDeptMapper; +import com.ruoyi.system.mapper.SysRoleMapper; +import com.ruoyi.system.service.ISysDeptService; + +/** + * 部门管理 服务实现 + * + * @author #author# + */ +@Service +public class SysDeptServiceImpl implements ISysDeptService +{ + @Autowired + private SysDeptMapper deptMapper; + + @Autowired + private SysRoleMapper roleMapper; + + /** + * 查询部门管理数据 + * + * @param dept 部门信息 + * @return 部门信息集合 + */ + @Override + @DataScope(deptAlias = "d") + public List selectDeptList(SysDept dept) + { + return deptMapper.selectDeptList(dept); + } + + /** + * 查询部门树结构信息 + * + * @param dept 部门信息 + * @return 部门树信息集合 + */ + @Override + public List selectDeptTreeList(SysDept dept) + { + List depts = SpringUtils.getAopProxy(this).selectDeptList(dept); + return buildDeptTreeSelect(depts); + } + + /** + * 构建前端所需要树结构 + * + * @param depts 部门列表 + * @return 树结构列表 + */ + @Override + public List buildDeptTree(List depts) + { + List returnList = new ArrayList(); + List tempList = depts.stream().map(SysDept::getDeptId).collect(Collectors.toList()); + for (SysDept dept : depts) + { + // 如果是顶级节点, 遍历该父节点的所有子节点 + if (!tempList.contains(dept.getParentId())) + { + recursionFn(depts, dept); + returnList.add(dept); + } + } + if (returnList.isEmpty()) + { + returnList = depts; + } + return returnList; + } + + /** + * 构建前端所需要下拉树结构 + * + * @param depts 部门列表 + * @return 下拉树结构列表 + */ + @Override + public List buildDeptTreeSelect(List depts) + { + List deptTrees = buildDeptTree(depts); + return deptTrees.stream().map(TreeSelect::new).collect(Collectors.toList()); + } + + /** + * 根据角色ID查询部门树信息 + * + * @param roleId 角色ID + * @return 选中部门列表 + */ + @Override + public List selectDeptListByRoleId(Long roleId) + { + SysRole role = roleMapper.selectRoleById(roleId); + return deptMapper.selectDeptListByRoleId(roleId, role.isDeptCheckStrictly()); + } + + /** + * 根据部门ID查询信息 + * + * @param deptId 部门ID + * @return 部门信息 + */ + @Override + public SysDept selectDeptById(Long deptId) + { + return deptMapper.selectDeptById(deptId); + } + + /** + * 根据ID查询所有子部门(正常状态) + * + * @param deptId 部门ID + * @return 子部门数 + */ + @Override + public int selectNormalChildrenDeptById(Long deptId) + { + return deptMapper.selectNormalChildrenDeptById(deptId); + } + + /** + * 是否存在子节点 + * + * @param deptId 部门ID + * @return 结果 + */ + @Override + public boolean hasChildByDeptId(Long deptId) + { + int result = deptMapper.hasChildByDeptId(deptId); + return result > 0; + } + + /** + * 查询部门是否存在用户 + * + * @param deptId 部门ID + * @return 结果 true 存在 false 不存在 + */ + @Override + public boolean checkDeptExistUser(Long deptId) + { + int result = deptMapper.checkDeptExistUser(deptId); + return result > 0; + } + + /** + * 校验部门名称是否唯一 + * + * @param dept 部门信息 + * @return 结果 + */ + @Override + public String checkDeptNameUnique(SysDept dept) + { + Long deptId = StringUtils.isNull(dept.getDeptId()) ? -1L : dept.getDeptId(); + SysDept info = deptMapper.checkDeptNameUnique(dept.getDeptName(), dept.getParentId()); + if (StringUtils.isNotNull(info) && info.getDeptId().longValue() != deptId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 校验部门是否有数据权限 + * + * @param deptId 部门id + */ + @Override + public void checkDeptDataScope(Long deptId) + { + if (!SysUser.isAdmin(SecurityUtils.getUserId())) + { + SysDept dept = new SysDept(); + dept.setDeptId(deptId); + List depts = SpringUtils.getAopProxy(this).selectDeptList(dept); + if (StringUtils.isEmpty(depts)) + { + throw new ServiceException("没有权限访问部门数据!"); + } + } + } + + /** + * 新增保存部门信息 + * + * @param dept 部门信息 + * @return 结果 + */ + @Override + public int insertDept(SysDept dept) + { + SysDept info = deptMapper.selectDeptById(dept.getParentId()); + // 如果父节点不为正常状态,则不允许新增子节点 + if (!UserConstants.DEPT_NORMAL.equals(info.getStatus())) + { + throw new ServiceException("部门停用,不允许新增"); + } + dept.setAncestors(info.getAncestors() + "," + dept.getParentId()); + return deptMapper.insertDept(dept); + } + + /** + * 修改保存部门信息 + * + * @param dept 部门信息 + * @return 结果 + */ + @Override + public int updateDept(SysDept dept) + { + SysDept newParentDept = deptMapper.selectDeptById(dept.getParentId()); + SysDept oldDept = deptMapper.selectDeptById(dept.getDeptId()); + if (StringUtils.isNotNull(newParentDept) && StringUtils.isNotNull(oldDept)) + { + String newAncestors = newParentDept.getAncestors() + "," + newParentDept.getDeptId(); + String oldAncestors = oldDept.getAncestors(); + dept.setAncestors(newAncestors); + updateDeptChildren(dept.getDeptId(), newAncestors, oldAncestors); + } + int result = deptMapper.updateDept(dept); + if (UserConstants.DEPT_NORMAL.equals(dept.getStatus()) && StringUtils.isNotEmpty(dept.getAncestors()) + && !StringUtils.equals("0", dept.getAncestors())) + { + // 如果该部门是启用状态,则启用该部门的所有上级部门 + updateParentDeptStatusNormal(dept); + } + return result; + } + + /** + * 修改该部门的父级部门状态 + * + * @param dept 当前部门 + */ + private void updateParentDeptStatusNormal(SysDept dept) + { + String ancestors = dept.getAncestors(); + Long[] deptIds = Convert.toLongArray(ancestors); + deptMapper.updateDeptStatusNormal(deptIds); + } + + /** + * 修改子元素关系 + * + * @param deptId 被修改的部门ID + * @param newAncestors 新的父ID集合 + * @param oldAncestors 旧的父ID集合 + */ + public void updateDeptChildren(Long deptId, String newAncestors, String oldAncestors) + { + List children = deptMapper.selectChildrenDeptById(deptId); + for (SysDept child : children) + { + child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors)); + } + if (children.size() > 0) + { + deptMapper.updateDeptChildren(children); + } + } + + /** + * 删除部门管理信息 + * + * @param deptId 部门ID + * @return 结果 + */ + @Override + public int deleteDeptById(Long deptId) + { + return deptMapper.deleteDeptById(deptId); + } + + /** + * 递归列表 + */ + private void recursionFn(List list, SysDept t) + { + // 得到子节点列表 + List childList = getChildList(list, t); + t.setChildren(childList); + for (SysDept tChild : childList) + { + if (hasChild(list, tChild)) + { + recursionFn(list, tChild); + } + } + } + + /** + * 得到子节点列表 + */ + private List getChildList(List list, SysDept t) + { + List tlist = new ArrayList(); + Iterator it = list.iterator(); + while (it.hasNext()) + { + SysDept n = (SysDept) it.next(); + if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getDeptId().longValue()) + { + tlist.add(n); + } + } + return tlist; + } + + /** + * 判断是否有子节点 + */ + private boolean hasChild(List list, SysDept t) + { + return getChildList(list, t).size() > 0; + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java new file mode 100644 index 0000000..af66b81 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java @@ -0,0 +1,111 @@ +package com.ruoyi.system.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.common.core.domain.entity.SysDictData; +import com.ruoyi.common.utils.DictUtils; +import com.ruoyi.system.mapper.SysDictDataMapper; +import com.ruoyi.system.service.ISysDictDataService; + +/** + * 字典 业务层处理 + * + * @author #author# + */ +@Service +public class SysDictDataServiceImpl implements ISysDictDataService +{ + @Autowired + private SysDictDataMapper dictDataMapper; + + /** + * 根据条件分页查询字典数据 + * + * @param dictData 字典数据信息 + * @return 字典数据集合信息 + */ + @Override + public List selectDictDataList(SysDictData dictData) + { + return dictDataMapper.selectDictDataList(dictData); + } + + /** + * 根据字典类型和字典键值查询字典数据信息 + * + * @param dictType 字典类型 + * @param dictValue 字典键值 + * @return 字典标签 + */ + @Override + public String selectDictLabel(String dictType, String dictValue) + { + return dictDataMapper.selectDictLabel(dictType, dictValue); + } + + /** + * 根据字典数据ID查询信息 + * + * @param dictCode 字典数据ID + * @return 字典数据 + */ + @Override + public SysDictData selectDictDataById(Long dictCode) + { + return dictDataMapper.selectDictDataById(dictCode); + } + + /** + * 批量删除字典数据信息 + * + * @param dictCodes 需要删除的字典数据ID + */ + @Override + public void deleteDictDataByIds(Long[] dictCodes) + { + for (Long dictCode : dictCodes) + { + SysDictData data = selectDictDataById(dictCode); + dictDataMapper.deleteDictDataById(dictCode); + List dictDatas = dictDataMapper.selectDictDataByType(data.getDictType()); + DictUtils.setDictCache(data.getDictType(), dictDatas); + } + } + + /** + * 新增保存字典数据信息 + * + * @param data 字典数据信息 + * @return 结果 + */ + @Override + public int insertDictData(SysDictData data) + { + int row = dictDataMapper.insertDictData(data); + if (row > 0) + { + List dictDatas = dictDataMapper.selectDictDataByType(data.getDictType()); + DictUtils.setDictCache(data.getDictType(), dictDatas); + } + return row; + } + + /** + * 修改保存字典数据信息 + * + * @param data 字典数据信息 + * @return 结果 + */ + @Override + public int updateDictData(SysDictData data) + { + int row = dictDataMapper.updateDictData(data); + if (row > 0) + { + List dictDatas = dictDataMapper.selectDictDataByType(data.getDictType()); + DictUtils.setDictCache(data.getDictType(), dictDatas); + } + return row; + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java new file mode 100644 index 0000000..3e1a18c --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java @@ -0,0 +1,223 @@ +package com.ruoyi.system.service.impl; + +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import javax.annotation.PostConstruct; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.domain.entity.SysDictData; +import com.ruoyi.common.core.domain.entity.SysDictType; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.DictUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.system.mapper.SysDictDataMapper; +import com.ruoyi.system.mapper.SysDictTypeMapper; +import com.ruoyi.system.service.ISysDictTypeService; + +/** + * 字典 业务层处理 + * + * @author #author# + */ +@Service +public class SysDictTypeServiceImpl implements ISysDictTypeService +{ + @Autowired + private SysDictTypeMapper dictTypeMapper; + + @Autowired + private SysDictDataMapper dictDataMapper; + + /** + * 项目启动时,初始化字典到缓存 + */ + @PostConstruct + public void init() + { + loadingDictCache(); + } + + /** + * 根据条件分页查询字典类型 + * + * @param dictType 字典类型信息 + * @return 字典类型集合信息 + */ + @Override + public List selectDictTypeList(SysDictType dictType) + { + return dictTypeMapper.selectDictTypeList(dictType); + } + + /** + * 根据所有字典类型 + * + * @return 字典类型集合信息 + */ + @Override + public List selectDictTypeAll() + { + return dictTypeMapper.selectDictTypeAll(); + } + + /** + * 根据字典类型查询字典数据 + * + * @param dictType 字典类型 + * @return 字典数据集合信息 + */ + @Override + public List selectDictDataByType(String dictType) + { + List dictDatas = DictUtils.getDictCache(dictType); + if (StringUtils.isNotEmpty(dictDatas)) + { + return dictDatas; + } + dictDatas = dictDataMapper.selectDictDataByType(dictType); + if (StringUtils.isNotEmpty(dictDatas)) + { + DictUtils.setDictCache(dictType, dictDatas); + return dictDatas; + } + return null; + } + + /** + * 根据字典类型ID查询信息 + * + * @param dictId 字典类型ID + * @return 字典类型 + */ + @Override + public SysDictType selectDictTypeById(Long dictId) + { + return dictTypeMapper.selectDictTypeById(dictId); + } + + /** + * 根据字典类型查询信息 + * + * @param dictType 字典类型 + * @return 字典类型 + */ + @Override + public SysDictType selectDictTypeByType(String dictType) + { + return dictTypeMapper.selectDictTypeByType(dictType); + } + + /** + * 批量删除字典类型信息 + * + * @param dictIds 需要删除的字典ID + */ + @Override + public void deleteDictTypeByIds(Long[] dictIds) + { + for (Long dictId : dictIds) + { + SysDictType dictType = selectDictTypeById(dictId); + if (dictDataMapper.countDictDataByType(dictType.getDictType()) > 0) + { + throw new ServiceException(String.format("%1$s已分配,不能删除", dictType.getDictName())); + } + dictTypeMapper.deleteDictTypeById(dictId); + DictUtils.removeDictCache(dictType.getDictType()); + } + } + + /** + * 加载字典缓存数据 + */ + @Override + public void loadingDictCache() + { + SysDictData dictData = new SysDictData(); + dictData.setStatus("0"); + Map> dictDataMap = dictDataMapper.selectDictDataList(dictData).stream().collect(Collectors.groupingBy(SysDictData::getDictType)); + for (Map.Entry> entry : dictDataMap.entrySet()) + { + DictUtils.setDictCache(entry.getKey(), entry.getValue().stream().sorted(Comparator.comparing(SysDictData::getDictSort)).collect(Collectors.toList())); + } + } + + /** + * 清空字典缓存数据 + */ + @Override + public void clearDictCache() + { + DictUtils.clearDictCache(); + } + + /** + * 重置字典缓存数据 + */ + @Override + public void resetDictCache() + { + clearDictCache(); + loadingDictCache(); + } + + /** + * 新增保存字典类型信息 + * + * @param dict 字典类型信息 + * @return 结果 + */ + @Override + public int insertDictType(SysDictType dict) + { + int row = dictTypeMapper.insertDictType(dict); + if (row > 0) + { + DictUtils.setDictCache(dict.getDictType(), null); + } + return row; + } + + /** + * 修改保存字典类型信息 + * + * @param dict 字典类型信息 + * @return 结果 + */ + @Override + @Transactional + public int updateDictType(SysDictType dict) + { + SysDictType oldDict = dictTypeMapper.selectDictTypeById(dict.getDictId()); + dictDataMapper.updateDictDataType(oldDict.getDictType(), dict.getDictType()); + int row = dictTypeMapper.updateDictType(dict); + if (row > 0) + { + List dictDatas = dictDataMapper.selectDictDataByType(dict.getDictType()); + DictUtils.setDictCache(dict.getDictType(), dictDatas); + } + return row; + } + + /** + * 校验字典类型称是否唯一 + * + * @param dict 字典类型 + * @return 结果 + */ + @Override + public String checkDictTypeUnique(SysDictType dict) + { + Long dictId = StringUtils.isNull(dict.getDictId()) ? -1L : dict.getDictId(); + SysDictType dictType = dictTypeMapper.checkDictTypeUnique(dict.getDictType()); + if (StringUtils.isNotNull(dictType) && dictType.getDictId().longValue() != dictId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java new file mode 100644 index 0000000..3ab1326 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java @@ -0,0 +1,65 @@ +package com.ruoyi.system.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.system.domain.SysLogininfor; +import com.ruoyi.system.mapper.SysLogininforMapper; +import com.ruoyi.system.service.ISysLogininforService; + +/** + * 系统访问日志情况信息 服务层处理 + * + * @author #author# + */ +@Service +public class SysLogininforServiceImpl implements ISysLogininforService +{ + + @Autowired + private SysLogininforMapper logininforMapper; + + /** + * 新增系统登录日志 + * + * @param logininfor 访问日志对象 + */ + @Override + public void insertLogininfor(SysLogininfor logininfor) + { + logininforMapper.insertLogininfor(logininfor); + } + + /** + * 查询系统登录日志集合 + * + * @param logininfor 访问日志对象 + * @return 登录记录集合 + */ + @Override + public List selectLogininforList(SysLogininfor logininfor) + { + return logininforMapper.selectLogininforList(logininfor); + } + + /** + * 批量删除系统登录日志 + * + * @param infoIds 需要删除的登录日志ID + * @return 结果 + */ + @Override + public int deleteLogininforByIds(Long[] infoIds) + { + return logininforMapper.deleteLogininforByIds(infoIds); + } + + /** + * 清空系统登录日志 + */ + @Override + public void cleanLogininfor() + { + logininforMapper.cleanLogininfor(); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java new file mode 100644 index 0000000..6b652cc --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java @@ -0,0 +1,531 @@ +package com.ruoyi.system.service.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.domain.TreeSelect; +import com.ruoyi.common.core.domain.entity.SysMenu; +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.system.domain.vo.MetaVo; +import com.ruoyi.system.domain.vo.RouterVo; +import com.ruoyi.system.mapper.SysMenuMapper; +import com.ruoyi.system.mapper.SysRoleMapper; +import com.ruoyi.system.mapper.SysRoleMenuMapper; +import com.ruoyi.system.service.ISysMenuService; + +/** + * 菜单 业务层处理 + * + * @author #author# + */ +@Service +public class SysMenuServiceImpl implements ISysMenuService +{ + public static final String PREMISSION_STRING = "perms[\"{0}\"]"; + + @Autowired + private SysMenuMapper menuMapper; + + @Autowired + private SysRoleMapper roleMapper; + + @Autowired + private SysRoleMenuMapper roleMenuMapper; + + /** + * 根据用户查询系统菜单列表 + * + * @param userId 用户ID + * @return 菜单列表 + */ + @Override + public List selectMenuList(Long userId) + { + return selectMenuList(new SysMenu(), userId); + } + + /** + * 查询系统菜单列表 + * + * @param menu 菜单信息 + * @return 菜单列表 + */ + @Override + public List selectMenuList(SysMenu menu, Long userId) + { + List menuList = null; + // 管理员显示所有菜单信息 + if (SysUser.isAdmin(userId)) + { + menuList = menuMapper.selectMenuList(menu); + } + else + { + menu.getParams().put("userId", userId); + menuList = menuMapper.selectMenuListByUserId(menu); + } + return menuList; + } + + /** + * 根据用户ID查询权限 + * + * @param userId 用户ID + * @return 权限列表 + */ + @Override + public Set selectMenuPermsByUserId(Long userId) + { + List perms = menuMapper.selectMenuPermsByUserId(userId); + Set permsSet = new HashSet<>(); + for (String perm : perms) + { + if (StringUtils.isNotEmpty(perm)) + { + permsSet.addAll(Arrays.asList(perm.trim().split(","))); + } + } + return permsSet; + } + + /** + * 根据角色ID查询权限 + * + * @param roleId 角色ID + * @return 权限列表 + */ + @Override + public Set selectMenuPermsByRoleId(Long roleId) + { + List perms = menuMapper.selectMenuPermsByRoleId(roleId); + Set permsSet = new HashSet<>(); + for (String perm : perms) + { + if (StringUtils.isNotEmpty(perm)) + { + permsSet.addAll(Arrays.asList(perm.trim().split(","))); + } + } + return permsSet; + } + + /** + * 根据用户ID查询菜单 + * + * @param userId 用户名称 + * @return 菜单列表 + */ + @Override + public List selectMenuTreeByUserId(Long userId) + { + List menus = null; + if (SecurityUtils.isAdmin(userId)) + { + menus = menuMapper.selectMenuTreeAll(); + } + else + { + menus = menuMapper.selectMenuTreeByUserId(userId); + } + return getChildPerms(menus, 0); + } + + /** + * 根据角色ID查询菜单树信息 + * + * @param roleId 角色ID + * @return 选中菜单列表 + */ + @Override + public List selectMenuListByRoleId(Long roleId) + { + SysRole role = roleMapper.selectRoleById(roleId); + return menuMapper.selectMenuListByRoleId(roleId, role.isMenuCheckStrictly()); + } + + /** + * 构建前端路由所需要的菜单 + * + * @param menus 菜单列表 + * @return 路由列表 + */ + @Override + public List buildMenus(List menus) + { + List routers = new LinkedList(); + for (SysMenu menu : menus) + { + RouterVo router = new RouterVo(); + router.setHidden("1".equals(menu.getVisible())); + router.setName(getRouteName(menu)); + router.setPath(getRouterPath(menu)); + router.setComponent(getComponent(menu)); + router.setQuery(menu.getQuery()); + router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath())); + List cMenus = menu.getChildren(); + if (!cMenus.isEmpty() && cMenus.size() > 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType())) + { + router.setAlwaysShow(true); + router.setRedirect("noRedirect"); + router.setChildren(buildMenus(cMenus)); + } + else if (isMenuFrame(menu)) + { + router.setMeta(null); + List childrenList = new ArrayList(); + RouterVo children = new RouterVo(); + children.setPath(menu.getPath()); + children.setComponent(menu.getComponent()); + children.setName(StringUtils.capitalize(menu.getPath())); + children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath())); + children.setQuery(menu.getQuery()); + childrenList.add(children); + router.setChildren(childrenList); + } + else if (menu.getParentId().intValue() == 0 && isInnerLink(menu)) + { + router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon())); + router.setPath("/"); + List childrenList = new ArrayList(); + RouterVo children = new RouterVo(); + String routerPath = innerLinkReplaceEach(menu.getPath()); + children.setPath(routerPath); + children.setComponent(UserConstants.INNER_LINK); + children.setName(StringUtils.capitalize(routerPath)); + children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), menu.getPath())); + childrenList.add(children); + router.setChildren(childrenList); + } + routers.add(router); + } + return routers; + } + + /** + * 构建前端所需要树结构 + * + * @param menus 菜单列表 + * @return 树结构列表 + */ + @Override + public List buildMenuTree(List menus) + { + List returnList = new ArrayList(); + List tempList = menus.stream().map(SysMenu::getMenuId).collect(Collectors.toList()); + for (Iterator iterator = menus.iterator(); iterator.hasNext();) + { + SysMenu menu = (SysMenu) iterator.next(); + // 如果是顶级节点, 遍历该父节点的所有子节点 + if (!tempList.contains(menu.getParentId())) + { + recursionFn(menus, menu); + returnList.add(menu); + } + } + if (returnList.isEmpty()) + { + returnList = menus; + } + return returnList; + } + + /** + * 构建前端所需要下拉树结构 + * + * @param menus 菜单列表 + * @return 下拉树结构列表 + */ + @Override + public List buildMenuTreeSelect(List menus) + { + List menuTrees = buildMenuTree(menus); + return menuTrees.stream().map(TreeSelect::new).collect(Collectors.toList()); + } + + /** + * 根据菜单ID查询信息 + * + * @param menuId 菜单ID + * @return 菜单信息 + */ + @Override + public SysMenu selectMenuById(Long menuId) + { + return menuMapper.selectMenuById(menuId); + } + + /** + * 是否存在菜单子节点 + * + * @param menuId 菜单ID + * @return 结果 + */ + @Override + public boolean hasChildByMenuId(Long menuId) + { + int result = menuMapper.hasChildByMenuId(menuId); + return result > 0; + } + + /** + * 查询菜单使用数量 + * + * @param menuId 菜单ID + * @return 结果 + */ + @Override + public boolean checkMenuExistRole(Long menuId) + { + int result = roleMenuMapper.checkMenuExistRole(menuId); + return result > 0; + } + + /** + * 新增保存菜单信息 + * + * @param menu 菜单信息 + * @return 结果 + */ + @Override + public int insertMenu(SysMenu menu) + { + return menuMapper.insertMenu(menu); + } + + /** + * 修改保存菜单信息 + * + * @param menu 菜单信息 + * @return 结果 + */ + @Override + public int updateMenu(SysMenu menu) + { + return menuMapper.updateMenu(menu); + } + + /** + * 删除菜单管理信息 + * + * @param menuId 菜单ID + * @return 结果 + */ + @Override + public int deleteMenuById(Long menuId) + { + return menuMapper.deleteMenuById(menuId); + } + + /** + * 校验菜单名称是否唯一 + * + * @param menu 菜单信息 + * @return 结果 + */ + @Override + public String checkMenuNameUnique(SysMenu menu) + { + Long menuId = StringUtils.isNull(menu.getMenuId()) ? -1L : menu.getMenuId(); + SysMenu info = menuMapper.checkMenuNameUnique(menu.getMenuName(), menu.getParentId()); + if (StringUtils.isNotNull(info) && info.getMenuId().longValue() != menuId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 获取路由名称 + * + * @param menu 菜单信息 + * @return 路由名称 + */ + public String getRouteName(SysMenu menu) + { + String routerName = StringUtils.capitalize(menu.getPath()); + // 非外链并且是一级目录(类型为目录) + if (isMenuFrame(menu)) + { + routerName = StringUtils.EMPTY; + } + return routerName; + } + + /** + * 获取路由地址 + * + * @param menu 菜单信息 + * @return 路由地址 + */ + public String getRouterPath(SysMenu menu) + { + String routerPath = menu.getPath(); + // 内链打开外网方式 + if (menu.getParentId().intValue() != 0 && isInnerLink(menu)) + { + routerPath = innerLinkReplaceEach(routerPath); + } + // 非外链并且是一级目录(类型为目录) + if (0 == menu.getParentId().intValue() && UserConstants.TYPE_DIR.equals(menu.getMenuType()) + && UserConstants.NO_FRAME.equals(menu.getIsFrame())) + { + routerPath = "/" + menu.getPath(); + } + // 非外链并且是一级目录(类型为菜单) + else if (isMenuFrame(menu)) + { + routerPath = "/"; + } + return routerPath; + } + + /** + * 获取组件信息 + * + * @param menu 菜单信息 + * @return 组件信息 + */ + public String getComponent(SysMenu menu) + { + String component = UserConstants.LAYOUT; + if (StringUtils.isNotEmpty(menu.getComponent()) && !isMenuFrame(menu)) + { + component = menu.getComponent(); + } + else if (StringUtils.isEmpty(menu.getComponent()) && menu.getParentId().intValue() != 0 && isInnerLink(menu)) + { + component = UserConstants.INNER_LINK; + } + else if (StringUtils.isEmpty(menu.getComponent()) && isParentView(menu)) + { + component = UserConstants.PARENT_VIEW; + } + return component; + } + + /** + * 是否为菜单内部跳转 + * + * @param menu 菜单信息 + * @return 结果 + */ + public boolean isMenuFrame(SysMenu menu) + { + return menu.getParentId().intValue() == 0 && UserConstants.TYPE_MENU.equals(menu.getMenuType()) + && menu.getIsFrame().equals(UserConstants.NO_FRAME); + } + + /** + * 是否为内链组件 + * + * @param menu 菜单信息 + * @return 结果 + */ + public boolean isInnerLink(SysMenu menu) + { + return menu.getIsFrame().equals(UserConstants.NO_FRAME) && StringUtils.ishttp(menu.getPath()); + } + + /** + * 是否为parent_view组件 + * + * @param menu 菜单信息 + * @return 结果 + */ + public boolean isParentView(SysMenu menu) + { + return menu.getParentId().intValue() != 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType()); + } + + /** + * 根据父节点的ID获取所有子节点 + * + * @param list 分类表 + * @param parentId 传入的父节点ID + * @return String + */ + public List getChildPerms(List list, int parentId) + { + List returnList = new ArrayList(); + for (Iterator iterator = list.iterator(); iterator.hasNext();) + { + SysMenu t = (SysMenu) iterator.next(); + // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点 + if (t.getParentId() == parentId) + { + recursionFn(list, t); + returnList.add(t); + } + } + return returnList; + } + + /** + * 递归列表 + * + * @param list 分类表 + * @param t 子节点 + */ + private void recursionFn(List list, SysMenu t) + { + // 得到子节点列表 + List childList = getChildList(list, t); + t.setChildren(childList); + for (SysMenu tChild : childList) + { + if (hasChild(list, tChild)) + { + recursionFn(list, tChild); + } + } + } + + /** + * 得到子节点列表 + */ + private List getChildList(List list, SysMenu t) + { + List tlist = new ArrayList(); + Iterator it = list.iterator(); + while (it.hasNext()) + { + SysMenu n = (SysMenu) it.next(); + if (n.getParentId().longValue() == t.getMenuId().longValue()) + { + tlist.add(n); + } + } + return tlist; + } + + /** + * 判断是否有子节点 + */ + private boolean hasChild(List list, SysMenu t) + { + return getChildList(list, t).size() > 0; + } + + /** + * 内链域名特殊字符替换 + * + * @return 替换后的内链域名 + */ + public String innerLinkReplaceEach(String path) + { + return StringUtils.replaceEach(path, new String[] { Constants.HTTP, Constants.HTTPS, Constants.WWW, "." }, + new String[] { "", "", "", "/" }); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java new file mode 100644 index 0000000..7367535 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java @@ -0,0 +1,92 @@ +package com.ruoyi.system.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.system.domain.SysNotice; +import com.ruoyi.system.mapper.SysNoticeMapper; +import com.ruoyi.system.service.ISysNoticeService; + +/** + * 公告 服务层实现 + * + * @author #author# + */ +@Service +public class SysNoticeServiceImpl implements ISysNoticeService +{ + @Autowired + private SysNoticeMapper noticeMapper; + + /** + * 查询公告信息 + * + * @param noticeId 公告ID + * @return 公告信息 + */ + @Override + public SysNotice selectNoticeById(Long noticeId) + { + return noticeMapper.selectNoticeById(noticeId); + } + + /** + * 查询公告列表 + * + * @param notice 公告信息 + * @return 公告集合 + */ + @Override + public List selectNoticeList(SysNotice notice) + { + return noticeMapper.selectNoticeList(notice); + } + + /** + * 新增公告 + * + * @param notice 公告信息 + * @return 结果 + */ + @Override + public int insertNotice(SysNotice notice) + { + return noticeMapper.insertNotice(notice); + } + + /** + * 修改公告 + * + * @param notice 公告信息 + * @return 结果 + */ + @Override + public int updateNotice(SysNotice notice) + { + return noticeMapper.updateNotice(notice); + } + + /** + * 删除公告对象 + * + * @param noticeId 公告ID + * @return 结果 + */ + @Override + public int deleteNoticeById(Long noticeId) + { + return noticeMapper.deleteNoticeById(noticeId); + } + + /** + * 批量删除公告信息 + * + * @param noticeIds 需要删除的公告ID + * @return 结果 + */ + @Override + public int deleteNoticeByIds(Long[] noticeIds) + { + return noticeMapper.deleteNoticeByIds(noticeIds); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java new file mode 100644 index 0000000..c57733d --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java @@ -0,0 +1,76 @@ +package com.ruoyi.system.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.system.domain.SysOperLog; +import com.ruoyi.system.mapper.SysOperLogMapper; +import com.ruoyi.system.service.ISysOperLogService; + +/** + * 操作日志 服务层处理 + * + * @author #author# + */ +@Service +public class SysOperLogServiceImpl implements ISysOperLogService +{ + @Autowired + private SysOperLogMapper operLogMapper; + + /** + * 新增操作日志 + * + * @param operLog 操作日志对象 + */ + @Override + public void insertOperlog(SysOperLog operLog) + { + operLogMapper.insertOperlog(operLog); + } + + /** + * 查询系统操作日志集合 + * + * @param operLog 操作日志对象 + * @return 操作日志集合 + */ + @Override + public List selectOperLogList(SysOperLog operLog) + { + return operLogMapper.selectOperLogList(operLog); + } + + /** + * 批量删除系统操作日志 + * + * @param operIds 需要删除的操作日志ID + * @return 结果 + */ + @Override + public int deleteOperLogByIds(Long[] operIds) + { + return operLogMapper.deleteOperLogByIds(operIds); + } + + /** + * 查询操作日志详细 + * + * @param operId 操作ID + * @return 操作日志对象 + */ + @Override + public SysOperLog selectOperLogById(Long operId) + { + return operLogMapper.selectOperLogById(operId); + } + + /** + * 清空操作日志 + */ + @Override + public void cleanOperLog() + { + operLogMapper.cleanOperLog(); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java new file mode 100644 index 0000000..d670050 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java @@ -0,0 +1,178 @@ +package com.ruoyi.system.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.system.domain.SysPost; +import com.ruoyi.system.mapper.SysPostMapper; +import com.ruoyi.system.mapper.SysUserPostMapper; +import com.ruoyi.system.service.ISysPostService; + +/** + * 岗位信息 服务层处理 + * + * @author #author# + */ +@Service +public class SysPostServiceImpl implements ISysPostService +{ + @Autowired + private SysPostMapper postMapper; + + @Autowired + private SysUserPostMapper userPostMapper; + + /** + * 查询岗位信息集合 + * + * @param post 岗位信息 + * @return 岗位信息集合 + */ + @Override + public List selectPostList(SysPost post) + { + return postMapper.selectPostList(post); + } + + /** + * 查询所有岗位 + * + * @return 岗位列表 + */ + @Override + public List selectPostAll() + { + return postMapper.selectPostAll(); + } + + /** + * 通过岗位ID查询岗位信息 + * + * @param postId 岗位ID + * @return 角色对象信息 + */ + @Override + public SysPost selectPostById(Long postId) + { + return postMapper.selectPostById(postId); + } + + /** + * 根据用户ID获取岗位选择框列表 + * + * @param userId 用户ID + * @return 选中岗位ID列表 + */ + @Override + public List selectPostListByUserId(Long userId) + { + return postMapper.selectPostListByUserId(userId); + } + + /** + * 校验岗位名称是否唯一 + * + * @param post 岗位信息 + * @return 结果 + */ + @Override + public String checkPostNameUnique(SysPost post) + { + Long postId = StringUtils.isNull(post.getPostId()) ? -1L : post.getPostId(); + SysPost info = postMapper.checkPostNameUnique(post.getPostName()); + if (StringUtils.isNotNull(info) && info.getPostId().longValue() != postId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 校验岗位编码是否唯一 + * + * @param post 岗位信息 + * @return 结果 + */ + @Override + public String checkPostCodeUnique(SysPost post) + { + Long postId = StringUtils.isNull(post.getPostId()) ? -1L : post.getPostId(); + SysPost info = postMapper.checkPostCodeUnique(post.getPostCode()); + if (StringUtils.isNotNull(info) && info.getPostId().longValue() != postId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 通过岗位ID查询岗位使用数量 + * + * @param postId 岗位ID + * @return 结果 + */ + @Override + public int countUserPostById(Long postId) + { + return userPostMapper.countUserPostById(postId); + } + + /** + * 删除岗位信息 + * + * @param postId 岗位ID + * @return 结果 + */ + @Override + public int deletePostById(Long postId) + { + return postMapper.deletePostById(postId); + } + + /** + * 批量删除岗位信息 + * + * @param postIds 需要删除的岗位ID + * @return 结果 + */ + @Override + public int deletePostByIds(Long[] postIds) + { + for (Long postId : postIds) + { + SysPost post = selectPostById(postId); + if (countUserPostById(postId) > 0) + { + throw new ServiceException(String.format("%1$s已分配,不能删除", post.getPostName())); + } + } + return postMapper.deletePostByIds(postIds); + } + + /** + * 新增保存岗位信息 + * + * @param post 岗位信息 + * @return 结果 + */ + @Override + public int insertPost(SysPost post) + { + return postMapper.insertPost(post); + } + + /** + * 修改保存岗位信息 + * + * @param post 岗位信息 + * @return 结果 + */ + @Override + public int updatePost(SysPost post) + { + return postMapper.updatePost(post); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java new file mode 100644 index 0000000..5457fa6 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java @@ -0,0 +1,424 @@ +package com.ruoyi.system.service.impl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import com.ruoyi.common.annotation.DataScope; +import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.system.domain.SysRoleDept; +import com.ruoyi.system.domain.SysRoleMenu; +import com.ruoyi.system.domain.SysUserRole; +import com.ruoyi.system.mapper.SysRoleDeptMapper; +import com.ruoyi.system.mapper.SysRoleMapper; +import com.ruoyi.system.mapper.SysRoleMenuMapper; +import com.ruoyi.system.mapper.SysUserRoleMapper; +import com.ruoyi.system.service.ISysRoleService; + +/** + * 角色 业务层处理 + * + * @author #author# + */ +@Service +public class SysRoleServiceImpl implements ISysRoleService +{ + @Autowired + private SysRoleMapper roleMapper; + + @Autowired + private SysRoleMenuMapper roleMenuMapper; + + @Autowired + private SysUserRoleMapper userRoleMapper; + + @Autowired + private SysRoleDeptMapper roleDeptMapper; + + /** + * 根据条件分页查询角色数据 + * + * @param role 角色信息 + * @return 角色数据集合信息 + */ + @Override + @DataScope(deptAlias = "d") + public List selectRoleList(SysRole role) + { + return roleMapper.selectRoleList(role); + } + + /** + * 根据用户ID查询角色 + * + * @param userId 用户ID + * @return 角色列表 + */ + @Override + public List selectRolesByUserId(Long userId) + { + List userRoles = roleMapper.selectRolePermissionByUserId(userId); + List roles = selectRoleAll(); + for (SysRole role : roles) + { + for (SysRole userRole : userRoles) + { + if (role.getRoleId().longValue() == userRole.getRoleId().longValue()) + { + role.setFlag(true); + break; + } + } + } + return roles; + } + + /** + * 根据用户ID查询权限 + * + * @param userId 用户ID + * @return 权限列表 + */ + @Override + public Set selectRolePermissionByUserId(Long userId) + { + List perms = roleMapper.selectRolePermissionByUserId(userId); + Set permsSet = new HashSet<>(); + for (SysRole perm : perms) + { + if (StringUtils.isNotNull(perm)) + { + permsSet.addAll(Arrays.asList(perm.getRoleKey().trim().split(","))); + } + } + return permsSet; + } + + /** + * 查询所有角色 + * + * @return 角色列表 + */ + @Override + public List selectRoleAll() + { + return SpringUtils.getAopProxy(this).selectRoleList(new SysRole()); + } + + /** + * 根据用户ID获取角色选择框列表 + * + * @param userId 用户ID + * @return 选中角色ID列表 + */ + @Override + public List selectRoleListByUserId(Long userId) + { + return roleMapper.selectRoleListByUserId(userId); + } + + /** + * 通过角色ID查询角色 + * + * @param roleId 角色ID + * @return 角色对象信息 + */ + @Override + public SysRole selectRoleById(Long roleId) + { + return roleMapper.selectRoleById(roleId); + } + + /** + * 校验角色名称是否唯一 + * + * @param role 角色信息 + * @return 结果 + */ + @Override + public String checkRoleNameUnique(SysRole role) + { + Long roleId = StringUtils.isNull(role.getRoleId()) ? -1L : role.getRoleId(); + SysRole info = roleMapper.checkRoleNameUnique(role.getRoleName()); + if (StringUtils.isNotNull(info) && info.getRoleId().longValue() != roleId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 校验角色权限是否唯一 + * + * @param role 角色信息 + * @return 结果 + */ + @Override + public String checkRoleKeyUnique(SysRole role) + { + Long roleId = StringUtils.isNull(role.getRoleId()) ? -1L : role.getRoleId(); + SysRole info = roleMapper.checkRoleKeyUnique(role.getRoleKey()); + if (StringUtils.isNotNull(info) && info.getRoleId().longValue() != roleId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 校验角色是否允许操作 + * + * @param role 角色信息 + */ + @Override + public void checkRoleAllowed(SysRole role) + { + if (StringUtils.isNotNull(role.getRoleId()) && role.isAdmin()) + { + throw new ServiceException("不允许操作超级管理员角色"); + } + } + + /** + * 校验角色是否有数据权限 + * + * @param roleId 角色id + */ + @Override + public void checkRoleDataScope(Long roleId) + { + if (!SysUser.isAdmin(SecurityUtils.getUserId())) + { + SysRole role = new SysRole(); + role.setRoleId(roleId); + List roles = SpringUtils.getAopProxy(this).selectRoleList(role); + if (StringUtils.isEmpty(roles)) + { + throw new ServiceException("没有权限访问角色数据!"); + } + } + } + + /** + * 通过角色ID查询角色使用数量 + * + * @param roleId 角色ID + * @return 结果 + */ + @Override + public int countUserRoleByRoleId(Long roleId) + { + return userRoleMapper.countUserRoleByRoleId(roleId); + } + + /** + * 新增保存角色信息 + * + * @param role 角色信息 + * @return 结果 + */ + @Override + @Transactional + public int insertRole(SysRole role) + { + // 新增角色信息 + roleMapper.insertRole(role); + return insertRoleMenu(role); + } + + /** + * 修改保存角色信息 + * + * @param role 角色信息 + * @return 结果 + */ + @Override + @Transactional + public int updateRole(SysRole role) + { + // 修改角色信息 + roleMapper.updateRole(role); + // 删除角色与菜单关联 + roleMenuMapper.deleteRoleMenuByRoleId(role.getRoleId()); + return insertRoleMenu(role); + } + + /** + * 修改角色状态 + * + * @param role 角色信息 + * @return 结果 + */ + @Override + public int updateRoleStatus(SysRole role) + { + return roleMapper.updateRole(role); + } + + /** + * 修改数据权限信息 + * + * @param role 角色信息 + * @return 结果 + */ + @Override + @Transactional + public int authDataScope(SysRole role) + { + // 修改角色信息 + roleMapper.updateRole(role); + // 删除角色与部门关联 + roleDeptMapper.deleteRoleDeptByRoleId(role.getRoleId()); + // 新增角色和部门信息(数据权限) + return insertRoleDept(role); + } + + /** + * 新增角色菜单信息 + * + * @param role 角色对象 + */ + public int insertRoleMenu(SysRole role) + { + int rows = 1; + // 新增用户与角色管理 + List list = new ArrayList(); + for (Long menuId : role.getMenuIds()) + { + SysRoleMenu rm = new SysRoleMenu(); + rm.setRoleId(role.getRoleId()); + rm.setMenuId(menuId); + list.add(rm); + } + if (list.size() > 0) + { + rows = roleMenuMapper.batchRoleMenu(list); + } + return rows; + } + + /** + * 新增角色部门信息(数据权限) + * + * @param role 角色对象 + */ + public int insertRoleDept(SysRole role) + { + int rows = 1; + // 新增角色与部门(数据权限)管理 + List list = new ArrayList(); + for (Long deptId : role.getDeptIds()) + { + SysRoleDept rd = new SysRoleDept(); + rd.setRoleId(role.getRoleId()); + rd.setDeptId(deptId); + list.add(rd); + } + if (list.size() > 0) + { + rows = roleDeptMapper.batchRoleDept(list); + } + return rows; + } + + /** + * 通过角色ID删除角色 + * + * @param roleId 角色ID + * @return 结果 + */ + @Override + @Transactional + public int deleteRoleById(Long roleId) + { + // 删除角色与菜单关联 + roleMenuMapper.deleteRoleMenuByRoleId(roleId); + // 删除角色与部门关联 + roleDeptMapper.deleteRoleDeptByRoleId(roleId); + return roleMapper.deleteRoleById(roleId); + } + + /** + * 批量删除角色信息 + * + * @param roleIds 需要删除的角色ID + * @return 结果 + */ + @Override + @Transactional + public int deleteRoleByIds(Long[] roleIds) + { + for (Long roleId : roleIds) + { + checkRoleAllowed(new SysRole(roleId)); + checkRoleDataScope(roleId); + SysRole role = selectRoleById(roleId); + if (countUserRoleByRoleId(roleId) > 0) + { + throw new ServiceException(String.format("%1$s已分配,不能删除", role.getRoleName())); + } + } + // 删除角色与菜单关联 + roleMenuMapper.deleteRoleMenu(roleIds); + // 删除角色与部门关联 + roleDeptMapper.deleteRoleDept(roleIds); + return roleMapper.deleteRoleByIds(roleIds); + } + + /** + * 取消授权用户角色 + * + * @param userRole 用户和角色关联信息 + * @return 结果 + */ + @Override + public int deleteAuthUser(SysUserRole userRole) + { + return userRoleMapper.deleteUserRoleInfo(userRole); + } + + /** + * 批量取消授权用户角色 + * + * @param roleId 角色ID + * @param userIds 需要取消授权的用户数据ID + * @return 结果 + */ + @Override + public int deleteAuthUsers(Long roleId, Long[] userIds) + { + return userRoleMapper.deleteUserRoleInfos(roleId, userIds); + } + + /** + * 批量选择授权用户角色 + * + * @param roleId 角色ID + * @param userIds 需要授权的用户数据ID + * @return 结果 + */ + @Override + public int insertAuthUsers(Long roleId, Long[] userIds) + { + // 新增用户与角色管理 + List list = new ArrayList(); + for (Long userId : userIds) + { + SysUserRole ur = new SysUserRole(); + ur.setUserId(userId); + ur.setRoleId(roleId); + list.add(ur); + } + return userRoleMapper.batchUserRole(list); + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.java new file mode 100644 index 0000000..3c5aaad --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.java @@ -0,0 +1,96 @@ +package com.ruoyi.system.service.impl; + +import org.springframework.stereotype.Service; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.system.domain.SysUserOnline; +import com.ruoyi.system.service.ISysUserOnlineService; + +/** + * 在线用户 服务层处理 + * + * @author #author# + */ +@Service +public class SysUserOnlineServiceImpl implements ISysUserOnlineService +{ + /** + * 通过登录地址查询信息 + * + * @param ipaddr 登录地址 + * @param user 用户信息 + * @return 在线用户信息 + */ + @Override + public SysUserOnline selectOnlineByIpaddr(String ipaddr, LoginUser user) + { + if (StringUtils.equals(ipaddr, user.getIpaddr())) + { + return loginUserToUserOnline(user); + } + return null; + } + + /** + * 通过用户名称查询信息 + * + * @param userName 用户名称 + * @param user 用户信息 + * @return 在线用户信息 + */ + @Override + public SysUserOnline selectOnlineByUserName(String userName, LoginUser user) + { + if (StringUtils.equals(userName, user.getUsername())) + { + return loginUserToUserOnline(user); + } + return null; + } + + /** + * 通过登录地址/用户名称查询信息 + * + * @param ipaddr 登录地址 + * @param userName 用户名称 + * @param user 用户信息 + * @return 在线用户信息 + */ + @Override + public SysUserOnline selectOnlineByInfo(String ipaddr, String userName, LoginUser user) + { + if (StringUtils.equals(ipaddr, user.getIpaddr()) && StringUtils.equals(userName, user.getUsername())) + { + return loginUserToUserOnline(user); + } + return null; + } + + /** + * 设置在线用户信息 + * + * @param user 用户信息 + * @return 在线用户 + */ + @Override + public SysUserOnline loginUserToUserOnline(LoginUser user) + { + if (StringUtils.isNull(user) || StringUtils.isNull(user.getUser())) + { + return null; + } + SysUserOnline sysUserOnline = new SysUserOnline(); + sysUserOnline.setTokenId(user.getToken()); + sysUserOnline.setUserName(user.getUsername()); + sysUserOnline.setIpaddr(user.getIpaddr()); + sysUserOnline.setLoginLocation(user.getLoginLocation()); + sysUserOnline.setBrowser(user.getBrowser()); + sysUserOnline.setOs(user.getOs()); + sysUserOnline.setLoginTime(user.getLoginTime()); + if (StringUtils.isNotNull(user.getUser().getDept())) + { + sysUserOnline.setDeptName(user.getUser().getDept().getDeptName()); + } + return sysUserOnline; + } +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java new file mode 100644 index 0000000..a0b037c --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java @@ -0,0 +1,543 @@ +package com.ruoyi.system.service.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import javax.validation.Validator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; +import com.ruoyi.common.annotation.DataScope; +import com.ruoyi.common.constant.UserConstants; +import com.ruoyi.common.core.domain.entity.SysRole; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.bean.BeanValidators; +import com.ruoyi.common.utils.spring.SpringUtils; +import com.ruoyi.system.domain.SysPost; +import com.ruoyi.system.domain.SysUserPost; +import com.ruoyi.system.domain.SysUserRole; +import com.ruoyi.system.mapper.SysPostMapper; +import com.ruoyi.system.mapper.SysRoleMapper; +import com.ruoyi.system.mapper.SysUserMapper; +import com.ruoyi.system.mapper.SysUserPostMapper; +import com.ruoyi.system.mapper.SysUserRoleMapper; +import com.ruoyi.system.service.ISysConfigService; +import com.ruoyi.system.service.ISysUserService; + +/** + * 用户 业务层处理 + * + * @author #author# + */ +@Service +public class SysUserServiceImpl implements ISysUserService +{ + private static final Logger log = LoggerFactory.getLogger(SysUserServiceImpl.class); + + @Autowired + private SysUserMapper userMapper; + + @Autowired + private SysRoleMapper roleMapper; + + @Autowired + private SysPostMapper postMapper; + + @Autowired + private SysUserRoleMapper userRoleMapper; + + @Autowired + private SysUserPostMapper userPostMapper; + + @Autowired + private ISysConfigService configService; + + @Autowired + protected Validator validator; + + /** + * 根据条件分页查询用户列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + @Override + @DataScope(deptAlias = "d", userAlias = "u") + public List selectUserList(SysUser user) + { + return userMapper.selectUserList(user); + } + + /** + * 根据条件分页查询已分配用户角色列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + @Override + @DataScope(deptAlias = "d", userAlias = "u") + public List selectAllocatedList(SysUser user) + { + return userMapper.selectAllocatedList(user); + } + + /** + * 根据条件分页查询未分配用户角色列表 + * + * @param user 用户信息 + * @return 用户信息集合信息 + */ + @Override + @DataScope(deptAlias = "d", userAlias = "u") + public List selectUnallocatedList(SysUser user) + { + return userMapper.selectUnallocatedList(user); + } + + /** + * 通过用户名查询用户 + * + * @param userName 用户名 + * @return 用户对象信息 + */ + @Override + public SysUser selectUserByUserName(String userName) + { + return userMapper.selectUserByUserName(userName); + } + + /** + * 通过用户ID查询用户 + * + * @param userId 用户ID + * @return 用户对象信息 + */ + @Override + public SysUser selectUserById(Long userId) + { + return userMapper.selectUserById(userId); + } + + /** + * 查询用户所属角色组 + * + * @param userName 用户名 + * @return 结果 + */ + @Override + public String selectUserRoleGroup(String userName) + { + List list = roleMapper.selectRolesByUserName(userName); + if (CollectionUtils.isEmpty(list)) + { + return StringUtils.EMPTY; + } + return list.stream().map(SysRole::getRoleName).collect(Collectors.joining(",")); + } + + /** + * 查询用户所属岗位组 + * + * @param userName 用户名 + * @return 结果 + */ + @Override + public String selectUserPostGroup(String userName) + { + List list = postMapper.selectPostsByUserName(userName); + if (CollectionUtils.isEmpty(list)) + { + return StringUtils.EMPTY; + } + return list.stream().map(SysPost::getPostName).collect(Collectors.joining(",")); + } + + /** + * 校验用户名称是否唯一 + * + * @param user 用户信息 + * @return 结果 + */ + @Override + public String checkUserNameUnique(SysUser user) + { + Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId(); + SysUser info = userMapper.checkUserNameUnique(user.getUserName()); + if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 校验手机号码是否唯一 + * + * @param user 用户信息 + * @return + */ + @Override + public String checkPhoneUnique(SysUser user) + { + Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId(); + SysUser info = userMapper.checkPhoneUnique(user.getPhonenumber()); + if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 校验email是否唯一 + * + * @param user 用户信息 + * @return + */ + @Override + public String checkEmailUnique(SysUser user) + { + Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId(); + SysUser info = userMapper.checkEmailUnique(user.getEmail()); + if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) + { + return UserConstants.NOT_UNIQUE; + } + return UserConstants.UNIQUE; + } + + /** + * 校验用户是否允许操作 + * + * @param user 用户信息 + */ + @Override + public void checkUserAllowed(SysUser user) + { + if (StringUtils.isNotNull(user.getUserId()) && user.isAdmin()) + { + throw new ServiceException("不允许操作超级管理员用户"); + } + } + + /** + * 校验用户是否有数据权限 + * + * @param userId 用户id + */ + @Override + public void checkUserDataScope(Long userId) + { + if (!SysUser.isAdmin(SecurityUtils.getUserId())) + { + SysUser user = new SysUser(); + user.setUserId(userId); + List users = SpringUtils.getAopProxy(this).selectUserList(user); + if (StringUtils.isEmpty(users)) + { + throw new ServiceException("没有权限访问用户数据!"); + } + } + } + + /** + * 新增保存用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + @Override + @Transactional + public int insertUser(SysUser user) + { + // 新增用户信息 + int rows = userMapper.insertUser(user); + // 新增用户岗位关联 + insertUserPost(user); + // 新增用户与角色管理 + insertUserRole(user); + return rows; + } + + /** + * 注册用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + @Override + public boolean registerUser(SysUser user) + { + return userMapper.insertUser(user) > 0; + } + + /** + * 修改保存用户信息 + * + * @param user 用户信息 + * @return 结果 + */ + @Override + @Transactional + public int updateUser(SysUser user) + { + Long userId = user.getUserId(); + // 删除用户与角色关联 + userRoleMapper.deleteUserRoleByUserId(userId); + // 新增用户与角色管理 + insertUserRole(user); + // 删除用户与岗位关联 + userPostMapper.deleteUserPostByUserId(userId); + // 新增用户与岗位管理 + insertUserPost(user); + return userMapper.updateUser(user); + } + + /** + * 用户授权角色 + * + * @param userId 用户ID + * @param roleIds 角色组 + */ + @Override + @Transactional + public void insertUserAuth(Long userId, Long[] roleIds) + { + userRoleMapper.deleteUserRoleByUserId(userId); + insertUserRole(userId, roleIds); + } + + /** + * 修改用户状态 + * + * @param user 用户信息 + * @return 结果 + */ + @Override + public int updateUserStatus(SysUser user) + { + return userMapper.updateUser(user); + } + + /** + * 修改用户基本信息 + * + * @param user 用户信息 + * @return 结果 + */ + @Override + public int updateUserProfile(SysUser user) + { + return userMapper.updateUser(user); + } + + /** + * 修改用户头像 + * + * @param userName 用户名 + * @param avatar 头像地址 + * @return 结果 + */ + @Override + public boolean updateUserAvatar(String userName, String avatar) + { + return userMapper.updateUserAvatar(userName, avatar) > 0; + } + + /** + * 重置用户密码 + * + * @param user 用户信息 + * @return 结果 + */ + @Override + public int resetPwd(SysUser user) + { + return userMapper.updateUser(user); + } + + /** + * 重置用户密码 + * + * @param userName 用户名 + * @param password 密码 + * @return 结果 + */ + @Override + public int resetUserPwd(String userName, String password) + { + return userMapper.resetUserPwd(userName, password); + } + + /** + * 新增用户角色信息 + * + * @param user 用户对象 + */ + public void insertUserRole(SysUser user) + { + this.insertUserRole(user.getUserId(), user.getRoleIds()); + } + + /** + * 新增用户岗位信息 + * + * @param user 用户对象 + */ + public void insertUserPost(SysUser user) + { + Long[] posts = user.getPostIds(); + if (StringUtils.isNotEmpty(posts)) + { + // 新增用户与岗位管理 + List list = new ArrayList(posts.length); + for (Long postId : posts) + { + SysUserPost up = new SysUserPost(); + up.setUserId(user.getUserId()); + up.setPostId(postId); + list.add(up); + } + userPostMapper.batchUserPost(list); + } + } + + /** + * 新增用户角色信息 + * + * @param userId 用户ID + * @param roleIds 角色组 + */ + public void insertUserRole(Long userId, Long[] roleIds) + { + if (StringUtils.isNotEmpty(roleIds)) + { + // 新增用户与角色管理 + List list = new ArrayList(roleIds.length); + for (Long roleId : roleIds) + { + SysUserRole ur = new SysUserRole(); + ur.setUserId(userId); + ur.setRoleId(roleId); + list.add(ur); + } + userRoleMapper.batchUserRole(list); + } + } + + /** + * 通过用户ID删除用户 + * + * @param userId 用户ID + * @return 结果 + */ + @Override + @Transactional + public int deleteUserById(Long userId) + { + // 删除用户与角色关联 + userRoleMapper.deleteUserRoleByUserId(userId); + // 删除用户与岗位表 + userPostMapper.deleteUserPostByUserId(userId); + return userMapper.deleteUserById(userId); + } + + /** + * 批量删除用户信息 + * + * @param userIds 需要删除的用户ID + * @return 结果 + */ + @Override + @Transactional + public int deleteUserByIds(Long[] userIds) + { + for (Long userId : userIds) + { + checkUserAllowed(new SysUser(userId)); + checkUserDataScope(userId); + } + // 删除用户与角色关联 + userRoleMapper.deleteUserRole(userIds); + // 删除用户与岗位关联 + userPostMapper.deleteUserPost(userIds); + return userMapper.deleteUserByIds(userIds); + } + + /** + * 导入用户数据 + * + * @param userList 用户数据列表 + * @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据 + * @param operName 操作用户 + * @return 结果 + */ + @Override + public String importUser(List userList, Boolean isUpdateSupport, String operName) + { + if (StringUtils.isNull(userList) || userList.size() == 0) + { + throw new ServiceException("导入用户数据不能为空!"); + } + int successNum = 0; + int failureNum = 0; + StringBuilder successMsg = new StringBuilder(); + StringBuilder failureMsg = new StringBuilder(); + String password = configService.selectConfigByKey("sys.user.initPassword"); + for (SysUser user : userList) + { + try + { + // 验证是否存在这个用户 + SysUser u = userMapper.selectUserByUserName(user.getUserName()); + if (StringUtils.isNull(u)) + { + BeanValidators.validateWithException(validator, user); + user.setPassword(SecurityUtils.encryptPassword(password)); + user.setCreateBy(operName); + this.insertUser(user); + successNum++; + successMsg.append("
" + successNum + "、账号 " + user.getUserName() + " 导入成功"); + } + else if (isUpdateSupport) + { + BeanValidators.validateWithException(validator, user); + checkUserAllowed(user); + checkUserDataScope(user.getUserId()); + user.setUpdateBy(operName); + this.updateUser(user); + successNum++; + successMsg.append("
" + successNum + "、账号 " + user.getUserName() + " 更新成功"); + } + else + { + failureNum++; + failureMsg.append("
" + failureNum + "、账号 " + user.getUserName() + " 已存在"); + } + } + catch (Exception e) + { + failureNum++; + String msg = "
" + failureNum + "、账号 " + user.getUserName() + " 导入失败:"; + failureMsg.append(msg + e.getMessage()); + log.error(msg, e); + } + } + if (failureNum > 0) + { + failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:"); + throw new ServiceException(failureMsg.toString()); + } + else + { + successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:"); + } + return successMsg.toString(); + } +} diff --git a/ruoyi-system/src/main/resources/mapper/system/SysConfigMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysConfigMapper.xml new file mode 100644 index 0000000..ca39f47 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/system/SysConfigMapper.xml @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + select config_id, config_name, config_key, config_value, config_type, create_by, create_time, update_by, update_time, remark + from sys_config + + + + + + + and config_id = #{configId} + + + and config_key = #{configKey} + + + + + + + + + + + + + + insert into sys_config ( + config_name, + config_key, + config_value, + config_type, + create_by, + remark, + create_time + )values( + #{configName}, + #{configKey}, + #{configValue}, + #{configType}, + #{createBy}, + #{remark}, + sysdate() + ) + + + + update sys_config + + config_name = #{configName}, + config_key = #{configKey}, + config_value = #{configValue}, + config_type = #{configType}, + update_by = #{updateBy}, + remark = #{remark}, + update_time = sysdate() + + where config_id = #{configId} + + + + delete from sys_config where config_id = #{configId} + + + + delete from sys_config where config_id in + + #{configId} + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml new file mode 100644 index 0000000..cf439f6 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml @@ -0,0 +1,159 @@ + + + + + + + + + + + + + + + + + + + + + + + + select d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.phone, d.email, d.status, d.del_flag, d.create_by, d.create_time + from sys_dept d + + + + + + + + + + + + + + + + + + + + insert into sys_dept( + dept_id, + parent_id, + dept_name, + ancestors, + order_num, + leader, + phone, + email, + status, + create_by, + create_time + )values( + #{deptId}, + #{parentId}, + #{deptName}, + #{ancestors}, + #{orderNum}, + #{leader}, + #{phone}, + #{email}, + #{status}, + #{createBy}, + sysdate() + ) + + + + update sys_dept + + parent_id = #{parentId}, + dept_name = #{deptName}, + ancestors = #{ancestors}, + order_num = #{orderNum}, + leader = #{leader}, + phone = #{phone}, + email = #{email}, + status = #{status}, + update_by = #{updateBy}, + update_time = sysdate() + + where dept_id = #{deptId} + + + + update sys_dept set ancestors = + + when #{item.deptId} then #{item.ancestors} + + where dept_id in + + #{item.deptId} + + + + + update sys_dept set status = '0' where dept_id in + + #{deptId} + + + + + update sys_dept set del_flag = '2' where dept_id = #{deptId} + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml new file mode 100644 index 0000000..8da9030 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + select dict_code, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark + from sys_dict_data + + + + + + + + + + + + + + delete from sys_dict_data where dict_code = #{dictCode} + + + + delete from sys_dict_data where dict_code in + + #{dictCode} + + + + + update sys_dict_data + + dict_sort = #{dictSort}, + dict_label = #{dictLabel}, + dict_value = #{dictValue}, + dict_type = #{dictType}, + css_class = #{cssClass}, + list_class = #{listClass}, + is_default = #{isDefault}, + status = #{status}, + remark = #{remark}, + update_by = #{updateBy}, + update_time = sysdate() + + where dict_code = #{dictCode} + + + + update sys_dict_data set dict_type = #{newDictType} where dict_type = #{oldDictType} + + + + insert into sys_dict_data( + dict_sort, + dict_label, + dict_value, + dict_type, + css_class, + list_class, + is_default, + status, + remark, + create_by, + create_time + )values( + #{dictSort}, + #{dictLabel}, + #{dictValue}, + #{dictType}, + #{cssClass}, + #{listClass}, + #{isDefault}, + #{status}, + #{remark}, + #{createBy}, + sysdate() + ) + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml new file mode 100644 index 0000000..55b4075 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + select dict_id, dict_name, dict_type, status, create_by, create_time, remark + from sys_dict_type + + + + + + + + + + + + + + delete from sys_dict_type where dict_id = #{dictId} + + + + delete from sys_dict_type where dict_id in + + #{dictId} + + + + + update sys_dict_type + + dict_name = #{dictName}, + dict_type = #{dictType}, + status = #{status}, + remark = #{remark}, + update_by = #{updateBy}, + update_time = sysdate() + + where dict_id = #{dictId} + + + + insert into sys_dict_type( + dict_name, + dict_type, + status, + remark, + create_by, + create_time + )values( + #{dictName}, + #{dictType}, + #{status}, + #{remark}, + #{createBy}, + sysdate() + ) + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/system/SysLogininforMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysLogininforMapper.xml new file mode 100644 index 0000000..b8178fa --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/system/SysLogininforMapper.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + insert into sys_logininfor (user_name, status, ipaddr, login_location, browser, os, msg, login_time) + values (#{userName}, #{status}, #{ipaddr}, #{loginLocation}, #{browser}, #{os}, #{msg}, sysdate()) + + + + + + delete from sys_logininfor where info_id in + + #{infoId} + + + + + truncate table sys_logininfor + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml new file mode 100644 index 0000000..6762007 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml @@ -0,0 +1,202 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select menu_id, menu_name, parent_id, order_num, path, component, `query`, is_frame, is_cache, menu_type, visible, status, ifnull(perms,'') as perms, icon, create_time + from sys_menu + + + + + + + + + + + + + + + + + + + + + + + + + + update sys_menu + + menu_name = #{menuName}, + parent_id = #{parentId}, + order_num = #{orderNum}, + path = #{path}, + component = #{component}, + `query` = #{query}, + is_frame = #{isFrame}, + is_cache = #{isCache}, + menu_type = #{menuType}, + visible = #{visible}, + status = #{status}, + perms = #{perms}, + icon = #{icon}, + remark = #{remark}, + update_by = #{updateBy}, + update_time = sysdate() + + where menu_id = #{menuId} + + + + insert into sys_menu( + menu_id, + parent_id, + menu_name, + order_num, + path, + component, + `query`, + is_frame, + is_cache, + menu_type, + visible, + status, + perms, + icon, + remark, + create_by, + create_time + )values( + #{menuId}, + #{parentId}, + #{menuName}, + #{orderNum}, + #{path}, + #{component}, + #{query}, + #{isFrame}, + #{isCache}, + #{menuType}, + #{visible}, + #{status}, + #{perms}, + #{icon}, + #{remark}, + #{createBy}, + sysdate() + ) + + + + delete from sys_menu where menu_id = #{menuId} + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml new file mode 100644 index 0000000..65d3079 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + select notice_id, notice_title, notice_type, cast(notice_content as char) as notice_content, status, create_by, create_time, update_by, update_time, remark + from sys_notice + + + + + + + + insert into sys_notice ( + notice_title, + notice_type, + notice_content, + status, + remark, + create_by, + create_time + )values( + #{noticeTitle}, + #{noticeType}, + #{noticeContent}, + #{status}, + #{remark}, + #{createBy}, + sysdate() + ) + + + + update sys_notice + + notice_title = #{noticeTitle}, + notice_type = #{noticeType}, + notice_content = #{noticeContent}, + status = #{status}, + update_by = #{updateBy}, + update_time = sysdate() + + where notice_id = #{noticeId} + + + + delete from sys_notice where notice_id = #{noticeId} + + + + delete from sys_notice where notice_id in + + #{noticeId} + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml new file mode 100644 index 0000000..018a747 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + select oper_id, title, business_type, method, request_method, operator_type, oper_name, dept_name, oper_url, oper_ip, oper_location, oper_param, json_result, status, error_msg, oper_time + from sys_oper_log + + + + insert into sys_oper_log(title, business_type, method, request_method, operator_type, oper_name, dept_name, oper_url, oper_ip, oper_location, oper_param, json_result, status, error_msg, oper_time) + values (#{title}, #{businessType}, #{method}, #{requestMethod}, #{operatorType}, #{operName}, #{deptName}, #{operUrl}, #{operIp}, #{operLocation}, #{operParam}, #{jsonResult}, #{status}, #{errorMsg}, sysdate()) + + + + + + delete from sys_oper_log where oper_id in + + #{operId} + + + + + + + truncate table sys_oper_log + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml new file mode 100644 index 0000000..227c459 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + select post_id, post_code, post_name, post_sort, status, create_by, create_time, remark + from sys_post + + + + + + + + + + + + + + + + + + update sys_post + + post_code = #{postCode}, + post_name = #{postName}, + post_sort = #{postSort}, + status = #{status}, + remark = #{remark}, + update_by = #{updateBy}, + update_time = sysdate() + + where post_id = #{postId} + + + + insert into sys_post( + post_id, + post_code, + post_name, + post_sort, + status, + remark, + create_by, + create_time + )values( + #{postId}, + #{postCode}, + #{postName}, + #{postSort}, + #{status}, + #{remark}, + #{createBy}, + sysdate() + ) + + + + delete from sys_post where post_id = #{postId} + + + + delete from sys_post where post_id in + + #{postId} + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml new file mode 100644 index 0000000..7c4139b --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + delete from sys_role_dept where role_id=#{roleId} + + + + + + delete from sys_role_dept where role_id in + + #{roleId} + + + + + insert into sys_role_dept(role_id, dept_id) values + + (#{item.roleId},#{item.deptId}) + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml new file mode 100644 index 0000000..52306c2 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + select distinct r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.menu_check_strictly, r.dept_check_strictly, + r.status, r.del_flag, r.create_time, r.remark + from sys_role r + left join sys_user_role ur on ur.role_id = r.role_id + left join sys_user u on u.user_id = ur.user_id + left join sys_dept d on u.dept_id = d.dept_id + + + + + + + + + + + + + + + + + + + + insert into sys_role( + role_id, + role_name, + role_key, + role_sort, + data_scope, + menu_check_strictly, + dept_check_strictly, + status, + remark, + create_by, + create_time + )values( + #{roleId}, + #{roleName}, + #{roleKey}, + #{roleSort}, + #{dataScope}, + #{menuCheckStrictly}, + #{deptCheckStrictly}, + #{status}, + #{remark}, + #{createBy}, + sysdate() + ) + + + + update sys_role + + role_name = #{roleName}, + role_key = #{roleKey}, + role_sort = #{roleSort}, + data_scope = #{dataScope}, + menu_check_strictly = #{menuCheckStrictly}, + dept_check_strictly = #{deptCheckStrictly}, + status = #{status}, + remark = #{remark}, + update_by = #{updateBy}, + update_time = sysdate() + + where role_id = #{roleId} + + + + update sys_role set del_flag = '2' where role_id = #{roleId} + + + + update sys_role set del_flag = '2' where role_id in + + #{roleId} + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml new file mode 100644 index 0000000..cb60a85 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + delete from sys_role_menu where role_id=#{roleId} + + + + delete from sys_role_menu where role_id in + + #{roleId} + + + + + insert into sys_role_menu(role_id, menu_id) values + + (#{item.roleId},#{item.menuId}) + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml new file mode 100644 index 0000000..d86c444 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml @@ -0,0 +1,221 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, + d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.status as dept_status, + r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status + from sys_user u + left join sys_dept d on u.dept_id = d.dept_id + left join sys_user_role ur on u.user_id = ur.user_id + left join sys_role r on r.role_id = ur.role_id + + + + + + + + + + + + + + + + + + + + insert into sys_user( + user_id, + dept_id, + user_name, + nick_name, + email, + avatar, + phonenumber, + sex, + password, + status, + create_by, + remark, + create_time + )values( + #{userId}, + #{deptId}, + #{userName}, + #{nickName}, + #{email}, + #{avatar}, + #{phonenumber}, + #{sex}, + #{password}, + #{status}, + #{createBy}, + #{remark}, + sysdate() + ) + + + + update sys_user + + dept_id = #{deptId}, + user_name = #{userName}, + nick_name = #{nickName}, + email = #{email}, + phonenumber = #{phonenumber}, + sex = #{sex}, + avatar = #{avatar}, + password = #{password}, + status = #{status}, + login_ip = #{loginIp}, + login_date = #{loginDate}, + update_by = #{updateBy}, + remark = #{remark}, + update_time = sysdate() + + where user_id = #{userId} + + + + update sys_user set status = #{status} where user_id = #{userId} + + + + update sys_user set avatar = #{avatar} where user_name = #{userName} + + + + update sys_user set password = #{password} where user_name = #{userName} + + + + update sys_user set del_flag = '2' where user_id = #{userId} + + + + update sys_user set del_flag = '2' where user_id in + + #{userId} + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml new file mode 100644 index 0000000..2b90bc4 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + delete from sys_user_post where user_id=#{userId} + + + + + + delete from sys_user_post where user_id in + + #{userId} + + + + + insert into sys_user_post(user_id, post_id) values + + (#{item.userId},#{item.postId}) + + + + \ No newline at end of file diff --git a/ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml new file mode 100644 index 0000000..dd72689 --- /dev/null +++ b/ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + delete from sys_user_role where user_id=#{userId} + + + + + + delete from sys_user_role where user_id in + + #{userId} + + + + + insert into sys_user_role(user_id, role_id) values + + (#{item.userId},#{item.roleId}) + + + + + delete from sys_user_role where user_id=#{userId} and role_id=#{roleId} + + + + delete from sys_user_role where role_id=#{roleId} and user_id in + + #{userId} + + + \ No newline at end of file diff --git a/sql/dba.sql b/sql/dba.sql new file mode 100644 index 0000000..a8156a0 --- /dev/null +++ b/sql/dba.sql @@ -0,0 +1,1251 @@ +/* + Navicat Premium Data Transfer + + Source Server : 本地数据库 + Source Server Type : MySQL + Source Server Version : 50738 + Source Host : localhost:3306 + Source Schema : dba + + Target Server Type : MySQL + Target Server Version : 50738 + File Encoding : 65001 + + Date: 01/04/2024 09:01:56 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for business_template +-- ---------------------------- +DROP TABLE IF EXISTS `business_template`; +CREATE TABLE `business_template` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', + `title` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '标题', + `context` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '内容', + `open` char(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '是否开放', + `create_by` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '修改人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间', + `deleted` bigint(20) NULL DEFAULT 0 COMMENT '是否删除', + `remark` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1774443791038652418 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '模版表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of business_template +-- ---------------------------- +INSERT INTO `business_template` VALUES (1774327297961119745, '测试', 'test', '1', 'admin', '2024-03-31 14:46:08', NULL, NULL, 0, NULL); +INSERT INTO `business_template` VALUES (1774432972057894914, '测试2', '123123', '0', 'admin', '2024-03-31 21:46:03', 'admin', '2024-03-31 21:56:33', 0, NULL); +INSERT INTO `business_template` VALUES (1774438528533504001, 'test1', '123', '1', 'test1', '2024-03-31 22:08:07', NULL, NULL, 0, NULL); +INSERT INTO `business_template` VALUES (1774443791038652417, '这是测试', '123123', '0', 'admin', '2024-03-31 22:29:02', 'admin', '2024-03-31 22:30:45', 0, NULL); + +-- ---------------------------- +-- Table structure for business_template_prop +-- ---------------------------- +DROP TABLE IF EXISTS `business_template_prop`; +CREATE TABLE `business_template_prop` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', + `title` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '标题', + `comp_type` char(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '组件类型(0单选框 1多选框)', + `field_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '字段名', + `plac_prompt` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '占位提示', + `default_value` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '默认值', + `optional_value` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '可选值', + `open` char(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '是否开放', + `temp_id` bigint(20) NULL DEFAULT NULL COMMENT '模版id', + `sort` int(6) NULL DEFAULT 0 COMMENT '排序', + `create_by` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '修改人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间', + `deleted` bigint(20) NULL DEFAULT 0 COMMENT '是否删除', + `remark` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1774444094773370883 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '模版属性表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of business_template_prop +-- ---------------------------- +INSERT INTO `business_template_prop` VALUES (12312312312, '爱好', '1', 'like', '请选择爱好', NULL, '0,电影|1,篮球', '1', 1774327297961119745, 0, 'admin', '2024-03-31 15:39:05', NULL, NULL, 0, NULL); +INSERT INTO `business_template_prop` VALUES (1774327728992964609, '性别', '0', 'sex', '请选择性别', NULL, '0,男|1,女', '1', 1774327297961119745, 0, 'admin', '2024-03-31 14:47:51', NULL, NULL, 0, NULL); +INSERT INTO `business_template_prop` VALUES (1774340622648369155, '姓名', '2', 'name', '请输入姓名', NULL, NULL, '1', 1774327297961119745, 0, 'admin', '2024-03-31 15:39:05', NULL, NULL, 0, NULL); +INSERT INTO `business_template_prop` VALUES (1774379056024895489, '多行', '3', 'doubleRows', '测试多行', NULL, NULL, NULL, 1774327297961119745, 0, 'admin', '2024-03-31 18:11:48', NULL, NULL, 0, NULL); +INSERT INTO `business_template_prop` VALUES (1774379229778132993, '密码', '4', 'pwd', NULL, NULL, NULL, NULL, 1774327297961119745, 0, 'admin', '2024-03-31 18:12:29', NULL, NULL, 0, NULL); +INSERT INTO `business_template_prop` VALUES (1774379365837160450, '计数器', '5', 'calcNum', NULL, NULL, NULL, NULL, 1774327297961119745, 0, 'admin', '2024-03-31 18:13:02', NULL, NULL, 0, NULL); +INSERT INTO `business_template_prop` VALUES (1774379705177325569, '下拉', '6', 'selected', NULL, NULL, '0,选择一|1,选择二', NULL, 1774327297961119745, 0, 'admin', '2024-03-31 18:14:23', NULL, NULL, 0, NULL); +INSERT INTO `business_template_prop` VALUES (1774379799100375041, '开关', '7', 'openOrClose', NULL, NULL, NULL, NULL, 1774327297961119745, 0, 'admin', '2024-03-31 18:14:45', NULL, NULL, 0, NULL); +INSERT INTO `business_template_prop` VALUES (1774379921293033474, '时间选择', '8', 'selectTime', NULL, NULL, NULL, NULL, 1774327297961119745, 0, 'admin', '2024-03-31 18:15:14', NULL, NULL, 0, NULL); +INSERT INTO `business_template_prop` VALUES (1774380021302018049, '时间范围', '9', 'beginEndTime', NULL, NULL, NULL, NULL, 1774327297961119745, 0, 'admin', '2024-03-31 18:15:38', NULL, NULL, 0, NULL); +INSERT INTO `business_template_prop` VALUES (1774441701222490114, 'ceshi', '2', '123', NULL, NULL, NULL, NULL, 1774438528533504001, 0, 'test1', '2024-03-31 22:20:44', NULL, NULL, 0, NULL); +INSERT INTO `business_template_prop` VALUES (1774444094773370882, '这是测试', '0', 'test', NULL, NULL, '1,张三|2,李四', NULL, 1774443791038652417, 0, 'admin', '2024-03-31 22:30:14', NULL, NULL, 0, NULL); + +-- ---------------------------- +-- Table structure for business_template_prop_value +-- ---------------------------- +DROP TABLE IF EXISTS `business_template_prop_value`; +CREATE TABLE `business_template_prop_value` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', + `prop_id` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '字段id', + `prop_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '字段名称', + `prop_type` char(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '字段类型', + `value_key` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '值键', + `value_text` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '值描述', + `value_sources` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '原值对象', + `temp_id` bigint(20) NULL DEFAULT NULL COMMENT '模版id', + `create_by` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '修改人', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间', + `deleted` bigint(20) NULL DEFAULT 0 COMMENT '是否删除', + `remark` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1774445984785481731 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '模版属性值表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of business_template_prop_value +-- ---------------------------- +INSERT INTO `business_template_prop_value` VALUES (1774396727323815937, '12312312312', 'like', '1', '[0, 1]', '电影,篮球', '[0, 1]', 1774327297961119745, 'admin', '2024-03-31 19:22:01', 'admin', '2024-03-31 21:40:05', 0, NULL); +INSERT INTO `business_template_prop_value` VALUES (1774396727407702018, '1774327728992964609', 'sex', '0', '1', '女', '1', 1774327297961119745, 'admin', '2024-03-31 19:22:01', 'admin', '2024-03-31 21:40:05', 0, NULL); +INSERT INTO `business_template_prop_value` VALUES (1774396727470616578, '1774340622648369155', 'name', '2', '123', '123', '123', 1774327297961119745, 'admin', '2024-03-31 19:22:01', 'admin', '2024-03-31 21:40:05', 0, NULL); +INSERT INTO `business_template_prop_value` VALUES (1774396727470616579, '1774379056024895489', 'doubleRows', '3', '1231231231234345436梵蒂冈合法的', '1231231231234345436梵蒂冈合法的', '1231231231234345436梵蒂冈合法的', 1774327297961119745, 'admin', '2024-03-31 19:22:01', 'admin', '2024-03-31 21:40:05', 0, NULL); +INSERT INTO `business_template_prop_value` VALUES (1774396727470616580, '1774379229778132993', 'pwd', '4', '123', '123', '123', 1774327297961119745, 'admin', '2024-03-31 19:22:01', 'admin', '2024-03-31 21:40:05', 0, NULL); +INSERT INTO `business_template_prop_value` VALUES (1774396727470616581, '1774379365837160450', 'calcNum', '5', '1', '1', '1', 1774327297961119745, 'admin', '2024-03-31 19:22:01', 'admin', '2024-03-31 21:40:05', 0, NULL); +INSERT INTO `business_template_prop_value` VALUES (1774396727470616582, '1774379705177325569', 'selected', '6', '1', '选择二', '1', 1774327297961119745, 'admin', '2024-03-31 19:22:01', 'admin', '2024-03-31 21:40:05', 0, NULL); +INSERT INTO `business_template_prop_value` VALUES (1774396727537725441, '1774379799100375041', 'openOrClose', '7', 'false', 'false', 'false', 1774327297961119745, 'admin', '2024-03-31 19:22:01', 'admin', '2024-03-31 21:40:05', 0, NULL); +INSERT INTO `business_template_prop_value` VALUES (1774396727537725442, '1774379921293033474', 'selectTime', '8', '19:21:53', '19:21:53', '19:21:53', 1774327297961119745, 'admin', '2024-03-31 19:22:01', 'admin', '2024-03-31 21:40:05', 0, NULL); +INSERT INTO `business_template_prop_value` VALUES (1774396727537725443, '1774380021302018049', 'beginEndTime', '9', '[08:00:00, 08:00:00]', '[08:00:00, 08:00:00]', '[08:00:00, 08:00:00]', 1774327297961119745, 'admin', '2024-03-31 19:22:01', 'admin', '2024-03-31 21:40:05', 0, NULL); +INSERT INTO `business_template_prop_value` VALUES (1774444309521735682, '1774444094773370882', 'test', '0', '1', '张三', '1', 1774443791038652417, 'admin', '2024-03-31 22:31:06', NULL, NULL, 0, NULL); +INSERT INTO `business_template_prop_value` VALUES (1774445984785481730, '1774441701222490114', '123', '2', '123', '123', '123', 1774438528533504001, 'test1', '2024-03-31 22:37:45', NULL, NULL, 0, NULL); + +-- ---------------------------- +-- Table structure for gen_table +-- ---------------------------- +DROP TABLE IF EXISTS `gen_table`; +CREATE TABLE `gen_table` ( + `table_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号', + `table_name` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '表名称', + `table_comment` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '表描述', + `sub_table_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '关联子表的表名', + `sub_table_fk_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '子表关联的外键名', + `class_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '实体类名称', + `tpl_category` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT 'crud' COMMENT '使用的模板(crud单表操作 tree树表操作)', + `package_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '生成包路径', + `module_name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '生成模块名', + `business_name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '生成业务名', + `function_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '生成功能名', + `function_author` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '生成功能作者', + `gen_type` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '生成代码方式(0zip压缩包 1自定义路径)', + `gen_path` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '/' COMMENT '生成路径(不填默认项目路径)', + `options` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '其它生成选项', + `create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', + `remark` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注', + PRIMARY KEY (`table_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '代码生成业务表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of gen_table +-- ---------------------------- +INSERT INTO `gen_table` VALUES (1, 'business_template', '问卷调查表', NULL, NULL, 'BusinessTemplate', 'crud', 'com.ruoyi.business', 'business', 'template', '模版管理', 'ruoyi', '0', '/', '{\"parentMenuId\":\"2000\"}', 'admin', '2024-03-31 03:13:37', '', '2024-03-31 14:59:13', NULL); +INSERT INTO `gen_table` VALUES (2, 'business_template_prop', '模版属性表', NULL, NULL, 'BusinessTemplateProp', 'crud', 'com.ruoyi.business', 'business', 'templateProp', '模版属性', 'ruoyi', '0', '/', '{\"parentMenuId\":2000}', 'admin', '2024-03-31 14:23:17', '', '2024-03-31 14:35:33', NULL); +INSERT INTO `gen_table` VALUES (3, 'business_template_prop_value', '模版属性值表', NULL, NULL, 'BusinessTemplatePropValue', 'crud', 'com.ruoyi.business', 'business', 'templatePropValue', '模版属性值', 'ruoyi', '0', '/', '{\"parentMenuId\":2000}', 'admin', '2024-03-31 15:54:59', '', '2024-03-31 15:56:23', NULL); + +-- ---------------------------- +-- Table structure for gen_table_column +-- ---------------------------- +DROP TABLE IF EXISTS `gen_table_column`; +CREATE TABLE `gen_table_column` ( + `column_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号', + `table_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '归属表编号', + `column_name` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '列名称', + `column_comment` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '列描述', + `column_type` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '列类型', + `java_type` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'JAVA类型', + `java_field` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'JAVA字段名', + `is_pk` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '是否主键(1是)', + `is_increment` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '是否自增(1是)', + `is_required` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '是否必填(1是)', + `is_insert` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '是否为插入字段(1是)', + `is_edit` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '是否编辑字段(1是)', + `is_list` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '是否列表字段(1是)', + `is_query` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '是否查询字段(1是)', + `query_type` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT 'EQ' COMMENT '查询方式(等于、不等于、大于、小于、范围)', + `html_type` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '显示类型(文本框、文本域、下拉框、复选框、单选框、日期控件)', + `dict_type` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '字典类型', + `sort` int(11) NULL DEFAULT NULL COMMENT '排序', + `create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`column_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 40 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '代码生成业务表字段' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of gen_table_column +-- ---------------------------- +INSERT INTO `gen_table_column` VALUES (1, '1', 'id', '主键', 'bigint(20)', 'Long', 'id', '1', '1', NULL, '1', NULL, NULL, NULL, 'EQ', 'input', '', 1, 'admin', '2024-03-31 03:13:37', '', '2024-03-31 14:59:13'); +INSERT INTO `gen_table_column` VALUES (2, '1', 'title', '标题', 'varchar(100)', 'String', 'title', '0', '0', NULL, '1', '1', '1', '1', 'EQ', 'input', '', 2, 'admin', '2024-03-31 03:13:37', '', '2024-03-31 14:59:13'); +INSERT INTO `gen_table_column` VALUES (3, '1', 'context', '内容', 'varchar(100)', 'String', 'context', '0', '0', NULL, '1', '1', '1', '1', 'EQ', 'input', '', 3, 'admin', '2024-03-31 03:13:37', '', '2024-03-31 14:59:13'); +INSERT INTO `gen_table_column` VALUES (5, '1', 'create_by', '创建人', 'varchar(100)', 'String', 'createBy', '0', '0', NULL, '0', NULL, NULL, NULL, 'EQ', 'input', '', 5, 'admin', '2024-03-31 03:13:37', '', '2024-03-31 14:59:13'); +INSERT INTO `gen_table_column` VALUES (6, '1', 'create_time', '创建时间', 'datetime', 'Date', 'createTime', '0', '0', NULL, '0', NULL, NULL, NULL, 'EQ', 'datetime', '', 6, 'admin', '2024-03-31 03:13:37', '', '2024-03-31 14:59:13'); +INSERT INTO `gen_table_column` VALUES (7, '1', 'update_by', '修改人', 'varchar(100)', 'String', 'updateBy', '0', '0', NULL, '0', '0', NULL, NULL, 'EQ', 'input', '', 7, 'admin', '2024-03-31 03:13:37', '', '2024-03-31 14:59:13'); +INSERT INTO `gen_table_column` VALUES (8, '1', 'update_time', '修改时间', 'datetime', 'Date', 'updateTime', '0', '0', NULL, '0', '0', NULL, NULL, 'EQ', 'datetime', '', 8, 'admin', '2024-03-31 03:13:37', '', '2024-03-31 14:59:13'); +INSERT INTO `gen_table_column` VALUES (9, '1', 'deleted', '是否删除', 'bigint(20)', 'Long', 'deleted', '0', '0', NULL, '0', '0', '0', '0', 'EQ', 'input', '', 9, 'admin', '2024-03-31 03:13:37', '', '2024-03-31 14:59:13'); +INSERT INTO `gen_table_column` VALUES (10, '1', 'remark', '备注', 'varchar(100)', 'String', 'remark', '0', '0', NULL, '0', '0', '0', NULL, 'EQ', 'input', '', 10, 'admin', '2024-03-31 03:13:37', '', '2024-03-31 14:59:13'); +INSERT INTO `gen_table_column` VALUES (11, '1', 'open', '是否开放', 'char(10)', 'String', 'open', '0', '0', NULL, '1', '1', '1', '1', 'EQ', 'select', 'open', 4, '', '2024-03-31 14:23:14', '', '2024-03-31 14:59:13'); +INSERT INTO `gen_table_column` VALUES (12, '2', 'id', '主键', 'bigint(20)', 'Long', 'id', '1', '1', NULL, '0', NULL, NULL, NULL, 'EQ', 'input', '', 1, 'admin', '2024-03-31 14:23:17', '', '2024-03-31 14:35:33'); +INSERT INTO `gen_table_column` VALUES (13, '2', 'title', '标题', 'varchar(100)', 'String', 'title', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'input', '', 2, 'admin', '2024-03-31 14:23:17', '', '2024-03-31 14:35:33'); +INSERT INTO `gen_table_column` VALUES (14, '2', 'comp_type', '组件类型(0单选框 1多选框)', 'char(10)', 'String', 'compType', '0', '0', '1', '1', '1', '1', '1', 'EQ', 'select', 'comp_type', 3, 'admin', '2024-03-31 14:23:17', '', '2024-03-31 14:35:33'); +INSERT INTO `gen_table_column` VALUES (15, '2', 'field_name', '字段名', 'varchar(100)', 'String', 'fieldName', '0', '0', '1', '1', '1', '1', '1', 'LIKE', 'input', '', 4, 'admin', '2024-03-31 14:23:17', '', '2024-03-31 14:35:33'); +INSERT INTO `gen_table_column` VALUES (16, '2', 'plac_prompt', '占位提示', 'varchar(100)', 'String', 'placPrompt', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'input', '', 5, 'admin', '2024-03-31 14:23:17', '', '2024-03-31 14:35:33'); +INSERT INTO `gen_table_column` VALUES (17, '2', 'default_value', '默认值', 'text', 'String', 'defaultValue', '0', '0', '0', '1', '1', '1', '1', 'EQ', 'textarea', '', 6, 'admin', '2024-03-31 14:23:17', '', '2024-03-31 14:35:33'); +INSERT INTO `gen_table_column` VALUES (18, '2', 'open', '是否开放', 'char(10)', 'String', 'open', '0', '0', NULL, '1', '1', '1', '1', 'EQ', 'input', '', 8, 'admin', '2024-03-31 14:23:17', '', '2024-03-31 14:35:33'); +INSERT INTO `gen_table_column` VALUES (19, '2', 'temp_id', '模版id', 'bigint(20)', 'Long', 'tempId', '0', '0', NULL, '1', '1', '1', '1', 'EQ', 'select', '', 9, 'admin', '2024-03-31 14:23:17', '', '2024-03-31 14:35:33'); +INSERT INTO `gen_table_column` VALUES (20, '2', 'create_by', '创建人', 'varchar(100)', 'String', 'createBy', '0', '0', NULL, '0', NULL, NULL, NULL, 'EQ', 'input', '', 10, 'admin', '2024-03-31 14:23:17', '', '2024-03-31 14:35:33'); +INSERT INTO `gen_table_column` VALUES (21, '2', 'create_time', '创建时间', 'datetime', 'Date', 'createTime', '0', '0', NULL, '0', NULL, NULL, NULL, 'EQ', 'datetime', '', 11, 'admin', '2024-03-31 14:23:17', '', '2024-03-31 14:35:33'); +INSERT INTO `gen_table_column` VALUES (22, '2', 'update_by', '修改人', 'varchar(100)', 'String', 'updateBy', '0', '0', NULL, '0', '0', NULL, NULL, 'EQ', 'input', '', 12, 'admin', '2024-03-31 14:23:17', '', '2024-03-31 14:35:33'); +INSERT INTO `gen_table_column` VALUES (23, '2', 'update_time', '修改时间', 'datetime', 'Date', 'updateTime', '0', '0', NULL, '0', '0', NULL, NULL, 'EQ', 'datetime', '', 13, 'admin', '2024-03-31 14:23:17', '', '2024-03-31 14:35:33'); +INSERT INTO `gen_table_column` VALUES (24, '2', 'deleted', '是否删除', 'bigint(20)', 'Long', 'deleted', '0', '0', NULL, '0', '0', '0', '0', 'EQ', 'input', '', 14, 'admin', '2024-03-31 14:23:17', '', '2024-03-31 14:35:33'); +INSERT INTO `gen_table_column` VALUES (25, '2', 'remark', '备注', 'varchar(100)', 'String', 'remark', '0', '0', NULL, '0', '0', '0', NULL, 'EQ', 'input', '', 15, 'admin', '2024-03-31 14:23:17', '', '2024-03-31 14:35:33'); +INSERT INTO `gen_table_column` VALUES (26, '2', 'optional_value', '可选值', 'varchar(100)', 'String', 'optionalValue', '0', '0', NULL, '1', '1', '1', '1', 'EQ', 'input', '', 7, '', '2024-03-31 14:27:58', '', '2024-03-31 14:35:33'); +INSERT INTO `gen_table_column` VALUES (27, '3', 'id', '主键', 'bigint(20)', 'Long', 'id', '1', '1', NULL, '1', NULL, NULL, NULL, 'EQ', 'input', '', 1, 'admin', '2024-03-31 15:54:59', '', '2024-03-31 18:23:24'); +INSERT INTO `gen_table_column` VALUES (28, '3', 'prop_id', '字段id', 'varchar(100)', 'String', 'propId', '0', '0', NULL, '1', '1', '1', '1', 'EQ', 'input', '', 2, 'admin', '2024-03-31 15:54:59', '', '2024-03-31 18:23:24'); +INSERT INTO `gen_table_column` VALUES (29, '3', 'prop_name', '字段名称', 'char(10)', 'String', 'propName', '0', '0', NULL, '1', '1', '1', '1', 'LIKE', 'input', '', 3, 'admin', '2024-03-31 15:54:59', '', '2024-03-31 18:23:24'); +INSERT INTO `gen_table_column` VALUES (30, '3', 'value_key', '值键', 'varchar(100)', 'String', 'valueKey', '0', '0', NULL, '1', '1', '1', '1', 'EQ', 'input', '', 5, 'admin', '2024-03-31 15:54:59', '', '2024-03-31 18:23:24'); +INSERT INTO `gen_table_column` VALUES (31, '3', 'value_text', '值描述', 'varchar(100)', 'String', 'valueText', '0', '0', NULL, '1', '1', '1', '1', 'EQ', 'input', '', 6, 'admin', '2024-03-31 15:54:59', '', '2024-03-31 18:23:24'); +INSERT INTO `gen_table_column` VALUES (32, '3', 'temp_id', '模版id', 'bigint(20)', 'Long', 'tempId', '0', '0', NULL, '1', '1', '1', '1', 'EQ', 'input', '', 7, 'admin', '2024-03-31 15:54:59', '', '2024-03-31 18:23:24'); +INSERT INTO `gen_table_column` VALUES (33, '3', 'create_by', '创建人', 'varchar(100)', 'String', 'createBy', '0', '0', NULL, '1', NULL, NULL, NULL, 'EQ', 'input', '', 8, 'admin', '2024-03-31 15:54:59', '', '2024-03-31 18:23:24'); +INSERT INTO `gen_table_column` VALUES (34, '3', 'create_time', '创建时间', 'datetime', 'Date', 'createTime', '0', '0', NULL, '1', NULL, NULL, NULL, 'EQ', 'datetime', '', 9, 'admin', '2024-03-31 15:54:59', '', '2024-03-31 18:23:24'); +INSERT INTO `gen_table_column` VALUES (35, '3', 'update_by', '修改人', 'varchar(100)', 'String', 'updateBy', '0', '0', NULL, '1', '1', NULL, NULL, 'EQ', 'input', '', 10, 'admin', '2024-03-31 15:54:59', '', '2024-03-31 18:23:24'); +INSERT INTO `gen_table_column` VALUES (36, '3', 'update_time', '修改时间', 'datetime', 'Date', 'updateTime', '0', '0', NULL, '1', '1', NULL, NULL, 'EQ', 'datetime', '', 11, 'admin', '2024-03-31 15:54:59', '', '2024-03-31 18:23:24'); +INSERT INTO `gen_table_column` VALUES (37, '3', 'deleted', '是否删除', 'bigint(20)', 'Long', 'deleted', '0', '0', NULL, '1', '1', '1', '1', 'EQ', 'input', '', 12, 'admin', '2024-03-31 15:54:59', '', '2024-03-31 18:23:24'); +INSERT INTO `gen_table_column` VALUES (38, '3', 'remark', '备注', 'varchar(100)', 'String', 'remark', '0', '0', NULL, '1', '1', '1', NULL, 'EQ', 'input', '', 13, 'admin', '2024-03-31 15:54:59', '', '2024-03-31 18:23:24'); +INSERT INTO `gen_table_column` VALUES (39, '3', 'prop_type', '字段类型', 'char(10)', 'String', 'propType', '0', '0', NULL, '1', '1', '1', '1', 'EQ', 'select', '', 4, '', '2024-03-31 18:23:24', '', NULL); + +-- ---------------------------- +-- Table structure for qrtz_blob_triggers +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_blob_triggers`; +CREATE TABLE `qrtz_blob_triggers` ( + `sched_name` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '调度名称', + `trigger_name` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'qrtz_triggers表trigger_name的外键', + `trigger_group` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'qrtz_triggers表trigger_group的外键', + `blob_data` blob NULL COMMENT '存放持久化Trigger对象', + PRIMARY KEY (`sched_name`, `trigger_name`, `trigger_group`) USING BTREE, + CONSTRAINT `qrtz_blob_triggers_ibfk_1` FOREIGN KEY (`sched_name`, `trigger_name`, `trigger_group`) REFERENCES `qrtz_triggers` (`sched_name`, `trigger_name`, `trigger_group`) ON DELETE RESTRICT ON UPDATE RESTRICT +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'Blob类型的触发器表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of qrtz_blob_triggers +-- ---------------------------- + +-- ---------------------------- +-- Table structure for qrtz_calendars +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_calendars`; +CREATE TABLE `qrtz_calendars` ( + `sched_name` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '调度名称', + `calendar_name` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '日历名称', + `calendar` blob NOT NULL COMMENT '存放持久化calendar对象', + PRIMARY KEY (`sched_name`, `calendar_name`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '日历信息表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of qrtz_calendars +-- ---------------------------- + +-- ---------------------------- +-- Table structure for qrtz_cron_triggers +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_cron_triggers`; +CREATE TABLE `qrtz_cron_triggers` ( + `sched_name` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '调度名称', + `trigger_name` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'qrtz_triggers表trigger_name的外键', + `trigger_group` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'qrtz_triggers表trigger_group的外键', + `cron_expression` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'cron表达式', + `time_zone_id` varchar(80) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '时区', + PRIMARY KEY (`sched_name`, `trigger_name`, `trigger_group`) USING BTREE, + CONSTRAINT `qrtz_cron_triggers_ibfk_1` FOREIGN KEY (`sched_name`, `trigger_name`, `trigger_group`) REFERENCES `qrtz_triggers` (`sched_name`, `trigger_name`, `trigger_group`) ON DELETE RESTRICT ON UPDATE RESTRICT +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = 'Cron类型的触发器表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of qrtz_cron_triggers +-- ---------------------------- + +-- ---------------------------- +-- Table structure for qrtz_fired_triggers +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_fired_triggers`; +CREATE TABLE `qrtz_fired_triggers` ( + `sched_name` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '调度名称', + `entry_id` varchar(95) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '调度器实例id', + `trigger_name` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'qrtz_triggers表trigger_name的外键', + `trigger_group` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'qrtz_triggers表trigger_group的外键', + `instance_name` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '调度器实例名', + `fired_time` bigint(13) NOT NULL COMMENT '触发的时间', + `sched_time` bigint(13) NOT NULL COMMENT '定时器制定的时间', + `priority` int(11) NOT NULL COMMENT '优先级', + `state` varchar(16) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '状态', + `job_name` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '任务名称', + `job_group` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '任务组名', + `is_nonconcurrent` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '是否并发', + `requests_recovery` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '是否接受恢复执行', + PRIMARY KEY (`sched_name`, `entry_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '已触发的触发器表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of qrtz_fired_triggers +-- ---------------------------- + +-- ---------------------------- +-- Table structure for qrtz_job_details +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_job_details`; +CREATE TABLE `qrtz_job_details` ( + `sched_name` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '调度名称', + `job_name` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '任务名称', + `job_group` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '任务组名', + `description` varchar(250) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '相关介绍', + `job_class_name` varchar(250) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '执行任务类名称', + `is_durable` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '是否持久化', + `is_nonconcurrent` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '是否并发', + `is_update_data` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '是否更新数据', + `requests_recovery` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '是否接受恢复执行', + `job_data` blob NULL COMMENT '存放持久化job对象', + PRIMARY KEY (`sched_name`, `job_name`, `job_group`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '任务详细信息表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of qrtz_job_details +-- ---------------------------- + +-- ---------------------------- +-- Table structure for qrtz_locks +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_locks`; +CREATE TABLE `qrtz_locks` ( + `sched_name` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '调度名称', + `lock_name` varchar(40) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '悲观锁名称', + PRIMARY KEY (`sched_name`, `lock_name`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '存储的悲观锁信息表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of qrtz_locks +-- ---------------------------- + +-- ---------------------------- +-- Table structure for qrtz_paused_trigger_grps +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_paused_trigger_grps`; +CREATE TABLE `qrtz_paused_trigger_grps` ( + `sched_name` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '调度名称', + `trigger_group` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'qrtz_triggers表trigger_group的外键', + PRIMARY KEY (`sched_name`, `trigger_group`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '暂停的触发器表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of qrtz_paused_trigger_grps +-- ---------------------------- + +-- ---------------------------- +-- Table structure for qrtz_scheduler_state +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_scheduler_state`; +CREATE TABLE `qrtz_scheduler_state` ( + `sched_name` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '调度名称', + `instance_name` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '实例名称', + `last_checkin_time` bigint(13) NOT NULL COMMENT '上次检查时间', + `checkin_interval` bigint(13) NOT NULL COMMENT '检查间隔时间', + PRIMARY KEY (`sched_name`, `instance_name`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '调度器状态表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of qrtz_scheduler_state +-- ---------------------------- + +-- ---------------------------- +-- Table structure for qrtz_simple_triggers +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_simple_triggers`; +CREATE TABLE `qrtz_simple_triggers` ( + `sched_name` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '调度名称', + `trigger_name` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'qrtz_triggers表trigger_name的外键', + `trigger_group` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'qrtz_triggers表trigger_group的外键', + `repeat_count` bigint(7) NOT NULL COMMENT '重复的次数统计', + `repeat_interval` bigint(12) NOT NULL COMMENT '重复的间隔时间', + `times_triggered` bigint(10) NOT NULL COMMENT '已经触发的次数', + PRIMARY KEY (`sched_name`, `trigger_name`, `trigger_group`) USING BTREE, + CONSTRAINT `qrtz_simple_triggers_ibfk_1` FOREIGN KEY (`sched_name`, `trigger_name`, `trigger_group`) REFERENCES `qrtz_triggers` (`sched_name`, `trigger_name`, `trigger_group`) ON DELETE RESTRICT ON UPDATE RESTRICT +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '简单触发器的信息表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of qrtz_simple_triggers +-- ---------------------------- + +-- ---------------------------- +-- Table structure for qrtz_simprop_triggers +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_simprop_triggers`; +CREATE TABLE `qrtz_simprop_triggers` ( + `sched_name` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '调度名称', + `trigger_name` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'qrtz_triggers表trigger_name的外键', + `trigger_group` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'qrtz_triggers表trigger_group的外键', + `str_prop_1` varchar(512) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'String类型的trigger的第一个参数', + `str_prop_2` varchar(512) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'String类型的trigger的第二个参数', + `str_prop_3` varchar(512) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'String类型的trigger的第三个参数', + `int_prop_1` int(11) NULL DEFAULT NULL COMMENT 'int类型的trigger的第一个参数', + `int_prop_2` int(11) NULL DEFAULT NULL COMMENT 'int类型的trigger的第二个参数', + `long_prop_1` bigint(20) NULL DEFAULT NULL COMMENT 'long类型的trigger的第一个参数', + `long_prop_2` bigint(20) NULL DEFAULT NULL COMMENT 'long类型的trigger的第二个参数', + `dec_prop_1` decimal(13, 4) NULL DEFAULT NULL COMMENT 'decimal类型的trigger的第一个参数', + `dec_prop_2` decimal(13, 4) NULL DEFAULT NULL COMMENT 'decimal类型的trigger的第二个参数', + `bool_prop_1` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'Boolean类型的trigger的第一个参数', + `bool_prop_2` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'Boolean类型的trigger的第二个参数', + PRIMARY KEY (`sched_name`, `trigger_name`, `trigger_group`) USING BTREE, + CONSTRAINT `qrtz_simprop_triggers_ibfk_1` FOREIGN KEY (`sched_name`, `trigger_name`, `trigger_group`) REFERENCES `qrtz_triggers` (`sched_name`, `trigger_name`, `trigger_group`) ON DELETE RESTRICT ON UPDATE RESTRICT +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '同步机制的行锁表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of qrtz_simprop_triggers +-- ---------------------------- + +-- ---------------------------- +-- Table structure for qrtz_triggers +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_triggers`; +CREATE TABLE `qrtz_triggers` ( + `sched_name` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '调度名称', + `trigger_name` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '触发器的名字', + `trigger_group` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '触发器所属组的名字', + `job_name` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'qrtz_job_details表job_name的外键', + `job_group` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'qrtz_job_details表job_group的外键', + `description` varchar(250) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '相关介绍', + `next_fire_time` bigint(13) NULL DEFAULT NULL COMMENT '上一次触发时间(毫秒)', + `prev_fire_time` bigint(13) NULL DEFAULT NULL COMMENT '下一次触发时间(默认为-1表示不触发)', + `priority` int(11) NULL DEFAULT NULL COMMENT '优先级', + `trigger_state` varchar(16) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '触发器状态', + `trigger_type` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '触发器的类型', + `start_time` bigint(13) NOT NULL COMMENT '开始时间', + `end_time` bigint(13) NULL DEFAULT NULL COMMENT '结束时间', + `calendar_name` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '日程表名称', + `misfire_instr` smallint(2) NULL DEFAULT NULL COMMENT '补偿执行的策略', + `job_data` blob NULL COMMENT '存放持久化job对象', + PRIMARY KEY (`sched_name`, `trigger_name`, `trigger_group`) USING BTREE, + INDEX `sched_name`(`sched_name`, `job_name`, `job_group`) USING BTREE, + CONSTRAINT `qrtz_triggers_ibfk_1` FOREIGN KEY (`sched_name`, `job_name`, `job_group`) REFERENCES `qrtz_job_details` (`sched_name`, `job_name`, `job_group`) ON DELETE RESTRICT ON UPDATE RESTRICT +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '触发器详细信息表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of qrtz_triggers +-- ---------------------------- + +-- ---------------------------- +-- Table structure for sys_config +-- ---------------------------- +DROP TABLE IF EXISTS `sys_config`; +CREATE TABLE `sys_config` ( + `config_id` int(5) NOT NULL AUTO_INCREMENT COMMENT '参数主键', + `config_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '参数名称', + `config_key` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '参数键名', + `config_value` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '参数键值', + `config_type` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT 'N' COMMENT '系统内置(Y是 N否)', + `create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', + `remark` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注', + PRIMARY KEY (`config_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '参数配置表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_config +-- ---------------------------- +INSERT INTO `sys_config` VALUES (1, '主框架页-默认皮肤样式名称', 'sys.index.skinName', 'skin-blue', 'Y', 'admin', '2024-03-31 01:19:12', '', NULL, '蓝色 skin-blue、绿色 skin-green、紫色 skin-purple、红色 skin-red、黄色 skin-yellow'); +INSERT INTO `sys_config` VALUES (2, '用户管理-账号初始密码', 'sys.user.initPassword', '123456', 'Y', 'admin', '2024-03-31 01:19:12', '', NULL, '初始化密码 123456'); +INSERT INTO `sys_config` VALUES (3, '主框架页-侧边栏主题', 'sys.index.sideTheme', 'theme-dark', 'Y', 'admin', '2024-03-31 01:19:12', '', NULL, '深色主题theme-dark,浅色主题theme-light'); +INSERT INTO `sys_config` VALUES (4, '账号自助-验证码开关', 'sys.account.captchaEnabled', 'true', 'Y', 'admin', '2024-03-31 01:19:12', '', NULL, '是否开启验证码功能(true开启,false关闭)'); +INSERT INTO `sys_config` VALUES (5, '账号自助-是否开启用户注册功能', 'sys.account.registerUser', 'true', 'Y', 'admin', '2024-03-31 01:19:12', 'admin', '2024-03-31 02:03:41', '是否开启注册用户功能(true开启,false关闭)'); + +-- ---------------------------- +-- Table structure for sys_dept +-- ---------------------------- +DROP TABLE IF EXISTS `sys_dept`; +CREATE TABLE `sys_dept` ( + `dept_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '部门id', + `parent_id` bigint(20) NULL DEFAULT 0 COMMENT '父部门id', + `ancestors` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '祖级列表', + `dept_name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '部门名称', + `order_num` int(4) NULL DEFAULT 0 COMMENT '显示顺序', + `leader` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '负责人', + `phone` varchar(11) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '联系电话', + `email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '邮箱', + `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '部门状态(0正常 1停用)', + `del_flag` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '删除标志(0代表存在 2代表删除)', + `create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`dept_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 101 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '部门表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_dept +-- ---------------------------- +INSERT INTO `sys_dept` VALUES (100, 0, '0', '总公司', 0, '开发者', '15888888888', 'ry@qq.com', '0', '0', 'admin', '2024-03-31 01:19:09', '', NULL); + +-- ---------------------------- +-- Table structure for sys_dict_data +-- ---------------------------- +DROP TABLE IF EXISTS `sys_dict_data`; +CREATE TABLE `sys_dict_data` ( + `dict_code` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '字典编码', + `dict_sort` int(4) NULL DEFAULT 0 COMMENT '字典排序', + `dict_label` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '字典标签', + `dict_value` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '字典键值', + `dict_type` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '字典类型', + `css_class` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '样式属性(其他样式扩展)', + `list_class` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '表格回显样式', + `is_default` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT 'N' COMMENT '是否默认(Y是 N否)', + `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '状态(0正常 1停用)', + `create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', + `remark` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注', + PRIMARY KEY (`dict_code`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 112 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '字典数据表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_dict_data +-- ---------------------------- +INSERT INTO `sys_dict_data` VALUES (1, 1, '男', '0', 'sys_user_sex', '', '', 'Y', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '性别男'); +INSERT INTO `sys_dict_data` VALUES (2, 2, '女', '1', 'sys_user_sex', '', '', 'N', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '性别女'); +INSERT INTO `sys_dict_data` VALUES (3, 3, '未知', '2', 'sys_user_sex', '', '', 'N', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '性别未知'); +INSERT INTO `sys_dict_data` VALUES (4, 1, '显示', '0', 'sys_show_hide', '', 'primary', 'Y', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '显示菜单'); +INSERT INTO `sys_dict_data` VALUES (5, 2, '隐藏', '1', 'sys_show_hide', '', 'danger', 'N', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '隐藏菜单'); +INSERT INTO `sys_dict_data` VALUES (6, 1, '正常', '0', 'sys_normal_disable', '', 'primary', 'Y', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '正常状态'); +INSERT INTO `sys_dict_data` VALUES (7, 2, '停用', '1', 'sys_normal_disable', '', 'danger', 'N', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '停用状态'); +INSERT INTO `sys_dict_data` VALUES (8, 1, '正常', '0', 'sys_job_status', '', 'primary', 'Y', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '正常状态'); +INSERT INTO `sys_dict_data` VALUES (9, 2, '暂停', '1', 'sys_job_status', '', 'danger', 'N', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '停用状态'); +INSERT INTO `sys_dict_data` VALUES (10, 1, '默认', 'DEFAULT', 'sys_job_group', '', '', 'Y', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '默认分组'); +INSERT INTO `sys_dict_data` VALUES (11, 2, '系统', 'SYSTEM', 'sys_job_group', '', '', 'N', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '系统分组'); +INSERT INTO `sys_dict_data` VALUES (12, 1, '是', 'Y', 'sys_yes_no', '', 'primary', 'Y', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '系统默认是'); +INSERT INTO `sys_dict_data` VALUES (13, 2, '否', 'N', 'sys_yes_no', '', 'danger', 'N', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '系统默认否'); +INSERT INTO `sys_dict_data` VALUES (14, 1, '通知', '1', 'sys_notice_type', '', 'warning', 'Y', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '通知'); +INSERT INTO `sys_dict_data` VALUES (15, 2, '公告', '2', 'sys_notice_type', '', 'success', 'N', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '公告'); +INSERT INTO `sys_dict_data` VALUES (16, 1, '正常', '0', 'sys_notice_status', '', 'primary', 'Y', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '正常状态'); +INSERT INTO `sys_dict_data` VALUES (17, 2, '关闭', '1', 'sys_notice_status', '', 'danger', 'N', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '关闭状态'); +INSERT INTO `sys_dict_data` VALUES (18, 99, '其他', '0', 'sys_oper_type', '', 'info', 'N', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '其他操作'); +INSERT INTO `sys_dict_data` VALUES (19, 1, '新增', '1', 'sys_oper_type', '', 'info', 'N', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '新增操作'); +INSERT INTO `sys_dict_data` VALUES (20, 2, '修改', '2', 'sys_oper_type', '', 'info', 'N', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '修改操作'); +INSERT INTO `sys_dict_data` VALUES (21, 3, '删除', '3', 'sys_oper_type', '', 'danger', 'N', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '删除操作'); +INSERT INTO `sys_dict_data` VALUES (22, 4, '授权', '4', 'sys_oper_type', '', 'primary', 'N', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '授权操作'); +INSERT INTO `sys_dict_data` VALUES (23, 5, '导出', '5', 'sys_oper_type', '', 'warning', 'N', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '导出操作'); +INSERT INTO `sys_dict_data` VALUES (24, 6, '导入', '6', 'sys_oper_type', '', 'warning', 'N', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '导入操作'); +INSERT INTO `sys_dict_data` VALUES (25, 7, '强退', '7', 'sys_oper_type', '', 'danger', 'N', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '强退操作'); +INSERT INTO `sys_dict_data` VALUES (26, 8, '生成代码', '8', 'sys_oper_type', '', 'warning', 'N', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '生成操作'); +INSERT INTO `sys_dict_data` VALUES (27, 9, '清空数据', '9', 'sys_oper_type', '', 'danger', 'N', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '清空操作'); +INSERT INTO `sys_dict_data` VALUES (28, 1, '成功', '0', 'sys_common_status', '', 'primary', 'N', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '正常状态'); +INSERT INTO `sys_dict_data` VALUES (29, 2, '失败', '1', 'sys_common_status', '', 'danger', 'N', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '停用状态'); +INSERT INTO `sys_dict_data` VALUES (100, 0, '单选框组', '0', 'comp_type', NULL, 'default', 'N', '0', 'admin', '2024-03-31 14:24:26', 'admin', '2024-03-31 17:32:10', NULL); +INSERT INTO `sys_dict_data` VALUES (101, 0, '多选框组', '1', 'comp_type', NULL, 'default', 'N', '0', 'admin', '2024-03-31 14:24:45', 'admin', '2024-03-31 17:32:22', NULL); +INSERT INTO `sys_dict_data` VALUES (102, 0, '关闭', '0', 'open', NULL, 'default', 'N', '0', 'admin', '2024-03-31 14:36:45', '', NULL, NULL); +INSERT INTO `sys_dict_data` VALUES (103, 0, '开放', '1', 'open', NULL, 'default', 'N', '0', 'admin', '2024-03-31 14:36:53', '', NULL, NULL); +INSERT INTO `sys_dict_data` VALUES (104, 0, '单行文本', '2', 'comp_type', NULL, 'default', 'N', '0', 'admin', '2024-03-31 15:46:08', 'admin', '2024-03-31 17:31:57', NULL); +INSERT INTO `sys_dict_data` VALUES (105, 0, '多行文本', '3', 'comp_type', NULL, 'default', 'N', '0', 'admin', '2024-03-31 17:32:38', '', NULL, NULL); +INSERT INTO `sys_dict_data` VALUES (106, 0, '密码', '4', 'comp_type', NULL, 'default', 'N', '0', 'admin', '2024-03-31 17:32:48', 'admin', '2024-03-31 17:32:53', NULL); +INSERT INTO `sys_dict_data` VALUES (107, 0, '计数器', '5', 'comp_type', NULL, 'default', 'N', '0', 'admin', '2024-03-31 17:33:12', 'admin', '2024-03-31 17:33:16', NULL); +INSERT INTO `sys_dict_data` VALUES (108, 0, '下拉选择', '6', 'comp_type', NULL, 'default', 'N', '0', 'admin', '2024-03-31 17:33:55', '', NULL, NULL); +INSERT INTO `sys_dict_data` VALUES (109, 0, '开关', '7', 'comp_type', NULL, 'default', 'N', '0', 'admin', '2024-03-31 17:34:12', '', NULL, NULL); +INSERT INTO `sys_dict_data` VALUES (110, 0, '时间选择', '8', 'comp_type', NULL, 'default', 'N', '0', 'admin', '2024-03-31 17:35:01', '', NULL, NULL); +INSERT INTO `sys_dict_data` VALUES (111, 0, '时间范围', '9', 'comp_type', NULL, 'default', 'N', '0', 'admin', '2024-03-31 17:35:29', '', NULL, NULL); + +-- ---------------------------- +-- Table structure for sys_dict_type +-- ---------------------------- +DROP TABLE IF EXISTS `sys_dict_type`; +CREATE TABLE `sys_dict_type` ( + `dict_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '字典主键', + `dict_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '字典名称', + `dict_type` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '字典类型', + `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '状态(0正常 1停用)', + `create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', + `remark` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注', + PRIMARY KEY (`dict_id`) USING BTREE, + UNIQUE INDEX `dict_type`(`dict_type`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 102 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '字典类型表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_dict_type +-- ---------------------------- +INSERT INTO `sys_dict_type` VALUES (1, '用户性别', 'sys_user_sex', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '用户性别列表'); +INSERT INTO `sys_dict_type` VALUES (2, '菜单状态', 'sys_show_hide', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '菜单状态列表'); +INSERT INTO `sys_dict_type` VALUES (3, '系统开关', 'sys_normal_disable', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '系统开关列表'); +INSERT INTO `sys_dict_type` VALUES (4, '任务状态', 'sys_job_status', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '任务状态列表'); +INSERT INTO `sys_dict_type` VALUES (5, '任务分组', 'sys_job_group', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '任务分组列表'); +INSERT INTO `sys_dict_type` VALUES (6, '系统是否', 'sys_yes_no', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '系统是否列表'); +INSERT INTO `sys_dict_type` VALUES (7, '通知类型', 'sys_notice_type', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '通知类型列表'); +INSERT INTO `sys_dict_type` VALUES (8, '通知状态', 'sys_notice_status', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '通知状态列表'); +INSERT INTO `sys_dict_type` VALUES (9, '操作类型', 'sys_oper_type', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '操作类型列表'); +INSERT INTO `sys_dict_type` VALUES (10, '系统状态', 'sys_common_status', '0', 'admin', '2024-03-31 01:19:12', '', NULL, '登录状态列表'); +INSERT INTO `sys_dict_type` VALUES (100, '组件类型', 'comp_type', '0', 'admin', '2024-03-31 14:24:08', '', NULL, NULL); +INSERT INTO `sys_dict_type` VALUES (101, '是否开放', 'open', '0', 'admin', '2024-03-31 14:36:25', '', NULL, NULL); + +-- ---------------------------- +-- Table structure for sys_job +-- ---------------------------- +DROP TABLE IF EXISTS `sys_job`; +CREATE TABLE `sys_job` ( + `job_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '任务ID', + `job_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '任务名称', + `job_group` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'DEFAULT' COMMENT '任务组名', + `invoke_target` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '调用目标字符串', + `cron_expression` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT 'cron执行表达式', + `misfire_policy` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '3' COMMENT '计划执行错误策略(1立即执行 2执行一次 3放弃执行)', + `concurrent` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '1' COMMENT '是否并发执行(0允许 1禁止)', + `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '状态(0正常 1暂停)', + `create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', + `remark` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '备注信息', + PRIMARY KEY (`job_id`, `job_name`, `job_group`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '定时任务调度表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_job +-- ---------------------------- +INSERT INTO `sys_job` VALUES (1, '系统默认(无参)', 'DEFAULT', 'ryTask.ryNoParams', '0/10 * * * * ?', '3', '1', '1', 'admin', '2024-03-31 01:19:12', '', NULL, ''); +INSERT INTO `sys_job` VALUES (2, '系统默认(有参)', 'DEFAULT', 'ryTask.ryParams(\'ry\')', '0/15 * * * * ?', '3', '1', '1', 'admin', '2024-03-31 01:19:12', '', NULL, ''); +INSERT INTO `sys_job` VALUES (3, '系统默认(多参)', 'DEFAULT', 'ryTask.ryMultipleParams(\'ry\', true, 2000L, 316.50D, 100)', '0/20 * * * * ?', '3', '1', '1', 'admin', '2024-03-31 01:19:12', '', NULL, ''); + +-- ---------------------------- +-- Table structure for sys_job_log +-- ---------------------------- +DROP TABLE IF EXISTS `sys_job_log`; +CREATE TABLE `sys_job_log` ( + `job_log_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '任务日志ID', + `job_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '任务名称', + `job_group` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '任务组名', + `invoke_target` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '调用目标字符串', + `job_message` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '日志信息', + `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '执行状态(0正常 1失败)', + `exception_info` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '异常信息', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + PRIMARY KEY (`job_log_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '定时任务调度日志表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_job_log +-- ---------------------------- + +-- ---------------------------- +-- Table structure for sys_logininfor +-- ---------------------------- +DROP TABLE IF EXISTS `sys_logininfor`; +CREATE TABLE `sys_logininfor` ( + `info_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '访问ID', + `user_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '用户账号', + `ipaddr` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '登录IP地址', + `login_location` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '登录地点', + `browser` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '浏览器类型', + `os` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '操作系统', + `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '登录状态(0成功 1失败)', + `msg` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '提示消息', + `login_time` datetime(0) NULL DEFAULT NULL COMMENT '访问时间', + PRIMARY KEY (`info_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 124 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '系统访问记录' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_logininfor +-- ---------------------------- +INSERT INTO `sys_logininfor` VALUES (100, 'admin', '127.0.0.1', '内网IP', 'Firefox 11', 'Windows 10', '0', '登录成功', '2024-03-31 01:53:30'); +INSERT INTO `sys_logininfor` VALUES (101, 'admin', '127.0.0.1', '内网IP', 'Firefox 11', 'Windows 10', '0', '退出成功', '2024-03-31 01:58:17'); +INSERT INTO `sys_logininfor` VALUES (102, 'admin', '127.0.0.1', '内网IP', 'Firefox 11', 'Windows 10', '0', '登录成功', '2024-03-31 02:03:26'); +INSERT INTO `sys_logininfor` VALUES (103, 'admin', '127.0.0.1', '内网IP', 'Firefox 11', 'Windows 10', '0', '退出成功', '2024-03-31 02:03:45'); +INSERT INTO `sys_logininfor` VALUES (104, 'admin', '127.0.0.1', '内网IP', 'Firefox 11', 'Windows 10', '0', '登录成功', '2024-03-31 02:05:01'); +INSERT INTO `sys_logininfor` VALUES (105, 'admin', '127.0.0.1', '内网IP', 'Firefox 11', 'Windows 10', '0', '登录成功', '2024-03-31 03:13:27'); +INSERT INTO `sys_logininfor` VALUES (106, 'admin', '127.0.0.1', '内网IP', 'Firefox 11', 'Windows 10', '0', '登录成功', '2024-03-31 13:33:57'); +INSERT INTO `sys_logininfor` VALUES (107, 'admin', '127.0.0.1', '内网IP', 'Firefox 11', 'Windows 10', '0', '退出成功', '2024-03-31 14:57:00'); +INSERT INTO `sys_logininfor` VALUES (108, 'admin', '127.0.0.1', '内网IP', 'Firefox 11', 'Windows 10', '0', '登录成功', '2024-03-31 14:57:10'); +INSERT INTO `sys_logininfor` VALUES (109, 'admin', '127.0.0.1', '内网IP', 'Firefox 11', 'Windows 10', '0', '登录成功', '2024-03-31 18:08:39'); +INSERT INTO `sys_logininfor` VALUES (110, 'admin', '127.0.0.1', '内网IP', 'Firefox 11', 'Windows 10', '0', '登录成功', '2024-03-31 19:09:32'); +INSERT INTO `sys_logininfor` VALUES (111, 'admin', '127.0.0.1', '内网IP', 'Firefox 11', 'Windows 10', '0', '登录成功', '2024-03-31 21:05:07'); +INSERT INTO `sys_logininfor` VALUES (112, 'admin', '127.0.0.1', '内网IP', 'Firefox 11', 'Windows 10', '0', '退出成功', '2024-03-31 22:05:44'); +INSERT INTO `sys_logininfor` VALUES (113, 'test1', '127.0.0.1', '内网IP', 'Firefox 11', 'Windows 10', '0', '登录成功', '2024-03-31 22:05:55'); +INSERT INTO `sys_logininfor` VALUES (114, 'test1', '127.0.0.1', '内网IP', 'Firefox 11', 'Windows 10', '0', '退出成功', '2024-03-31 22:06:01'); +INSERT INTO `sys_logininfor` VALUES (115, 'admin', '127.0.0.1', '内网IP', 'Firefox 11', 'Windows 10', '0', '登录成功', '2024-03-31 22:06:28'); +INSERT INTO `sys_logininfor` VALUES (116, 'admin', '127.0.0.1', '内网IP', 'Firefox 11', 'Windows 10', '0', '退出成功', '2024-03-31 22:07:41'); +INSERT INTO `sys_logininfor` VALUES (117, 'test1', '127.0.0.1', '内网IP', 'Firefox 11', 'Windows 10', '0', '登录成功', '2024-03-31 22:07:54'); +INSERT INTO `sys_logininfor` VALUES (118, 'test1', '127.0.0.1', '内网IP', 'Firefox 11', 'Windows 10', '0', '退出成功', '2024-03-31 22:21:15'); +INSERT INTO `sys_logininfor` VALUES (119, 'admin', '127.0.0.1', '内网IP', 'Firefox 11', 'Windows 10', '0', '登录成功', '2024-03-31 22:21:21'); +INSERT INTO `sys_logininfor` VALUES (120, 'admin', '127.0.0.1', '内网IP', 'Firefox 11', 'Windows 10', '0', '退出成功', '2024-03-31 22:28:30'); +INSERT INTO `sys_logininfor` VALUES (121, 'admin', '127.0.0.1', '内网IP', 'Firefox 11', 'Windows 10', '0', '登录成功', '2024-03-31 22:28:46'); +INSERT INTO `sys_logininfor` VALUES (122, 'admin', '127.0.0.1', '内网IP', 'Firefox 11', 'Windows 10', '0', '退出成功', '2024-03-31 22:35:17'); +INSERT INTO `sys_logininfor` VALUES (123, 'test1', '127.0.0.1', '内网IP', 'Firefox 11', 'Windows 10', '0', '登录成功', '2024-03-31 22:35:35'); + +-- ---------------------------- +-- Table structure for sys_menu +-- ---------------------------- +DROP TABLE IF EXISTS `sys_menu`; +CREATE TABLE `sys_menu` ( + `menu_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '菜单ID', + `menu_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '菜单名称', + `parent_id` bigint(20) NULL DEFAULT 0 COMMENT '父菜单ID', + `order_num` int(4) NULL DEFAULT 0 COMMENT '显示顺序', + `path` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '路由地址', + `component` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '组件路径', + `query` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '路由参数', + `is_frame` int(1) NULL DEFAULT 1 COMMENT '是否为外链(0是 1否)', + `is_cache` int(1) NULL DEFAULT 0 COMMENT '是否缓存(0缓存 1不缓存)', + `menu_type` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '菜单类型(M目录 C菜单 F按钮)', + `visible` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '菜单状态(0显示 1隐藏)', + `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '菜单状态(0正常 1停用)', + `perms` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '权限标识', + `icon` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '#' COMMENT '菜单图标', + `create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', + `remark` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '备注', + PRIMARY KEY (`menu_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 2030 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '菜单权限表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_menu +-- ---------------------------- +INSERT INTO `sys_menu` VALUES (1, '系统管理', 0, 1, 'system', NULL, '', 1, 0, 'M', '0', '0', '', 'system', 'admin', '2024-03-31 01:19:09', '', NULL, '系统管理目录'); +INSERT INTO `sys_menu` VALUES (2, '系统监控', 0, 2, 'monitor', NULL, '', 1, 0, 'M', '0', '0', '', 'monitor', 'admin', '2024-03-31 01:19:09', '', NULL, '系统监控目录'); +INSERT INTO `sys_menu` VALUES (3, '系统工具', 0, 3, 'tool', NULL, '', 1, 0, 'M', '0', '0', '', 'tool', 'admin', '2024-03-31 01:19:09', '', NULL, '系统工具目录'); +INSERT INTO `sys_menu` VALUES (100, '用户管理', 1, 1, 'user', 'system/user/index', '', 1, 0, 'C', '0', '0', 'system:user:list', 'user', 'admin', '2024-03-31 01:19:09', '', NULL, '用户管理菜单'); +INSERT INTO `sys_menu` VALUES (101, '角色管理', 1, 2, 'role', 'system/role/index', '', 1, 0, 'C', '0', '0', 'system:role:list', 'peoples', 'admin', '2024-03-31 01:19:09', '', NULL, '角色管理菜单'); +INSERT INTO `sys_menu` VALUES (102, '菜单管理', 1, 3, 'menu', 'system/menu/index', '', 1, 0, 'C', '0', '0', 'system:menu:list', 'tree-table', 'admin', '2024-03-31 01:19:09', '', NULL, '菜单管理菜单'); +INSERT INTO `sys_menu` VALUES (103, '部门管理', 1, 4, 'dept', 'system/dept/index', '', 1, 0, 'C', '0', '0', 'system:dept:list', 'tree', 'admin', '2024-03-31 01:19:09', '', NULL, '部门管理菜单'); +INSERT INTO `sys_menu` VALUES (104, '岗位管理', 1, 5, 'post', 'system/post/index', '', 1, 0, 'C', '0', '0', 'system:post:list', 'post', 'admin', '2024-03-31 01:19:09', '', NULL, '岗位管理菜单'); +INSERT INTO `sys_menu` VALUES (105, '字典管理', 1, 6, 'dict', 'system/dict/index', '', 1, 0, 'C', '0', '0', 'system:dict:list', 'dict', 'admin', '2024-03-31 01:19:09', '', NULL, '字典管理菜单'); +INSERT INTO `sys_menu` VALUES (106, '参数设置', 1, 7, 'config', 'system/config/index', '', 1, 0, 'C', '0', '0', 'system:config:list', 'edit', 'admin', '2024-03-31 01:19:09', '', NULL, '参数设置菜单'); +INSERT INTO `sys_menu` VALUES (107, '通知公告', 1, 8, 'notice', 'system/notice/index', '', 1, 0, 'C', '0', '0', 'system:notice:list', 'message', 'admin', '2024-03-31 01:19:09', '', NULL, '通知公告菜单'); +INSERT INTO `sys_menu` VALUES (108, '日志管理', 1, 9, 'log', '', '', 1, 0, 'M', '0', '0', '', 'log', 'admin', '2024-03-31 01:19:09', '', NULL, '日志管理菜单'); +INSERT INTO `sys_menu` VALUES (109, '在线用户', 2, 1, 'online', 'monitor/online/index', '', 1, 0, 'C', '0', '0', 'monitor:online:list', 'online', 'admin', '2024-03-31 01:19:09', '', NULL, '在线用户菜单'); +INSERT INTO `sys_menu` VALUES (110, '定时任务', 2, 2, 'job', 'monitor/job/index', '', 1, 0, 'C', '0', '0', 'monitor:job:list', 'job', 'admin', '2024-03-31 01:19:09', '', NULL, '定时任务菜单'); +INSERT INTO `sys_menu` VALUES (111, '数据监控', 2, 3, 'druid', 'monitor/druid/index', '', 1, 0, 'C', '0', '0', 'monitor:druid:list', 'druid', 'admin', '2024-03-31 01:19:09', '', NULL, '数据监控菜单'); +INSERT INTO `sys_menu` VALUES (112, '服务监控', 2, 4, 'server', 'monitor/server/index', '', 1, 0, 'C', '0', '0', 'monitor:server:list', 'server', 'admin', '2024-03-31 01:19:09', '', NULL, '服务监控菜单'); +INSERT INTO `sys_menu` VALUES (113, '缓存监控', 2, 5, 'cache', 'monitor/cache/index', '', 1, 0, 'C', '0', '0', 'monitor:cache:list', 'redis', 'admin', '2024-03-31 01:19:09', '', NULL, '缓存监控菜单'); +INSERT INTO `sys_menu` VALUES (114, '缓存列表', 2, 6, 'cacheList', 'monitor/cache/list', '', 1, 0, 'C', '0', '0', 'monitor:cache:list', 'redis-list', 'admin', '2024-03-31 01:19:09', '', NULL, '缓存列表菜单'); +INSERT INTO `sys_menu` VALUES (115, '表单构建', 3, 1, 'build', 'tool/build/index', '', 1, 0, 'C', '0', '0', 'tool:build:list', 'build', 'admin', '2024-03-31 01:19:09', '', NULL, '表单构建菜单'); +INSERT INTO `sys_menu` VALUES (116, '代码生成', 3, 2, 'gen', 'tool/gen/index', '', 1, 0, 'C', '0', '0', 'tool:gen:list', 'code', 'admin', '2024-03-31 01:19:09', '', NULL, '代码生成菜单'); +INSERT INTO `sys_menu` VALUES (117, '系统接口', 3, 3, 'swagger', 'tool/swagger/index', '', 1, 0, 'C', '0', '0', 'tool:swagger:list', 'swagger', 'admin', '2024-03-31 01:19:09', '', NULL, '系统接口菜单'); +INSERT INTO `sys_menu` VALUES (500, '操作日志', 108, 1, 'operlog', 'monitor/operlog/index', '', 1, 0, 'C', '0', '0', 'monitor:operlog:list', 'form', 'admin', '2024-03-31 01:19:09', '', NULL, '操作日志菜单'); +INSERT INTO `sys_menu` VALUES (501, '登录日志', 108, 2, 'logininfor', 'monitor/logininfor/index', '', 1, 0, 'C', '0', '0', 'monitor:logininfor:list', 'logininfor', 'admin', '2024-03-31 01:19:09', '', NULL, '登录日志菜单'); +INSERT INTO `sys_menu` VALUES (1000, '用户查询', 100, 1, '', '', '', 1, 0, 'F', '0', '0', 'system:user:query', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1001, '用户新增', 100, 2, '', '', '', 1, 0, 'F', '0', '0', 'system:user:add', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1002, '用户修改', 100, 3, '', '', '', 1, 0, 'F', '0', '0', 'system:user:edit', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1003, '用户删除', 100, 4, '', '', '', 1, 0, 'F', '0', '0', 'system:user:remove', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1004, '用户导出', 100, 5, '', '', '', 1, 0, 'F', '0', '0', 'system:user:export', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1005, '用户导入', 100, 6, '', '', '', 1, 0, 'F', '0', '0', 'system:user:import', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1006, '重置密码', 100, 7, '', '', '', 1, 0, 'F', '0', '0', 'system:user:resetPwd', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1007, '角色查询', 101, 1, '', '', '', 1, 0, 'F', '0', '0', 'system:role:query', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1008, '角色新增', 101, 2, '', '', '', 1, 0, 'F', '0', '0', 'system:role:add', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1009, '角色修改', 101, 3, '', '', '', 1, 0, 'F', '0', '0', 'system:role:edit', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1010, '角色删除', 101, 4, '', '', '', 1, 0, 'F', '0', '0', 'system:role:remove', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1011, '角色导出', 101, 5, '', '', '', 1, 0, 'F', '0', '0', 'system:role:export', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1012, '菜单查询', 102, 1, '', '', '', 1, 0, 'F', '0', '0', 'system:menu:query', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1013, '菜单新增', 102, 2, '', '', '', 1, 0, 'F', '0', '0', 'system:menu:add', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1014, '菜单修改', 102, 3, '', '', '', 1, 0, 'F', '0', '0', 'system:menu:edit', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1015, '菜单删除', 102, 4, '', '', '', 1, 0, 'F', '0', '0', 'system:menu:remove', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1016, '部门查询', 103, 1, '', '', '', 1, 0, 'F', '0', '0', 'system:dept:query', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1017, '部门新增', 103, 2, '', '', '', 1, 0, 'F', '0', '0', 'system:dept:add', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1018, '部门修改', 103, 3, '', '', '', 1, 0, 'F', '0', '0', 'system:dept:edit', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1019, '部门删除', 103, 4, '', '', '', 1, 0, 'F', '0', '0', 'system:dept:remove', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1020, '岗位查询', 104, 1, '', '', '', 1, 0, 'F', '0', '0', 'system:post:query', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1021, '岗位新增', 104, 2, '', '', '', 1, 0, 'F', '0', '0', 'system:post:add', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1022, '岗位修改', 104, 3, '', '', '', 1, 0, 'F', '0', '0', 'system:post:edit', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1023, '岗位删除', 104, 4, '', '', '', 1, 0, 'F', '0', '0', 'system:post:remove', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1024, '岗位导出', 104, 5, '', '', '', 1, 0, 'F', '0', '0', 'system:post:export', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1025, '字典查询', 105, 1, '#', '', '', 1, 0, 'F', '0', '0', 'system:dict:query', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1026, '字典新增', 105, 2, '#', '', '', 1, 0, 'F', '0', '0', 'system:dict:add', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1027, '字典修改', 105, 3, '#', '', '', 1, 0, 'F', '0', '0', 'system:dict:edit', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1028, '字典删除', 105, 4, '#', '', '', 1, 0, 'F', '0', '0', 'system:dict:remove', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1029, '字典导出', 105, 5, '#', '', '', 1, 0, 'F', '0', '0', 'system:dict:export', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1030, '参数查询', 106, 1, '#', '', '', 1, 0, 'F', '0', '0', 'system:config:query', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1031, '参数新增', 106, 2, '#', '', '', 1, 0, 'F', '0', '0', 'system:config:add', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1032, '参数修改', 106, 3, '#', '', '', 1, 0, 'F', '0', '0', 'system:config:edit', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1033, '参数删除', 106, 4, '#', '', '', 1, 0, 'F', '0', '0', 'system:config:remove', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1034, '参数导出', 106, 5, '#', '', '', 1, 0, 'F', '0', '0', 'system:config:export', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1035, '公告查询', 107, 1, '#', '', '', 1, 0, 'F', '0', '0', 'system:notice:query', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1036, '公告新增', 107, 2, '#', '', '', 1, 0, 'F', '0', '0', 'system:notice:add', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1037, '公告修改', 107, 3, '#', '', '', 1, 0, 'F', '0', '0', 'system:notice:edit', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1038, '公告删除', 107, 4, '#', '', '', 1, 0, 'F', '0', '0', 'system:notice:remove', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1039, '操作查询', 500, 1, '#', '', '', 1, 0, 'F', '0', '0', 'monitor:operlog:query', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1040, '操作删除', 500, 2, '#', '', '', 1, 0, 'F', '0', '0', 'monitor:operlog:remove', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1041, '日志导出', 500, 3, '#', '', '', 1, 0, 'F', '0', '0', 'monitor:operlog:export', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1042, '登录查询', 501, 1, '#', '', '', 1, 0, 'F', '0', '0', 'monitor:logininfor:query', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1043, '登录删除', 501, 2, '#', '', '', 1, 0, 'F', '0', '0', 'monitor:logininfor:remove', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1044, '日志导出', 501, 3, '#', '', '', 1, 0, 'F', '0', '0', 'monitor:logininfor:export', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1045, '账户解锁', 501, 4, '#', '', '', 1, 0, 'F', '0', '0', 'monitor:logininfor:unlock', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1046, '在线查询', 109, 1, '#', '', '', 1, 0, 'F', '0', '0', 'monitor:online:query', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1047, '批量强退', 109, 2, '#', '', '', 1, 0, 'F', '0', '0', 'monitor:online:batchLogout', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1048, '单条强退', 109, 3, '#', '', '', 1, 0, 'F', '0', '0', 'monitor:online:forceLogout', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1049, '任务查询', 110, 1, '#', '', '', 1, 0, 'F', '0', '0', 'monitor:job:query', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1050, '任务新增', 110, 2, '#', '', '', 1, 0, 'F', '0', '0', 'monitor:job:add', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1051, '任务修改', 110, 3, '#', '', '', 1, 0, 'F', '0', '0', 'monitor:job:edit', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1052, '任务删除', 110, 4, '#', '', '', 1, 0, 'F', '0', '0', 'monitor:job:remove', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1053, '状态修改', 110, 5, '#', '', '', 1, 0, 'F', '0', '0', 'monitor:job:changeStatus', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1054, '任务导出', 110, 6, '#', '', '', 1, 0, 'F', '0', '0', 'monitor:job:export', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1055, '生成查询', 116, 1, '#', '', '', 1, 0, 'F', '0', '0', 'tool:gen:query', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1056, '生成修改', 116, 2, '#', '', '', 1, 0, 'F', '0', '0', 'tool:gen:edit', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1057, '生成删除', 116, 3, '#', '', '', 1, 0, 'F', '0', '0', 'tool:gen:remove', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1058, '导入代码', 116, 4, '#', '', '', 1, 0, 'F', '0', '0', 'tool:gen:import', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1059, '预览代码', 116, 5, '#', '', '', 1, 0, 'F', '0', '0', 'tool:gen:preview', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (1060, '生成代码', 116, 6, '#', '', '', 1, 0, 'F', '0', '0', 'tool:gen:code', '#', 'admin', '2024-03-31 01:19:09', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (2000, '问卷调查', 0, 0, 'questionnaire', NULL, NULL, 1, 0, 'M', '0', '0', NULL, 'checkbox', 'admin', '2024-03-31 03:15:46', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (2007, '模版管理', 2000, 1, 'template', 'business/template/index', NULL, 1, 1, 'C', '0', '0', 'business:template:list', '#', 'admin', '2024-03-31 14:39:33', 'admin', '2024-03-31 22:33:50', '模版管理菜单'); +INSERT INTO `sys_menu` VALUES (2008, '模版管理查询', 2007, 1, '#', '', NULL, 1, 0, 'F', '0', '0', 'business:template:query', '#', 'admin', '2024-03-31 14:39:33', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (2009, '模版管理新增', 2007, 2, '#', '', NULL, 1, 0, 'F', '0', '0', 'business:template:add', '#', 'admin', '2024-03-31 14:39:33', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (2010, '模版管理修改', 2007, 3, '#', '', NULL, 1, 0, 'F', '0', '0', 'business:template:edit', '#', 'admin', '2024-03-31 14:39:33', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (2011, '模版管理删除', 2007, 4, '#', '', NULL, 1, 0, 'F', '0', '0', 'business:template:remove', '#', 'admin', '2024-03-31 14:39:33', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (2012, '模版管理导出', 2007, 5, '#', '', NULL, 1, 0, 'F', '0', '0', 'business:template:export', '#', 'admin', '2024-03-31 14:39:33', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (2013, '模版属性', 2000, 1, 'templateProp', 'business/templateProp/index', NULL, 1, 1, 'C', '0', '0', 'business:templateProp:list', '#', 'admin', '2024-03-31 14:39:41', 'admin', '2024-03-31 22:33:54', '模版属性菜单'); +INSERT INTO `sys_menu` VALUES (2014, '模版属性查询', 2013, 1, '#', '', NULL, 1, 0, 'F', '0', '0', 'business:templateProp:query', '#', 'admin', '2024-03-31 14:39:41', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (2015, '模版属性新增', 2013, 2, '#', '', NULL, 1, 0, 'F', '0', '0', 'business:templateProp:add', '#', 'admin', '2024-03-31 14:39:41', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (2016, '模版属性修改', 2013, 3, '#', '', NULL, 1, 0, 'F', '0', '0', 'business:templateProp:edit', '#', 'admin', '2024-03-31 14:39:41', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (2017, '模版属性删除', 2013, 4, '#', '', NULL, 1, 0, 'F', '0', '0', 'business:templateProp:remove', '#', 'admin', '2024-03-31 14:39:41', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (2018, '模版属性导出', 2013, 5, '#', '', NULL, 1, 0, 'F', '0', '0', 'business:templateProp:export', '#', 'admin', '2024-03-31 14:39:41', '', NULL, ''); +INSERT INTO `sys_menu` VALUES (2021, '问卷调查', 2000, 1, 'survey', 'business/survey/index', NULL, 1, 1, 'C', '0', '0', 'business:template:list', '#', 'admin', '2024-03-31 15:00:21', 'admin', '2024-03-31 22:33:58', '问卷调查菜单'); +INSERT INTO `sys_menu` VALUES (2022, '填写问卷', 2000, 1, 'surveySubmit', 'business/surveySubmit/index', '', 1, 1, 'C', '1', '0', 'business:template:list', '#', 'admin', '2024-03-31 15:04:24', 'admin', '2024-03-31 22:34:03', '填写问卷'); +INSERT INTO `sys_menu` VALUES (2029, '问卷统计', 2000, 1, 'countGroup', 'business/countGroup/index', '', 1, 1, 'C', '1', '0', 'business:countGroup:list', '#', 'admin', '2024-03-31 15:04:24', 'admin', '2024-03-31 22:34:07', '问卷统计'); + +-- ---------------------------- +-- Table structure for sys_notice +-- ---------------------------- +DROP TABLE IF EXISTS `sys_notice`; +CREATE TABLE `sys_notice` ( + `notice_id` int(4) NOT NULL AUTO_INCREMENT COMMENT '公告ID', + `notice_title` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '公告标题', + `notice_type` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '公告类型(1通知 2公告)', + `notice_content` longblob NULL COMMENT '公告内容', + `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '公告状态(0正常 1关闭)', + `create_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', + `remark` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注', + PRIMARY KEY (`notice_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '通知公告表' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_notice +-- ---------------------------- +INSERT INTO `sys_notice` VALUES (1, '温馨提醒:2018-07-01 若依新版本发布啦', '2', 0xE696B0E78988E69CACE58685E5AEB9, '0', 'admin', '2024-03-31 01:19:12', '', NULL, '管理员'); +INSERT INTO `sys_notice` VALUES (2, '维护通知:2018-07-01 若依系统凌晨维护', '1', 0xE7BBB4E68AA4E58685E5AEB9, '0', 'admin', '2024-03-31 01:19:12', '', NULL, '管理员'); + +-- ---------------------------- +-- Table structure for sys_oper_log +-- ---------------------------- +DROP TABLE IF EXISTS `sys_oper_log`; +CREATE TABLE `sys_oper_log` ( + `oper_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '日志主键', + `title` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '模块标题', + `business_type` int(2) NULL DEFAULT 0 COMMENT '业务类型(0其它 1新增 2修改 3删除)', + `method` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '方法名称', + `request_method` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '请求方式', + `operator_type` int(1) NULL DEFAULT 0 COMMENT '操作类别(0其它 1后台用户 2手机端用户)', + `oper_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '操作人员', + `dept_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '部门名称', + `oper_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '请求URL', + `oper_ip` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '主机地址', + `oper_location` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '操作地点', + `oper_param` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '请求参数', + `json_result` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '返回参数', + `status` int(1) NULL DEFAULT 0 COMMENT '操作状态(0正常 1异常)', + `error_msg` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '错误消息', + `oper_time` datetime(0) NULL DEFAULT NULL COMMENT '操作时间', + PRIMARY KEY (`oper_id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 220 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '操作日志记录' ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of sys_oper_log +-- ---------------------------- +INSERT INTO `sys_oper_log` VALUES (100, '参数管理', 2, 'com.ruoyi.web.controller.system.SysConfigController.edit()', 'PUT', 1, 'admin', NULL, '/system/config', '127.0.0.1', '内网IP', '{\"configId\":5,\"configKey\":\"sys.account.registerUser\",\"configName\":\"账号自助-是否开启用户注册功能\",\"configType\":\"Y\",\"configValue\":\"true\",\"createBy\":\"admin\",\"createTime\":\"2024-03-31 01:19:12\",\"params\":{},\"remark\":\"是否开启注册用户功能(true开启,false关闭)\",\"updateBy\":\"admin\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-31 02:03:41'); +INSERT INTO `sys_oper_log` VALUES (101, '代码生成', 6, 'com.ruoyi.generator.controller.GenController.importTableSave()', 'POST', 1, 'admin', NULL, '/tool/gen/importTable', '127.0.0.1', '内网IP', '\"business_template\"', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-31 03:13:37'); +INSERT INTO `sys_oper_log` VALUES (102, '菜单管理', 1, 'com.ruoyi.web.controller.system.SysMenuController.add()', 'POST', 1, 'admin', NULL, '/system/menu', '127.0.0.1', '内网IP', '{\"children\":[],\"createBy\":\"admin\",\"icon\":\"checkbox\",\"isCache\":\"0\",\"isFrame\":\"1\",\"menuName\":\"问卷调查\",\"menuType\":\"M\",\"orderNum\":0,\"params\":{},\"parentId\":0,\"path\":\"questionnaire\",\"status\":\"0\",\"visible\":\"0\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-31 03:15:46'); +INSERT INTO `sys_oper_log` VALUES (103, '代码生成', 2, 'com.ruoyi.generator.controller.GenController.editSave()', 'PUT', 1, 'admin', NULL, '/tool/gen', '127.0.0.1', '内网IP', '{\"businessName\":\"template\",\"className\":\"BusinessTemplate\",\"columns\":[{\"capJavaField\":\"Id\",\"columnComment\":\"主键\",\"columnId\":1,\"columnName\":\"id\",\"columnType\":\"bigint(20)\",\"createBy\":\"admin\",\"createTime\":\"2024-03-31 03:13:37\",\"dictType\":\"\",\"edit\":false,\"htmlType\":\"input\",\"increment\":true,\"insert\":true,\"isIncrement\":\"1\",\"isInsert\":\"1\",\"isPk\":\"1\",\"javaField\":\"id\",\"javaType\":\"Long\",\"list\":false,\"params\":{},\"pk\":true,\"query\":false,\"queryType\":\"EQ\",\"required\":false,\"sort\":1,\"superColumn\":false,\"tableId\":1,\"updateBy\":\"\",\"usableColumn\":false},{\"capJavaField\":\"Title\",\"columnComment\":\"标题\",\"columnId\":2,\"columnName\":\"title\",\"columnType\":\"varchar(100)\",\"createBy\":\"admin\",\"createTime\":\"2024-03-31 03:13:37\",\"dictType\":\"\",\"edit\":true,\"htmlType\":\"input\",\"increment\":false,\"insert\":true,\"isEdit\":\"1\",\"isIncrement\":\"0\",\"isInsert\":\"1\",\"isList\":\"1\",\"isPk\":\"0\",\"isQuery\":\"1\",\"javaField\":\"title\",\"javaType\":\"String\",\"list\":true,\"params\":{},\"pk\":false,\"query\":true,\"queryType\":\"EQ\",\"required\":false,\"sort\":2,\"superColumn\":false,\"tableId\":1,\"updateBy\":\"\",\"usableColumn\":false},{\"capJavaField\":\"Context\",\"columnComment\":\"内容\",\"columnId\":3,\"columnName\":\"context\",\"columnType\":\"varchar(100)\",\"createBy\":\"admin\",\"createTime\":\"2024-03-31 03:13:37\",\"dictType\":\"\",\"edit\":true,\"htmlType\":\"input\",\"increment\":false,\"insert\":true,\"isEdit\":\"1\",\"isIncrement\":\"0\",\"isInsert\":\"1\",\"isList\":\"1\",\"isPk\":\"0\",\"isQuery\":\"1\",\"javaField\":\"context\",\"javaType\":\"String\",\"list\":true,\"params\":{},\"pk\":false,\"query\":true,\"queryType\":\"EQ\",\"required\":false,\"sort\":3,\"superColumn\":false,\"tableId\":1,\"updateBy\":\"\",\"usableColumn\":false},{\"capJavaField\":\"TempValue\",\"columnComment\":\"模版值\",\"columnId\":4,\"columnName\":\"temp_value\",\"columnType\":\"text\",\"createBy\":\"admin\",\"createTime\":\"2024-03-31 03:13:37\",\"dictType\":\"\",\"edit\":true,\"htmlType\":\"textarea\",\"increment\":false,\"insert\":true,\"isEdit\":\"1\",\"isIncrement\":\"0\",\"isInsert\":\"1\",\"isList\":\"1\",\"isPk\":\"0\",\"isQuery\":\"1\",\"javaField\":\"tempValue\",\"javaType\":\"String\",\"list\":true,\"params\":{},\"pk\":false,\"query\":', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-31 03:16:31'); +INSERT INTO `sys_oper_log` VALUES (104, '代码生成', 2, 'com.ruoyi.generator.controller.GenController.editSave()', 'PUT', 1, 'admin', NULL, '/tool/gen', '127.0.0.1', '内网IP', '{\"businessName\":\"template\",\"className\":\"BusinessTemplate\",\"columns\":[{\"capJavaField\":\"Id\",\"columnComment\":\"主键\",\"columnId\":1,\"columnName\":\"id\",\"columnType\":\"bigint(20)\",\"createBy\":\"admin\",\"createTime\":\"2024-03-31 03:13:37\",\"dictType\":\"\",\"edit\":false,\"htmlType\":\"input\",\"increment\":true,\"insert\":false,\"isIncrement\":\"1\",\"isInsert\":\"0\",\"isPk\":\"1\",\"javaField\":\"id\",\"javaType\":\"Long\",\"list\":false,\"params\":{},\"pk\":true,\"query\":false,\"queryType\":\"EQ\",\"required\":false,\"sort\":1,\"superColumn\":false,\"tableId\":1,\"updateBy\":\"\",\"updateTime\":\"2024-03-31 03:16:31\",\"usableColumn\":false},{\"capJavaField\":\"Title\",\"columnComment\":\"标题\",\"columnId\":2,\"columnName\":\"title\",\"columnType\":\"varchar(100)\",\"createBy\":\"admin\",\"createTime\":\"2024-03-31 03:13:37\",\"dictType\":\"\",\"edit\":true,\"htmlType\":\"input\",\"increment\":false,\"insert\":true,\"isEdit\":\"1\",\"isIncrement\":\"0\",\"isInsert\":\"1\",\"isList\":\"1\",\"isPk\":\"0\",\"isQuery\":\"1\",\"javaField\":\"title\",\"javaType\":\"String\",\"list\":true,\"params\":{},\"pk\":false,\"query\":true,\"queryType\":\"EQ\",\"required\":false,\"sort\":2,\"superColumn\":false,\"tableId\":1,\"updateBy\":\"\",\"updateTime\":\"2024-03-31 03:16:31\",\"usableColumn\":false},{\"capJavaField\":\"Context\",\"columnComment\":\"内容\",\"columnId\":3,\"columnName\":\"context\",\"columnType\":\"varchar(100)\",\"createBy\":\"admin\",\"createTime\":\"2024-03-31 03:13:37\",\"dictType\":\"\",\"edit\":true,\"htmlType\":\"input\",\"increment\":false,\"insert\":true,\"isEdit\":\"1\",\"isIncrement\":\"0\",\"isInsert\":\"1\",\"isList\":\"1\",\"isPk\":\"0\",\"isQuery\":\"1\",\"javaField\":\"context\",\"javaType\":\"String\",\"list\":true,\"params\":{},\"pk\":false,\"query\":true,\"queryType\":\"EQ\",\"required\":false,\"sort\":3,\"superColumn\":false,\"tableId\":1,\"updateBy\":\"\",\"updateTime\":\"2024-03-31 03:16:31\",\"usableColumn\":false},{\"capJavaField\":\"TempValue\",\"columnComment\":\"模版值\",\"columnId\":4,\"columnName\":\"temp_value\",\"columnType\":\"text\",\"createBy\":\"admin\",\"createTime\":\"2024-03-31 03:13:37\",\"dictType\":\"\",\"edit\":true,\"htmlType\":\"textarea\",\"increment\":false,\"insert\":true,\"isEdit\":\"1\",\"isIncrement\":\"0\",\"isInsert\":\"1\",\"isList\":\"1\",\"isPk\"', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-31 03:17:18'); +INSERT INTO `sys_oper_log` VALUES (105, '代码生成', 2, 'com.ruoyi.generator.controller.GenController.editSave()', 'PUT', 1, 'admin', NULL, '/tool/gen', '127.0.0.1', '内网IP', '{\"businessName\":\"template\",\"className\":\"BusinessTemplate\",\"columns\":[{\"capJavaField\":\"Id\",\"columnComment\":\"主键\",\"columnId\":1,\"columnName\":\"id\",\"columnType\":\"bigint(20)\",\"createBy\":\"admin\",\"createTime\":\"2024-03-31 03:13:37\",\"dictType\":\"\",\"edit\":false,\"htmlType\":\"input\",\"increment\":true,\"insert\":false,\"isIncrement\":\"1\",\"isInsert\":\"0\",\"isPk\":\"1\",\"javaField\":\"id\",\"javaType\":\"Long\",\"list\":false,\"params\":{},\"pk\":true,\"query\":false,\"queryType\":\"EQ\",\"required\":false,\"sort\":1,\"superColumn\":false,\"tableId\":1,\"updateBy\":\"\",\"updateTime\":\"2024-03-31 03:17:18\",\"usableColumn\":false},{\"capJavaField\":\"Title\",\"columnComment\":\"标题\",\"columnId\":2,\"columnName\":\"title\",\"columnType\":\"varchar(100)\",\"createBy\":\"admin\",\"createTime\":\"2024-03-31 03:13:37\",\"dictType\":\"\",\"edit\":true,\"htmlType\":\"input\",\"increment\":false,\"insert\":true,\"isEdit\":\"1\",\"isIncrement\":\"0\",\"isInsert\":\"1\",\"isList\":\"1\",\"isPk\":\"0\",\"isQuery\":\"1\",\"javaField\":\"title\",\"javaType\":\"String\",\"list\":true,\"params\":{},\"pk\":false,\"query\":true,\"queryType\":\"EQ\",\"required\":false,\"sort\":2,\"superColumn\":false,\"tableId\":1,\"updateBy\":\"\",\"updateTime\":\"2024-03-31 03:17:18\",\"usableColumn\":false},{\"capJavaField\":\"Context\",\"columnComment\":\"内容\",\"columnId\":3,\"columnName\":\"context\",\"columnType\":\"varchar(100)\",\"createBy\":\"admin\",\"createTime\":\"2024-03-31 03:13:37\",\"dictType\":\"\",\"edit\":true,\"htmlType\":\"input\",\"increment\":false,\"insert\":true,\"isEdit\":\"1\",\"isIncrement\":\"0\",\"isInsert\":\"1\",\"isList\":\"1\",\"isPk\":\"0\",\"isQuery\":\"1\",\"javaField\":\"context\",\"javaType\":\"String\",\"list\":true,\"params\":{},\"pk\":false,\"query\":true,\"queryType\":\"EQ\",\"required\":false,\"sort\":3,\"superColumn\":false,\"tableId\":1,\"updateBy\":\"\",\"updateTime\":\"2024-03-31 03:17:18\",\"usableColumn\":false},{\"capJavaField\":\"TempValue\",\"columnComment\":\"模版值\",\"columnId\":4,\"columnName\":\"temp_value\",\"columnType\":\"text\",\"createBy\":\"admin\",\"createTime\":\"2024-03-31 03:13:37\",\"dictType\":\"\",\"edit\":true,\"htmlType\":\"textarea\",\"increment\":false,\"insert\":true,\"isEdit\":\"1\",\"isIncrement\":\"0\",\"isInsert\":\"1\",\"isList\":\"1\",\"isPk\"', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-31 03:17:35'); +INSERT INTO `sys_oper_log` VALUES (106, '代码生成', 8, 'com.ruoyi.generator.controller.GenController.batchGenCode()', 'GET', 1, 'admin', NULL, '/tool/gen/batchGenCode', '127.0.0.1', '内网IP', '{\"tables\":\"business_template\"}', NULL, 0, NULL, '2024-03-31 03:34:27'); +INSERT INTO `sys_oper_log` VALUES (107, '模版管理', 1, 'com.ruoyi.business.controller.BusinessTemplateController.add()', 'POST', 1, 'admin', NULL, '/business/template', '127.0.0.1', '内网IP', '{\"params\":{}}', NULL, 1, 'Invalid bound statement (not found): com.ruoyi.business.mapper.BusinessTemplateMapper.insert', '2024-03-31 03:53:18'); +INSERT INTO `sys_oper_log` VALUES (108, '模版管理', 1, 'com.ruoyi.business.controller.BusinessTemplateController.add()', 'POST', 1, 'admin', NULL, '/business/template', '127.0.0.1', '内网IP', '{\"params\":{}}', NULL, 1, 'Invalid bound statement (not found): com.ruoyi.business.mapper.BusinessTemplateMapper.insert', '2024-03-31 03:54:16'); +INSERT INTO `sys_oper_log` VALUES (109, '模版管理', 1, 'com.ruoyi.business.controller.BusinessTemplateController.add()', 'POST', 1, 'admin', NULL, '/business/template', '127.0.0.1', '内网IP', '{\"params\":{}}', NULL, 1, 'Invalid bound statement (not found): com.ruoyi.business.mapper.BusinessTemplateMapper.insert', '2024-03-31 03:54:16'); +INSERT INTO `sys_oper_log` VALUES (110, '模版管理', 1, 'com.ruoyi.business.controller.BusinessTemplateController.add()', 'POST', 1, 'admin', NULL, '/business/template', '127.0.0.1', '内网IP', '{\"params\":{},\"tempValue\":\"\\n\\n\\n\"}', NULL, 1, 'Invalid bound statement (not found): com.ruoyi.business.mapper.BusinessTemplateMapper.insert', '2024-03-31 03:55:51'); +INSERT INTO `sys_oper_log` VALUES (111, '模版管理', 1, 'com.ruoyi.business.controller.BusinessTemplateController.add()', 'POST', 1, 'admin', NULL, '/business/template', '127.0.0.1', '内网IP', '{\"params\":{},\"tempValue\":\"\\n\\n\\n\",\"title\":\"ceshi\"}', NULL, 1, 'Invalid bound statement (not found): com.ruoyi.business.mapper.BusinessTemplateMapper.insert', '2024-03-31 03:55:51'); +INSERT INTO `sys_oper_log` VALUES (112, '模版管理', 1, 'com.ruoyi.business.controller.BusinessTemplateController.add()', 'POST', 1, 'admin', NULL, '/business/template', '127.0.0.1', '内网IP', '{\"params\":{},\"tempValue\":\"\\n\\n\\n\",\"title\":\"ceshi\"}', NULL, 1, 'Invalid bound statement (not found): com.ruoyi.business.mapper.BusinessTemplateMapper.insert', '2024-03-31 03:56:58'); +INSERT INTO `sys_oper_log` VALUES (113, '模版管理', 1, 'com.ruoyi.business.controller.BusinessTemplateController.add()', 'POST', 1, 'admin', NULL, '/business/template', '127.0.0.1', '内网IP', '{\"params\":{},\"tempValue\":\"\\n\\n\\n\"}', NULL, 1, 'Invalid bound statement (not found): com.ruoyi.business.mapper.BusinessTemplateMapper.insert', '2024-03-31 03:56:58'); +INSERT INTO `sys_oper_log` VALUES (114, '模版管理', 1, 'com.ruoyi.business.controller.BusinessTemplateController.add()', 'POST', 1, 'admin', NULL, '/business/template', '127.0.0.1', '内网IP', '{\"params\":{},\"tempValue\":\"\\n\\n\\n\",\"title\":\"ceshi\"}', NULL, 1, 'Invalid bound statement (not found): com.ruoyi.business.mapper.BusinessTemplateMapper.insert', '2024-03-31 03:59:35'); +INSERT INTO `sys_oper_log` VALUES (115, '模版管理', 1, 'com.ruoyi.business.controller.BusinessTemplateController.add()', 'POST', 1, 'admin', NULL, '/business/template', '127.0.0.1', '内网IP', '{\"params\":{},\"tempValue\":\"\\n\\n\\n\"}', NULL, 1, 'Invalid bound statement (not found): com.ruoyi.business.mapper.BusinessTemplateMapper.insert', '2024-03-31 03:59:35'); +INSERT INTO `sys_oper_log` VALUES (116, '模版管理', 1, 'com.ruoyi.business.controller.BusinessTemplateController.add()', 'POST', 1, 'admin', NULL, '/business/template', '127.0.0.1', '内网IP', '{\"params\":{},\"tempValue\":\"\\n\\n\\n\",\"title\":\"ceshi\"}', NULL, 1, 'nested exception is org.apache.ibatis.exceptions.PersistenceException: \r\n### Error updating database. Cause: java.lang.IllegalStateException: Type handler was null on parameter mapping for property \'params\'. It was either not specified and/or could not be found for the javaType (java.util.Map) : jdbcType (null) combination.\r\n### The error may exist in com/ruoyi/business/mapper/BusinessTemplateMapper.java (best guess)\r\n### The error may involve com.ruoyi.business.mapper.BusinessTemplateMapper.insert\r\n### The error occurred while executing an update\r\n### Cause: java.lang.IllegalStateException: Type handler was null on parameter mapping for property \'params\'. It was either not specified and/or could not be found for the javaType (java.util.Map) : jdbcType (null) combination.', '2024-03-31 04:10:33'); +INSERT INTO `sys_oper_log` VALUES (117, '模版管理', 1, 'com.ruoyi.business.controller.BusinessTemplateController.add()', 'POST', 1, 'admin', NULL, '/business/template', '127.0.0.1', '内网IP', '{\"params\":{},\"tempValue\":\"\\n\\n\\n\"}', NULL, 1, 'nested exception is org.apache.ibatis.exceptions.PersistenceException: \r\n### Error updating database. Cause: java.lang.IllegalStateException: Type handler was null on parameter mapping for property \'params\'. It was either not specified and/or could not be found for the javaType (java.util.Map) : jdbcType (null) combination.\r\n### The error may exist in com/ruoyi/business/mapper/BusinessTemplateMapper.java (best guess)\r\n### The error may involve com.ruoyi.business.mapper.BusinessTemplateMapper.insert\r\n### The error occurred while executing an update\r\n### Cause: java.lang.IllegalStateException: Type handler was null on parameter mapping for property \'params\'. It was either not specified and/or could not be found for the javaType (java.util.Map) : jdbcType (null) combination.', '2024-03-31 04:10:33'); +INSERT INTO `sys_oper_log` VALUES (118, '模版管理', 1, 'com.ruoyi.business.controller.BusinessTemplateController.add()', 'POST', 1, 'admin', NULL, '/business/template', '127.0.0.1', '内网IP', '{\"createBy\":\"admin\",\"createTime\":\"2024-03-31 04:14:19\",\"id\":\"1774168297470779393\",\"params\":{},\"tempValue\":\"\\n\\n\\n\",\"title\":\"ceshi\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-31 04:14:19'); +INSERT INTO `sys_oper_log` VALUES (119, '模版管理', 1, 'com.ruoyi.business.controller.BusinessTemplateController.add()', 'POST', 1, 'admin', NULL, '/business/template', '127.0.0.1', '内网IP', '{\"createBy\":\"admin\",\"createTime\":\"2024-03-31 04:14:19\",\"id\":\"1774168297470779394\",\"params\":{},\"tempValue\":\"\\n\\n\\n\"}', '{\"msg\":\"操作成功\",\"code\":200}', 0, NULL, '2024-03-31 04:14:19'); +INSERT INTO `sys_oper_log` VALUES (120, '模版管理', 1, 'com.ruoyi.business.controller.BusinessTemplateController.add()', 'POST', 1, 'admin', NULL, '/business/template', '127.0.0.1', '内网IP', '{\"createBy\":\"admin\",\"createTime\":\"2024-03-31 04:28:47\",\"id\":\"1774171941196881922\",\"params\":{},\"tempValue\":\"\\n" - }) - List getCardInfoByNumber(List number); -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/dao/CtClickFarmingDao.java b/wjcy-common/src/main/java/me/zhengjie/dao/CtClickFarmingDao.java deleted file mode 100644 index 1669d9e..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/dao/CtClickFarmingDao.java +++ /dev/null @@ -1,90 +0,0 @@ -package me.zhengjie.dao; - -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import me.zhengjie.entity.CtBuyerClickSuccess; -import me.zhengjie.entity.CtClickFarmYdParams; -import me.zhengjie.entity.CtClickFarming; -import me.zhengjie.service.vo.CtClickFarmEditDetailVO; -import me.zhengjie.service.vo.CtClickFarmingDetailVO; -import me.zhengjie.service.vo.CtClickFarmingVO; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Select; - -import java.util.List; - -/** - * 刷单Excel信息(CtClickFarming)表数据库访问层 - * - * @author rch - * @since 2022-08-16 - */ -@Mapper -public interface CtClickFarmingDao extends BaseMapper { - - // @Select("select farming.* from ct_click_farming farming left join ct_click_order clickOrder on farming.ct_click_order_id = clickOrder.id ${ew.customSqlSegment} ") - @Select("SELECT\n" + - "\tfarming.*,\n" + - "\tbuyer.contntry_short as country,\n" + - "\tbuyer.account\n" + - "FROM\n" + - "\tct_click_farming farming\n" + - "\tLEFT JOIN ct_click_order clickOrder ON farming.ct_click_order_id = clickOrder.id\n" + - "\tLEFT JOIN ct_buyer buyer ON buyer.id = farming.buyer_id\n" + - "${ew.customSqlSegment}") - IPage searchPageList(IPage page, Wrapper ew); - - @Select("select * from ct_click_farming where id = #{id} for update") - CtClickFarming getByIdLock(Long id); - - @Select("SELECT t1.*, t2.account AS buyer_name FROM ct_click_farming t1 LEFT JOIN ct_buyer t2 ON t1.buyer_id = t2.id where t1.id = #{id}") - CtClickFarmEditDetailVO getEditDetailById(Long id); - - @Select("SELECT t1.*, t2.account AS buyer_name FROM ct_click_farming t1 LEFT JOIN ct_buyer t2 ON t1.buyer_id = t2.id where t1.id = #{id}") - CtClickFarmingDetailVO getDetailById(Long id); - -// @Select("select buyer_id, count(1) as successCount from ct_click_farming where account != #{buyerAccount} and `status` = 3 GROUP BY buyer_id;") -// @Select("SELECT\n" + -// "\tclick.buyer_id,\n" + -// "\tcount( 1 ) AS successCount \n" + -// "FROM\n" + -// "\tct_click_farming AS click \t\n" + -// "\tLEFT JOIN ct_buyer AS buyer ON buyer.id = click.buyer_id and click.account != #{buyerAccount} AND click.status = 3\n" + -// "\tAND buyer.occupy_status = 2 AND buyer.country = #{country} and click.shopName != #{shopName} And ct\n" + -// "GROUP BY\n" + -// "\tbuyer_id;") -// @Select("SELECT click.buyer_id, count( 1 ) AS successCount, click.created_at FROM ct_click_farming AS click LEFT JOIN ct_buyer AS buyer ON buyer.id = click.buyer_id AND click.account != #{buyerAccount} AND click.STATUS = 3 AND buyer.occupy_status = 2 AND buyer.country = #{country} AND click.shop_name != #{shopName} GROUP BY buyer_id HAVING created_at < DATE_SUB(CURDATE(), INTERVAL 1 MONTH)") - @Select("SELECT click.buyer_id, count(1) AS successCount, click.status, click.created_at FROM ct_click_farming AS click LEFT JOIN ct_buyer AS buyer ON buyer.id = click.buyer_id AND click.account != #{buyerAccount} AND buyer.occupy_status = 2 AND buyer.country = #{country} AND click.shop_name != #{shopName} GROUP BY buyer_id HAVING created_at < DATE_SUB(CURDATE(), INTERVAL 1 MONTH) AND STATUS = 3") - List ruleGetCtBuyer(String buyerAccount, String country, String shopName); - - @Select("SELECT\n" + - "\tfarming.id,\n" + - "\tfarming.key_word as keyWord,\n" + - "\tfarming.number,\n" + - "\tfarming.params_type,\n" + - "\tfarming.specification,\n" + - "\tfarming.color,\n" + - "\tfarming.item,\n" + - "\tfarming.exchange,\n" + - "\tfarming.link,\n" + - "\tfarming.section_min as sectionMin,\n" + - "\tfarming.section_max as sectionMax,\n" + - "\tfarming.amessage,\n" + - "\tbuyer.contntry_short as country,\n" + - "\tbuyer.account,\n" + - "\tbuyer.pwd,\n" + - "\tctVpn.link as vpnShare,\n" + - "\tctCard.term_of_validity as termOfValidity,\n" + - "\tCONCAT(ctCard.holder_surname, \" \",ctCard.holder_name) AS cardName,\n" + - "\tctCard.number as cardNumber,\n" + - "\tctCard.pwd as cardPwd\n" + - "FROM\n" + - "\tct_click_farming farming\n" + - "\tLEFT JOIN ct_click_order clickOrder ON farming.ct_click_order_id = clickOrder.id\n" + - "\tLEFT JOIN ct_buyer buyer ON buyer.id = farming.buyer_id\n" + - "\tLEFT JOIN ct_vpn ctVpn ON buyer.vpn_id = ctVpn.id\n" + - "\tLEFT JOIN ct_card ctCard ON buyer.card_id = ctCard.id where farming.id = #{id}") - CtClickFarmYdParams getCtClickFarmYdParams(Long id); -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/dao/CtClickOrderDao.java b/wjcy-common/src/main/java/me/zhengjie/dao/CtClickOrderDao.java deleted file mode 100644 index b90cfa3..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/dao/CtClickOrderDao.java +++ /dev/null @@ -1,100 +0,0 @@ -package me.zhengjie.dao; - -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import me.zhengjie.entity.CtClickFarmingOrderInfo; -import me.zhengjie.entity.CtClickOrder; -import me.zhengjie.service.vo.CtClickOrderDetailVO; -import me.zhengjie.service.vo.CtClickOrderListVO; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Select; - -/** - * 刷单-订单信息(CtClickOrder)表数据库访问层 - * - * @author rch - * @since 2022-09-14 - */ -@Mapper -public interface CtClickOrderDao extends BaseMapper { - - /** - * 分页查询 - * @param page - * @param ew - */ - //TODO sql 修改 -// @Select("SELECT\n" + -// "\t`order`.platform_id, \n" + -// "\t`order`.company_id, \n" + -// "\t`order`.id, \n" + -// "\t`order`.created_at, \n" + -// "\t`order`.updated_at, \n" + -// "\t`order`.amount, \n" + -// "\t`order`.shop, \n" + -// "\t`order`.order_id, \n" + -// "\t`order`.comment, \n" + -// "\t`order`.account, \n" + -// "\t`order`.pwd, \n" + -// "\tcompany.`name` AS companyName, \n" + -// "\tplatform.`name` AS platformName\n" + -// "FROM\n" + -// "\tct_click_order AS `order`\n" + -// "\tLEFT JOIN\n" + -// "\tct_platform AS platform\n" + -// "\tON \n" + -// "\t\t`order`.platform_id = platform.id\n" + -// "\tLEFT JOIN\n" + -// "\tct_company AS company\n" + -// "\tON \n" + -// "\t\t`order`.company_id = company.id ${ew.customSqlSegment} ") - @Select("SELECT clickOrder.company_id, clickOrder.type, clickOrder.status, clickOrder.id, clickOrder.created_at, clickOrder.updated_at, clickOrder.amount, clickOrder.shop, clickOrder.order_id, clickOrder.comment, company.name AS companyName FROM ct_click_order AS clickOrder LEFT JOIN ct_company AS company ON clickOrder.company_id = company.id ${ew.customSqlSegment}") - IPage searchPageList(IPage page, Wrapper ew); - - @Select("SELECT\n" + - "\tclickOrder.id,\n" + - "\tclickOrder.order_id,\n" + - "\tclickOrder.COMMENT,\n" + - "\tclickOrder.STATUS,\n" + - "\tclickOrder.paths,\n" + - "\tbuyer.country,\n" + - "\tbuyer.account,\n" + - "\tbuyer.pwd,\n" + - "\tctVpn.link as vpnShare\n" + - "FROM\n" + - "\tct_click_order clickOrder\n" + - "\tLEFT JOIN ct_click_farming clickFarming ON clickOrder.id = clickFarming.ct_click_order_id \n" + - "\tLEFT JOIN ct_buyer buyer ON buyer.id = clickFarming.buyer_id\n" + - "\tLEFT JOIN ct_vpn ctVpn ON buyer.vpn_id = ctVpn.id\n" + - "WHERE \n" + - "\tclickOrder.id = #{orderId}") - CtClickFarmingOrderInfo getClickFarmOrderById(Long orderId); - - @Select("select * from ct_click_order where id = #{id} for update") - CtClickOrder getByIdLock(Long id); - - @Select("SELECT\n" + - "\tclickOrder.id,\n" + - "\tclickOrder.created_at,\n" + - "\tclickOrder.updated_at,\n" + - "\tclickOrder.prices_number,\n" + - "\tclickOrder.payment_results,\n" + - "\tclickOrder.order_id,\n" + - "\tclickOrder.COMMENT,\n" + -// "\tclickOrder.status,\n" + -// "\tclickOrder.platform_id,\n" + - "\tclickOrder.company_id,\n" + - "\tclickOrder.amount,\n" + - "\tclickOrder.shop,\n" + - "\tclickOrder.shop_name,\n" + - "\tclickOrder.order_date,\n" + - "\tclickOrder.paths\n" + - "FROM\n" + - "\tct_click_order clickOrder\n" + - "\tLEFT JOIN ct_click_farming clickFarming ON clickOrder.id = clickFarming.ct_click_order_id \n" + - "WHERE\n" + - "\tclickOrder.id = #{orderId}") - CtClickOrderDetailVO getClickOrderDetailById(Long id); -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/dao/CtCompanyDao.java b/wjcy-common/src/main/java/me/zhengjie/dao/CtCompanyDao.java deleted file mode 100644 index a5ff0de..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/dao/CtCompanyDao.java +++ /dev/null @@ -1,34 +0,0 @@ -package me.zhengjie.dao; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import me.zhengjie.entity.CtCompany; -import me.zhengjie.entity.CtCompanyInfo; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; - -import java.util.List; - -/** - * 公司信息(CtCompany)表数据库访问层 - * - * @author zhw - * @since 2022-07-14 - */ -@Mapper -public interface CtCompanyDao extends BaseMapper { - - @Select({ - "" - }) - List getByName(@Param("names") List names); - - @Select("select id,name from ct_company") - List getCompanyList(); -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/dao/CtDhPayDao.java b/wjcy-common/src/main/java/me/zhengjie/dao/CtDhPayDao.java deleted file mode 100644 index 3bc6536..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/dao/CtDhPayDao.java +++ /dev/null @@ -1,24 +0,0 @@ -package me.zhengjie.dao; - -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import me.zhengjie.entity.CtDhPay; -import me.zhengjie.service.vo.CtBuyerListVO; -import me.zhengjie.service.vo.CtDhPayListVO; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Select; - -/** - * 平台信息(CtDyPay)表数据库访问层 - * - * @author rch - * @since 2022-07-28 - */ -@Mapper -public interface CtDhPayDao extends BaseMapper { - - @Select("select * from ct_dh_pay ${ew.customSqlSegment}") - IPage searchPageList(IPage page, Wrapper ew); -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/dao/CtExcelDao.java b/wjcy-common/src/main/java/me/zhengjie/dao/CtExcelDao.java deleted file mode 100644 index 1291b82..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/dao/CtExcelDao.java +++ /dev/null @@ -1,17 +0,0 @@ -package me.zhengjie.dao; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import me.zhengjie.entity.CtExcel; -import org.apache.ibatis.annotations.Mapper; - -/** - * Excel 导入信息(CtExcel)表数据库访问层 - * - * @author makejava - * @since 2022-06-23 10:37:44 - */ -@Mapper -public interface CtExcelDao extends BaseMapper { - -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/dao/CtExcelImportInfoDao.java b/wjcy-common/src/main/java/me/zhengjie/dao/CtExcelImportInfoDao.java deleted file mode 100644 index 94f2f76..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/dao/CtExcelImportInfoDao.java +++ /dev/null @@ -1,17 +0,0 @@ -package me.zhengjie.dao; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import me.zhengjie.entity.CtExcelImportInfo; -import org.apache.ibatis.annotations.Mapper; - -/** - * Excel导入信息(CtExcelImportInfo)表数据库访问层 - * - * @author rch - * @since 2022-06-23 - */ -@Mapper -public interface CtExcelImportInfoDao extends BaseMapper { - -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/dao/CtOrderDao.java b/wjcy-common/src/main/java/me/zhengjie/dao/CtOrderDao.java deleted file mode 100644 index c20f9da..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/dao/CtOrderDao.java +++ /dev/null @@ -1,17 +0,0 @@ -package me.zhengjie.dao; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import me.zhengjie.entity.CtOrder; -import org.apache.ibatis.annotations.Mapper; - -/** - * (CtOrder)表数据库访问层 - * - * @author rch - * @since 2022-07-01 - */ -@Mapper -public interface CtOrderDao extends BaseMapper { - -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/dao/CtPlatformDao.java b/wjcy-common/src/main/java/me/zhengjie/dao/CtPlatformDao.java deleted file mode 100644 index 486b02c..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/dao/CtPlatformDao.java +++ /dev/null @@ -1,17 +0,0 @@ -package me.zhengjie.dao; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import me.zhengjie.entity.CtPlatform; -import org.apache.ibatis.annotations.Mapper; - -/** - * 平台信息(CtPlatform)表数据库访问层 - * - * @author rch - * @since 2022-06-23 10:37:44 - */ -@Mapper -public interface CtPlatformDao extends BaseMapper { - -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/dao/CtRebotDao.java b/wjcy-common/src/main/java/me/zhengjie/dao/CtRebotDao.java deleted file mode 100644 index 589314c..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/dao/CtRebotDao.java +++ /dev/null @@ -1,41 +0,0 @@ -package me.zhengjie.dao; - -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import me.zhengjie.base.BaseEntity; -import me.zhengjie.entity.CtRebot; -import me.zhengjie.service.vo.CtRebotListVO; -import me.zhengjie.utils.PageUtils; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Select; -import org.apache.ibatis.annotations.Update; - -import java.util.List; - -/** - * 影刀设备-机器人信息(CtRebot)表数据库访问层 - * - * @author rch - * @since 2022-07-23 - */ -@Mapper -public interface CtRebotDao extends BaseMapper { - - @Select("select * from ct_rebot where account_name = #{accountName} for update") - CtRebot getByAccountNameLock(String accountName); - - - @Select("select * from ct_rebot ${ew.customSqlSegment}") - IPage searchRebotList(IPage page, Wrapper ew); - - @Select("select account_name from ct_rebot") - List getAccountNameList(); - - @Select("select robot_client_uuid from ct_rebot") - List getClientUuidList(); - - @Update("update ct_rebot set status = #{newStatus} where id = #{id} and status = #{oldStatus}") - Boolean updateNewStatusByOldStatus(Long id, Integer newStatus, Integer oldStatus); -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/dao/CtResponseOrderAddressDao.java b/wjcy-common/src/main/java/me/zhengjie/dao/CtResponseOrderAddressDao.java deleted file mode 100644 index e2195fb..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/dao/CtResponseOrderAddressDao.java +++ /dev/null @@ -1,17 +0,0 @@ -package me.zhengjie.dao; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import me.zhengjie.entity.CtResponseOrderAddress; -import org.apache.ibatis.annotations.Mapper; - -/** - * 下注成功订单响应收货地址信息(CtResponseOrderAddress)表数据库访问层 - * - * @author rch - * @since 2022-07-01 - */ -@Mapper -public interface CtResponseOrderAddressDao extends BaseMapper { - -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/dao/CtResponseOrderDao.java b/wjcy-common/src/main/java/me/zhengjie/dao/CtResponseOrderDao.java deleted file mode 100644 index 5824efb..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/dao/CtResponseOrderDao.java +++ /dev/null @@ -1,17 +0,0 @@ -package me.zhengjie.dao; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import me.zhengjie.entity.CtResponseOrder; -import org.apache.ibatis.annotations.Mapper; - -/** - * 下单成功响应订单商品信息(CtResponseOrder)表数据库访问层 - * - * @author rch - * @since 2022-07-01 - */ -@Mapper -public interface CtResponseOrderDao extends BaseMapper { - -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/dao/CtResponseOrderProductDao.java b/wjcy-common/src/main/java/me/zhengjie/dao/CtResponseOrderProductDao.java deleted file mode 100644 index 0ff58c8..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/dao/CtResponseOrderProductDao.java +++ /dev/null @@ -1,17 +0,0 @@ -package me.zhengjie.dao; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import me.zhengjie.entity.CtResponseOrderProduct; -import org.apache.ibatis.annotations.Mapper; - -/** - * 下单订单响应产品信息(CtResponseOrderProduct)表数据库访问层 - * - * @author rch - * @since 2022-07-01 - */ -@Mapper -public interface CtResponseOrderProductDao extends BaseMapper { - -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/dao/CtVpnDao.java b/wjcy-common/src/main/java/me/zhengjie/dao/CtVpnDao.java deleted file mode 100644 index 7d0aa3e..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/dao/CtVpnDao.java +++ /dev/null @@ -1,35 +0,0 @@ -package me.zhengjie.dao; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import me.zhengjie.entity.CtVpn; -import me.zhengjie.entity.CtVpnInfo; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Select; - -import java.util.List; - -/** - * VPN信息表(CtVpn)表数据库访问层 - * - * @author rch - * @since 2022-07-07 - */ -@Mapper -public interface CtVpnDao extends BaseMapper { - - @Select("select ip_address from ct_vpn") - List getIpList(); - - //@Select("select id,ip_address from ct_vpn where ip_address in ${ipAddress}") - @Select({ - "" - }) - List getVpnInfoByIp(List ipAddress); - -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/dao/DhAddCarDao.java b/wjcy-common/src/main/java/me/zhengjie/dao/DhAddCarDao.java deleted file mode 100644 index 89e96ba..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/dao/DhAddCarDao.java +++ /dev/null @@ -1,61 +0,0 @@ -package me.zhengjie.dao; - -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import me.zhengjie.entity.DhAddCar; -import me.zhengjie.service.vo.dhaddcar.DhAddCarVO; -import me.zhengjie.service.vo.dhaddcar.DhAddCarListVO; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Select; - -/** - * 敦煌加入购物车(DhAddCar)表数据库访问层 - * - * @author rch - * @since 2022-11-17 09:11:53 - */ -@Mapper -public interface DhAddCarDao extends BaseMapper { - - @Select("SELECT\n" + - "\tdhAddCar.*,\n" + - "\tbuyer.id AS buyerId,\n" + - "\tbuyer.account,\n" + - "\tbuyer.contntry_short AS country,\n" + - "\tcompany.NAME AS companyName\n" + - "\t\n" + - "FROM\n" + - "\tdh_add_car AS dhAddCar\n" + - "LEFT JOIN\n" + - "\tct_buyer buyer ON dhAddCar.buyer_id = buyer.id\n" + - "LEFT JOIN\n" + - "\tct_company company ON buyer.company_id = company.id\n" + - "\t${ew.customSqlSegment}") - IPage searchPageList(IPage page, Wrapper ew); - - - @Select("SELECT\n" + - " dhAddCar.id,\n" + - "\tdhAddCar.params_type,\n" + - "\tdhAddCar.car_good_ids AS carGoodIds,\n" + - "\tbuyer.id AS buyerId,\n" + - "\tbuyer.account,\n" + - "\tbuyer.contntry_short as country,\n" + - "\tbuyer.pwd,\n" + - "\tvpn.link as vpnShare,\n" + - "\tdhAddCar.status,\n" + - "\tcompany.NAME AS companyName\n" + - "FROM\n" + - "\tdh_add_car AS dhAddCar\n" + - "\tLEFT JOIN ct_buyer buyer ON dhAddCar.buyer_id = buyer.id\n" + - "\tLEFT JOIN ct_vpn vpn ON buyer.vpn_id = vpn.id\n" + - "\tLEFT JOIN\n" + - "\tct_company company ON buyer.company_id = company.id\n" + - "\tWHERE dhAddCar.id = #{id}") - DhAddCarVO getDetailById(Long id); - - @Select("select * from dh_add_car where id = #{id}") - DhAddCar getByIdLock(Long id); -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/dao/DhAddCarOrderDao.java b/wjcy-common/src/main/java/me/zhengjie/dao/DhAddCarOrderDao.java deleted file mode 100644 index c103c95..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/dao/DhAddCarOrderDao.java +++ /dev/null @@ -1,48 +0,0 @@ -package me.zhengjie.dao; - -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import me.zhengjie.entity.DhAddCarOrder; -import me.zhengjie.service.vo.dhaddcar.DhAddCarListVO; -import me.zhengjie.service.vo.dhcarorder.DhAddCarOrderListVO; -import me.zhengjie.service.vo.dhcarorder.DhCarOrderParamsVO; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Select; - -/** - * 敦煌-加购物车-订单(DhAddCarOrder)表数据库访问层 - * - * @author rch - * @since 2022-11-17 09:11:57 - */ -@Mapper -public interface DhAddCarOrderDao extends BaseMapper { - - @Select("select * from dh_add_car_order where id = #{id} for update") - DhAddCarOrder getByIdLock(Long id); - - @Select("select * from dh_add_car_order ${ew.customSqlSegment}") - IPage searchPageList(IPage page, Wrapper ew); - - @Select("SELECT\n" + - "\tdhAddCarOrder.id,\n" + - "\tdhAddCarOrder.order_id,\n" + - "\tdhAddCar.params_type,\n" + - "\tdhAddCar.car_good_ids AS carGoodIds,\n" + - "\tbuyer.id AS buyerId,\n" + - "\tbuyer.account,\n" + - "\tbuyer.contntry_short AS country,\n" + - "\tbuyer.pwd,\n" + - "\tvpn.link AS vpnShare\n" + - "FROM\n" + - "\tdh_add_car_order as dhAddCarOrder\n" + - "\tLEFT JOIN dh_add_car dhAddCar ON dhAddCar.id = dhAddCarOrder.add_car_id\n" + - "\tLEFT JOIN ct_buyer buyer ON dhAddCar.buyer_id = buyer.id\n" + - "\tLEFT JOIN ct_vpn vpn ON buyer.vpn_id = vpn.id\n" + - "\tLEFT JOIN ct_company company ON buyer.company_id = company.id \n" + - "WHERE\n" + - "\tdhAddCarOrder.id = #{id}") - DhCarOrderParamsVO getYdParams(Long id); -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/dao/DhCarGoodsDao.java b/wjcy-common/src/main/java/me/zhengjie/dao/DhCarGoodsDao.java deleted file mode 100644 index 8aa8743..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/dao/DhCarGoodsDao.java +++ /dev/null @@ -1,17 +0,0 @@ -package me.zhengjie.dao; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import me.zhengjie.entity.DhCarGoods; -import org.apache.ibatis.annotations.Mapper; - -/** - * 敦煌-加入购物车商品信息(DhCarGoods)表数据库访问层 - * - * @author makejava - * @since 2022-11-17 09:12:01 - */ -@Mapper -public interface DhCarGoodsDao extends BaseMapper { - -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/dao/LoginIpDao.java b/wjcy-common/src/main/java/me/zhengjie/dao/LoginIpDao.java deleted file mode 100644 index 0acee04..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/dao/LoginIpDao.java +++ /dev/null @@ -1,17 +0,0 @@ -package me.zhengjie.dao; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import me.zhengjie.entity.LoginIp; -import org.apache.ibatis.annotations.Mapper; - -/** - * (LoginIp)表数据库访问层 - * - * @author zeng - * @since 2022-03-21 14:07:01 - */ -@Mapper -public interface LoginIpDao extends BaseMapper { - -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/dao/SettingSiteDao.java b/wjcy-common/src/main/java/me/zhengjie/dao/SettingSiteDao.java deleted file mode 100644 index b4f548f..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/dao/SettingSiteDao.java +++ /dev/null @@ -1,17 +0,0 @@ -package me.zhengjie.dao; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import me.zhengjie.entity.CtSettingSite; -import org.apache.ibatis.annotations.Mapper; - -/** - * 站点配置(CtSettingSite)表数据库访问层 - * - * @author rch - * @since 2021-11-23 - */ -@Mapper -public interface SettingSiteDao extends BaseMapper { - String getValueByKey(String key); -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/dao/SysQuartzJobDao.java b/wjcy-common/src/main/java/me/zhengjie/dao/SysQuartzJobDao.java deleted file mode 100644 index ca96b7c..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/dao/SysQuartzJobDao.java +++ /dev/null @@ -1,26 +0,0 @@ -package me.zhengjie.dao; - -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import me.zhengjie.entity.SysQuartzJob; -import me.zhengjie.service.vo.SysQuartzJobListVO; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Select; - -/** - * 定时任务(SysQuartzJob)表数据库访问层 - * - * @author zhw - * @since 2022-07-21 - */ -@Mapper -public interface SysQuartzJobDao extends BaseMapper { - - @Select("select * from sys_quartz_job ${ew.customSqlSegment}") - IPage searchPageList(IPage page, Wrapper ew); - - @Select("select * from sys_quartz_job where task_num = #{taskNum}") - SysQuartzJob getByTaskNum(String taskNum); -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/dao/SysQuartzLogDao.java b/wjcy-common/src/main/java/me/zhengjie/dao/SysQuartzLogDao.java deleted file mode 100644 index 64b4ba5..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/dao/SysQuartzLogDao.java +++ /dev/null @@ -1,23 +0,0 @@ -package me.zhengjie.dao; - -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import me.zhengjie.entity.SysQuartzLog; -import me.zhengjie.service.vo.SysQuartzLogListVO; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Select; - -/** - * 定时任务(SysQuartzLog)表数据库访问层 - * - * @author rch - * @since 2022-07-20 - */ -@Mapper -public interface SysQuartzLogDao extends BaseMapper { - - @Select("select * from sys_quartz_log ${ew.customSqlSegment} ") - IPage searchPageList(IPage page, Wrapper ew); -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/dao/mapper/CtDhPayService.xml b/wjcy-common/src/main/java/me/zhengjie/dao/mapper/CtDhPayService.xml deleted file mode 100644 index 25a0430..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/dao/mapper/CtDhPayService.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/wjcy-common/src/main/java/me/zhengjie/dto/Dto.java b/wjcy-common/src/main/java/me/zhengjie/dto/Dto.java deleted file mode 100644 index 159b385..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/dto/Dto.java +++ /dev/null @@ -1,73 +0,0 @@ -package me.zhengjie.dto; - - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.error.ErrorCodeEnum; - -import java.io.Serializable; -import java.util.HashMap; -import java.util.Map; - -/** - *

- * 请求结果通用数据结构 - *

- * - * @author: zeng - * @since: 2020-07-01 - */ -@Data -@NoArgsConstructor -@AllArgsConstructor -@Slf4j -public class Dto implements Serializable { - - private int code; - - private String message; - - private T data; - - private Dto(Object data) { - this.code = 200; - this.message = "请求成功"; - this.data =(T) data; - } - - private Dto(int code, String message) { - this.code = code; - this.message = message; - } - - public Dto setData(String key, Object value) { - if (this.data == null) { - data = (T)new HashMap(16); - } - ((Map) data).put(key, value); - return this; - } - - public static Dto returnResult(Object data) { - return new Dto(data); - } - - public static Dto returnErrorResult(String message) { - return new Dto(-1, message); - } - - public static Dto getInstance(ErrorCodeEnum errorCodeEnum) { - log.error("---枚举类返回错误信息:--return error:" + errorCodeEnum.getDesc()); - return new Dto(errorCodeEnum.getCode(), errorCodeEnum.getDesc()); - } - - public boolean success(Dto dto){ - if (dto.getCode() == 200) { - return true; - } else { - return false; - } - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/dto/PageDTO.java b/wjcy-common/src/main/java/me/zhengjie/dto/PageDTO.java deleted file mode 100644 index ed0fa84..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/dto/PageDTO.java +++ /dev/null @@ -1,49 +0,0 @@ -package me.zhengjie.dto; - -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import lombok.Data; - -import javax.validation.constraints.Min; -import javax.validation.constraints.NotNull; -import java.io.Serializable; - -/** - * @Description 分页查询参数 - * @Date 2022-06-22 - * @Author rch - */ -@Data -public class PageDTO implements Serializable { - - private static final long serialVersionUID = 1L; - - /** 当前页码 */ - @Min(value = 1) - @NotNull - private Integer page; - /** 页面大小 */ - @Min(value = 1) - @NotNull - private Integer pageSize; - /** 排序字段 */ - private String sort; - /** 排序方式 asc/desc */ - private String order; - - /** 获取mysql limit 分页的起始位置 */ - public Integer getLimitStart() { - int i = (page-1)*pageSize; - return i > 0 ? i : 0; - } - - public IPage getiPage(){ - return new Page(page, pageSize); - } - - - public boolean isAsc() { - return "asc".equalsIgnoreCase(order); - } - -} diff --git a/wjcy-common/src/main/java/me/zhengjie/dto/StatementAggregateDTO.java b/wjcy-common/src/main/java/me/zhengjie/dto/StatementAggregateDTO.java deleted file mode 100644 index ba9bf10..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/dto/StatementAggregateDTO.java +++ /dev/null @@ -1,38 +0,0 @@ -package me.zhengjie.dto; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.utils.PageUtils; - -import java.util.List; - -/** - * 本页合计、总计DTO - * @author zeng - * @since 2021/10/11 19:37 - */ -@Data -@NoArgsConstructor -@AllArgsConstructor -public class StatementAggregateDTO { - - /** 列表 */ - private List list; - - /** 本页小计 */ - private T pageTotal; - - /** 总计 */ - private T aggregate; - - /** 总记录数 */ - private Long total; - - public StatementAggregateDTO(PageUtils pageUtils, T pageTotal, T aggregate) { - this.list = pageUtils.getList(); - this.pageTotal = pageTotal; - this.aggregate = aggregate; - this.total = pageUtils.getTotal(); - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtApply.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtApply.java deleted file mode 100644 index f09b9de..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtApply.java +++ /dev/null @@ -1,73 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.extension.activerecord.Model; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.Date; - -/** - * 影刀应用信息(CtApply)表实体类 - * - * @author rch - * @since 2022-07-23 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel -public class CtApply extends Model { - - @TableId(value = "id", type = IdType.AUTO) - @ApiModelProperty(value = "id") - private Long id; - - @TableField(fill = FieldFill.INSERT) - @ApiModelProperty(value = "创建时间") - private String createdAt; - - @TableField(fill = FieldFill.INSERT_UPDATE) - @ApiModelProperty(value = "修改时间") - private String updatedAt; - - /** 操作人账号*/ - @TableField(fill = FieldFill.INSERT_UPDATE) - @ApiModelProperty(value = "操作人账号") - private String gmName; - - /** 应用名称 */ - @ApiModelProperty(value = "应用名称") - private String name; - - /** 任务名称 */ - @ApiModelProperty(value = "任务名称") - private String taskName; - - /** 方法名称 */ - @ApiModelProperty(value = "方法名称") - private String methodName; - - /** accessKeyId */ - @ApiModelProperty(value = "accessKeyId") - private String accessKeyId; - - /** accessKeySecret */ - @ApiModelProperty(value = "accessKeySecret") - private String accessKeySecret; - - /** 应用id */ - @ApiModelProperty(value = "应用id") - private String robotUuid; - - /** 备注 */ - @ApiModelProperty(value = "备注") - private String remark; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtBrowse.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtBrowse.java deleted file mode 100644 index 2a64547..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtBrowse.java +++ /dev/null @@ -1,45 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 浏览收藏(CtBrowse)表实体类 - * - * @author rch - * @since 2022-11-04 09:45:31 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtBrowse extends Model { - - @TableId(value = "id", type = IdType.AUTO) - private Long id; - @TableField(fill = FieldFill.INSERT) - private String createdAt; - @TableField(fill = FieldFill.INSERT_UPDATE) - private String updatedAt; - /** 操作人账号*/ - @TableField(fill = FieldFill.INSERT_UPDATE) - private String gmName; - - /** 买家ID */ - private Long buyerId; - - /** 收藏链接 */ - private String linkUrl; - - /** 状态描述 */ - private String paymentResults; - - /** 状态 1.待执行 2.执行中 3.执行成功 4.执行失败 */ - private Integer status; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtBrowseYdParams.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtBrowseYdParams.java deleted file mode 100644 index 89f99a6..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtBrowseYdParams.java +++ /dev/null @@ -1,33 +0,0 @@ -package me.zhengjie.entity; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 浏览好评订单影刀参数 - * - * @author rch - * @since 2022-11-07 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtBrowseYdParams { - private Long id; - - /** 国家 */ - private String country; - - /** 账号 */ - private String account; - - /** 密码 */ - private String pwd; - - /** vpn分享链接 */ - private String vpnShare; - - /** 收藏链接 */ - private String linkUrl; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtBuyer.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtBuyer.java deleted file mode 100644 index 49ab741..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtBuyer.java +++ /dev/null @@ -1,103 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.math.BigDecimal; -/** - * 买家信息表(CtBuyer)表实体类 - * - * @author rch - * @since 2022-06-22 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtBuyer extends Model { - - @TableId(value = "id", type = IdType.AUTO) - private Long id; - @TableField(fill = FieldFill.INSERT) - private String createdAt; - @TableField(fill = FieldFill.INSERT_UPDATE) - private String updatedAt; - /** 操作人账号*/ - @TableField(fill = FieldFill.INSERT_UPDATE) - private String gmName; - - /** 昵称*/ - private String nickName; - /** 账号*/ - private String account; - /** 密码*/ - private String pwd; - /** 公司id */ - private Long companyId; - /** 平台id */ - private Integer platformId; - /** 平台名称 */ -// private String platformName; - - // TODO 导入需要的字段接着往下添加 - - /** 国家 */ - private String contntryShort; - /** 邮件 */ - private String email; - /** Email密码 */ - private String emailPwd; - /** VPN_ID(导入excel里包含) */ - private Long vpnId; - /** 信用卡ID */ - private Long cardId; - /** 用户等级(导入默认内部账号) 1.普通 2.精品 3.压力 4.内部账号 */ - private Integer level; - /** 占用状态 1.已占用 2.未占用 */ - private Integer occupyStatus; - /** 占用账户 */ - private String occupyAccount; - /** 账户余额 */ - private BigDecimal balance; - /** 账户购买总金额 */ - private BigDecimal buyTotalMoney; - /** mac */ - private String mac; - /** route_mac*/ - private String routeMac; - /** Cookies值 */ - private String cookies; - /** 过期时间 */ - private String expireDate; - /** 状态(导入默认正常) 1.待注册 2待验证 3.待完善 4.正常 5.异常 6.可用但已用 7.删除 */ - private Integer status; - - // ==================地址信息相关========================================begin - /** 地址1 */ - private String addressline1; - /** 国家 */ - private String country; - /** 州 */ - private String state; - /** 电话 */ - private String tel; - /** lastname */ - private String lastname; - /** 税号 */ - private String vatNumber; - /** 城市 */ - private String city; - /** 地址2 */ - private String addressline2; - /** firstname */ - private String firstname; - /** 邮政编码 */ - private String postalcode; - // ==================地址信息相关========================================end -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtBuyerClickSuccess.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtBuyerClickSuccess.java deleted file mode 100644 index 13f46d8..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtBuyerClickSuccess.java +++ /dev/null @@ -1,19 +0,0 @@ -package me.zhengjie.entity; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 统计买家刷单成功个数信息 - * - * @author rch - * @create 2022-10-10 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtBuyerClickSuccess { - private Long buyerId; - private Integer successCount; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtBuyerContactInfo.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtBuyerContactInfo.java deleted file mode 100644 index a680207..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtBuyerContactInfo.java +++ /dev/null @@ -1,45 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.math.BigDecimal; - -/** - * 买家收款地址信息 - * - * @author rch - * @since 2022-07-18 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtBuyerContactInfo { - /** 地址1 */ - private String addressline1; - /** 国家 */ - private String country; - /** 州 */ - private String state; - /** 电话 */ - private String tel; - /** lastname */ - private String lastname; - /** 税号 */ - private String vatNumber; - /** 城市 */ - private String city; - /** 地址2 */ - private String addressline2; - /** firstname */ - private String firstname; - /** 邮政编码 */ - private String postalcode; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtBuyerExport.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtBuyerExport.java deleted file mode 100644 index 92efaa9..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtBuyerExport.java +++ /dev/null @@ -1,71 +0,0 @@ -package me.zhengjie.entity; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.utils.excel.ExcelExport; - - -/** - * 买家信息(CtBuyer)表实体类 导出对象信息 - * @author zhw - * @since 2022-07-14 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtBuyerExport { - - - @ExcelExport(value = "昵称") - /** 昵称*/ - private String nickName; - /** 账号*/ - @ExcelExport(value = "账号") - private String account; - /** 密码*/ - @ExcelExport(value = "密码") - private String pwd; - /** 公司名称 */ - @ExcelExport(value = "公司名称") - private String companyName; - /** 平台名称 */ - @ExcelExport(value = "平台名称") - private String platformName; - /** 国家 */ - @ExcelExport(value = "所属国家") - private String contntryShort; - /** VPN_IP地址*/ - @ExcelExport(value = "VPN_IP地址") - private String vpnIp; - /** 信用卡卡号 */ - @ExcelExport(value = "信用卡卡号") - private String cardNumber; - /** 地址1 */ - @ExcelExport(value = "地址1") - private String addressline1; - /** 国家 */ - @ExcelExport(value = "国家") - private String country; - /** 州 */ - @ExcelExport(value = "州") - private String state; - /** 电话 */ - @ExcelExport(value = "电话") - private String tel; - /** lastname */ - @ExcelExport(value = "lastname") - private String lastname; - /** 城市 */ - @ExcelExport(value = "城市") - private String city; - /** firstname */ - @ExcelExport(value = "firstname") - private String firstname; - /** 邮政编码 */ - @ExcelExport(value = "邮政编码") - private String postalcode; - /** 异常信息 */ - @ExcelExport(value = "异常信息") - private String error; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtBuyerExportTemple.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtBuyerExportTemple.java deleted file mode 100644 index c92d084..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtBuyerExportTemple.java +++ /dev/null @@ -1,67 +0,0 @@ -package me.zhengjie.entity; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.utils.excel.ExcelExport; - - -/** - * 买家信息(CtBuyer)表实体类 导出excel模板 - * @author zhw - * @since 2022-07-18 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtBuyerExportTemple { - - @ExcelExport(value = "昵称") - /** 昵称*/ - private String nickName; - /** 账号*/ - @ExcelExport(value = "账号") - private String account; - /** 密码*/ - @ExcelExport(value = "密码") - private String pwd; - /** 公司名称 */ - @ExcelExport(value = "公司名称") - private String companyName; - /** 平台名称 */ - @ExcelExport(value = "平台名称") - private String platformName; - /** 国家 */ - @ExcelExport(value = "所属国家") - private String contntryShort; - /** VPN_IP地址*/ - @ExcelExport(value = "VPN_IP地址") - private String vpnIp; - /** 信用卡卡号 */ - @ExcelExport(value = "信用卡卡号") - private String cardNumber; - /** 地址1 */ - @ExcelExport(value = "地址1") - private String addressline1; - /** 国家 */ - @ExcelExport(value = "国家") - private String country; - /** 州 */ - @ExcelExport(value = "州") - private String state; - /** 电话 */ - @ExcelExport(value = "电话") - private String tel; - /** lastname */ - @ExcelExport(value = "lastname") - private String lastname; - /** 城市 */ - @ExcelExport(value = "城市") - private String city; - /** firstname */ - @ExcelExport(value = "firstname") - private String firstname; - /** 邮政编码 */ - @ExcelExport(value = "邮政编码") - private String postalcode; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtBuyerImport.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtBuyerImport.java deleted file mode 100644 index 742bbdb..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtBuyerImport.java +++ /dev/null @@ -1,84 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.utils.excel.ExcelImport; - -/** - * Buyer信息(CtBuyer)表实体类 Import - * - * @author zhw - * @since 2022-07-14 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtBuyerImport { - - private int rowNum; - private String rowTips; - - @TableId(value = "id", type = IdType.AUTO) - private Long id; - @TableField(fill = FieldFill.INSERT) - private String createdAt; - @TableField(fill = FieldFill.INSERT_UPDATE) - private String updatedAt; - /** 操作人账号*/ - @TableField(fill = FieldFill.INSERT_UPDATE) - private String gmName; - - @ExcelImport(value = "昵称", required = true) - /** 昵称*/ - private String nickName; - /** 账号*/ - @ExcelImport(value = "账号", required = true, unique = true) - private String account; - /** 密码*/ - @ExcelImport(value = "密码", required = true) - private String pwd; - /** 公司名称 */ - @ExcelImport(value = "公司名称", required = true) - private String companyName; - /** 平台名称 */ - @ExcelImport(value = "平台名称", required = true) - private String platformName; - /** 国家 */ - @ExcelImport(value = "所属国家", required = true) - private String contntryShort; - /** VPN_IP地址*/ - @ExcelImport(value = "VPN_IP地址", required = true) - private String vpnIp; - /** 信用卡卡号 */ - @ExcelImport(value = "信用卡卡号") - private String cardNumber; - /** 地址1 */ - @ExcelImport(value = "地址1", required = true) - private String addressline1; - /** 国家 */ - @ExcelImport(value = "国家", required = true) - private String country; - /** 州 */ - @ExcelImport(value = "州", required = true) - private String state; - /** 电话 */ - @ExcelImport(value = "电话", required = true) - private String tel; - /** lastname */ - @ExcelImport(value = "lastname", required = true) - private String lastname; - /** 城市 */ - @ExcelImport(value = "城市", required = true) - private String city; - /** firstname */ - @ExcelImport(value = "firstname", required = true) - private String firstname; - /** 邮政编码 */ - @ExcelImport(value = "邮政编码", required = true) - private String postalcode; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtCard.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtCard.java deleted file mode 100644 index 777745f..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtCard.java +++ /dev/null @@ -1,80 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.math.BigDecimal; -import java.util.Date; - -/** - * 信用卡信息(CtCard)表实体类 - * - * @author rch - * @since 2022-07-07 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtCard extends Model { - - @TableId(value = "id", type = IdType.AUTO) - private Long id; - @TableField(fill = FieldFill.INSERT) - private String createdAt; - @TableField(fill = FieldFill.INSERT_UPDATE) - private String updatedAt; - /** 操作人账号*/ - @TableField(fill = FieldFill.INSERT_UPDATE) - private String gmName; - - /** 父ID */ - private Long parentId; - /** 卡号 */ - private String number; -// /** PIN码 */ -// private String pinNumber; - /** 持卡人姓氏 */ - private String holderSurname; - /** 持卡人名称 */ - private String holderName; - /** 有效期 */ - private String termOfValidity; - /** 余额 */ - private BigDecimal balance; - /** 累计消费 */ - private BigDecimal sumConsume; - /** 开卡日期 */ - private Date openDate; - /** 所属国家 */ - private String contntryShort; - /** 信用卡类型 1.Payoneer 2.万事达虚拟卡 3.Visa信用卡 */ - private Integer type; - /** 所属厂商:1.AmzKeys 2.Airwallex */ - private Integer cardDealer; - /** 身份证号 */ - private String idNumber; - /** 省份 */ - private String province; - /** 城市 */ - private String country; - /** 地址 */ - private String address; - /** 手机号 */ - private String phone; - /** 邮箱 */ - private String email; - /** 登陆账号 */ - private String account; - /** 密码 */ - private String pwd; - /** 状态:1.正常、2.异常、3.已删除 */ - private Integer status; - /** 备注 */ - private String remarks; -} \ No newline at end of file diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtCardExport.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtCardExport.java deleted file mode 100644 index 7ed9aae..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtCardExport.java +++ /dev/null @@ -1,40 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.utils.excel.ExcelExport; - -/** - * 信用卡信息(CtCard)表实体类 导出对象信息 - * - * @author rch - * @since 2022-07-07 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtCardExport extends Model { - /** 卡号 */ - @ExcelExport(value = "卡号") - private String number; -// /** PIN码 */ -// @ExcelExport(value = "PIN码") -// private String pinNumber; - /** 有效期 */ - @ExcelExport(value = "有效期") - private String termOfValidity; - /** 信用卡类型 1.Payoneer 2.万事达虚拟卡 3.Visa信用卡 */ - @ExcelExport(value = "信用卡类型", kv = "1-Payoneer;2-万事达虚拟卡;3-Visa信用卡") - private Integer type; - /** 所属厂商:1.AmzKeys 2.Airwallex */ - @ExcelExport(value = "所属厂商", kv = "1-AmzKeys;2-Airwallex") - private Integer cardDealer; - /** 状态:1.正常、2.异常、3.已删除 */ - @ExcelExport(value = "状态", kv = "1-正常;2-异常;3-已删除") - private Integer status; - /** 异常信息 */ - @ExcelExport(value = "异常信息") - private String error; -} \ No newline at end of file diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtCardExportTemple.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtCardExportTemple.java deleted file mode 100644 index 45d23c8..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtCardExportTemple.java +++ /dev/null @@ -1,46 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.utils.excel.ExcelExport; - -/** - * 信用卡信息(CtCard)表实体类 导出模版对象信息 - * - * @author rch - * @since 2022-07-07 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtCardExportTemple extends Model { - /** 卡号 */ - @ExcelExport(value = "卡号") - private String number; - /** PIN码 */ -// @ExcelExport(value = "PIN码") -// private String pinNumber; - /** 密码 */ - @ExcelExport(value = "密码") - private String pwd; - /** 有效期 */ - @ExcelExport(value = "有效期(文本:yyyy-MM-dd)") - private String termOfValidity; - /** 信用卡类型 1.Payoneer 2.万事达虚拟卡 3.Visa信用卡 */ - @ExcelExport(value = "信用卡类型", kv = "1-Payoneer;2-万事达虚拟卡;3-Visa信用卡") - private Integer type; - /** 所属厂商:1.AmzKeys 2.Airwallex */ - @ExcelExport(value = "所属厂商", kv = "1-AmzKeys;2-Airwallex") - private Integer cardDealer; - /** 状态:1.正常、2.异常、3.已删除 */ - @ExcelExport(value = "状态", kv = "1-正常;2-异常;3-已删除") - private Integer status; - /** 持卡人姓氏 */ - @ExcelExport(value = "持卡人姓氏") - private String holderSurname; - /** 持卡人名称 */ - @ExcelExport(value = "持卡人名称") - private String holderName; -} \ No newline at end of file diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtCardImport.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtCardImport.java deleted file mode 100644 index 16f2235..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtCardImport.java +++ /dev/null @@ -1,96 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.utils.excel.ExcelImport; - -import java.math.BigDecimal; -import java.util.Date; - -/** - * 信用卡信息(CtCard)表实体类 Import - * - * @author rch - * @since 2022-07-07 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtCardImport extends Model { - - /** Excel 行号 */ - private int rowNum; - - /** Excel 错误提示 */ - private String rowTips; - - @TableId(value = "id", type = IdType.AUTO) - private Long id; - @TableField(fill = FieldFill.INSERT) - private String createdAt; - @TableField(fill = FieldFill.INSERT_UPDATE) - private String updatedAt; - /** 操作人账号*/ - @TableField(fill = FieldFill.INSERT_UPDATE) - private String gmName; - - /** 父ID */ - private Long parentId; - /** 卡号 */ - @ExcelImport(value = "卡号", required = true, unique = true) - private String number; -// /** PIN码 */ -// @ExcelImport(value = "PIN码", required = true, unique = true) -// private String pinNumber; - /** 持卡人姓氏 */ - @ExcelImport(value = "持卡人姓氏") - private String holderSurname; - /** 持卡人名称 */ - @ExcelImport(value = "持卡人名称") - private String holderName; - /** 有效期 */ - @ExcelImport(value = "有效期(文本:yyyy-MM-dd)", required = true) - private String termOfValidity; - /** 余额 */ - private BigDecimal balance; - /** 累计消费 */ - private BigDecimal sumConsume; - /** 开卡日期 */ - private Date openDate; - /** 所属国家 */ - private String contntryShort; - /** 信用卡类型 1.Payoneer 2.万事达虚拟卡 3.Visa信用卡 */ - @ExcelImport(value = "信用卡类型", kv = "1-Payoneer;2-万事达虚拟卡;3-Visa信用卡", required = true) - private Integer type; - /** 所属厂商:1.AmzKeys 2.Airwallex */ - @ExcelImport(value = "所属厂商", kv = "1-AmzKeys;2-Airwallex", required = true) - private Integer cardDealer; - /** 身份证号 */ - private String idNumber; - /** 省份 */ - private String province; - /** 城市 */ - private String country; - /** 地址 */ - private String address; - /** 手机号 */ - private String phone; - /** 邮箱 */ - private String email; - /** 登陆账号 */ - private String account; - /** 密码 */ - @ExcelImport(value = "密码") - private String pwd; - /** 状态:1.正常、2.异常、3.已删除 */ - @ExcelImport(value = "状态", kv = "1-正常;2-异常;3-已删除", required = true) - private Integer status; - /** 备注 */ - private String remarks; -} \ No newline at end of file diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtCardInfo.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtCardInfo.java deleted file mode 100644 index 70d4443..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtCardInfo.java +++ /dev/null @@ -1,22 +0,0 @@ -package me.zhengjie.entity; - - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * Card(CtCard)表实体类 - * - * @author zhw - * @since 2022-07-14 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtCardInfo { - /** id */ - private Long id; - /** 信用卡卡号 */ - private String number; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtClickFarmSupplyMentYdParams.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtClickFarmSupplyMentYdParams.java deleted file mode 100644 index e700dee..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtClickFarmSupplyMentYdParams.java +++ /dev/null @@ -1,41 +0,0 @@ -package me.zhengjie.entity; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 刷单补录 - * - * @author rch - * @since 2022-08-16 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtClickFarmSupplyMentYdParams { - - private Long id; - /** 刷单类型 */ - private Integer paramsType; - /** 国家 */ - private String country; - /** 账号 */ - private String account; - /** 密码 */ - private String pwd; - /** vpn分享链接 */ - private String vpnShare; - - /** item */ - private String item; - /** 有效期 */ - private String termOfValidity; - /** 信用卡持卡人名称 */ - private String cardName; - /** 信用卡卡号 */ - private String cardNumber; - /** 信用卡密码 */ - private String cardPwd; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtClickFarmYdParams.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtClickFarmYdParams.java deleted file mode 100644 index 489e5b1..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtClickFarmYdParams.java +++ /dev/null @@ -1,59 +0,0 @@ -package me.zhengjie.entity; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotBlank; - -/** - * 刷单信息 影刀参数 - * - * @author rch - * @since 2022-08-16 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtClickFarmYdParams { - - private Long id; - /** 刷单类型 */ - private Integer paramsType; - /** 国家 */ - private String country; - /** 账号 */ - private String account; - /** 密码 */ - private String pwd; - /** 关键词 */ - private String keyWord; - /** 数量 */ - private Integer number; - /** 规格 */ - private String specification; - /** 颜色 */ - private String color; - /** item */ - private String item; - private String exchange; - /** 最小价格区间 */ - private String sectionMin; - /** 最大价格区间 */ - private String sectionMax; - /** vpn分享链接 */ - private String vpnShare; - /** 链接 */ - private String link; - /** 留言 */ - private String amessage; - /** 有效期 */ - private String termOfValidity; - /** 信用卡持卡人名称 */ - private String cardName; - /** 信用卡卡号 */ - private String cardNumber; - /** 信用卡密码 */ - private String cardPwd; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtClickFarming.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtClickFarming.java deleted file mode 100644 index e46c75a..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtClickFarming.java +++ /dev/null @@ -1,70 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 刷单Excel信息(CtClickFarming)表实体类 - * - * @author rch - * @since 2022-08-16 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtClickFarming extends Model { - - @TableId(value = "id", type = IdType.AUTO) - private Long id; - @TableField(fill = FieldFill.INSERT) - private String createdAt; - @TableField(fill = FieldFill.INSERT_UPDATE) - private String updatedAt; - /** 操作人账号*/ - @TableField(fill = FieldFill.INSERT_UPDATE) - private String gmName; - - /** 关联刷单订单ID */ - private Long ctClickOrderId; - /** 买家id */ - private Long buyerId; - /** 刷单类型 */ - private Integer paramsType; - /** 店铺名称 */ - private String shopName; - /** 关键词 */ - private String keyWord; - /** 标题 */ - private String title; - /** 链接 */ - private String link; - /** 数量 */ - private Integer number; - /** 规格 */ - private String specification; - /** 颜色 */ - private String color; - /** item */ - private String item; - /** 优惠劵 */ - private String exchange; - /** 最小价格区间 */ - private String sectionMin; - /** 最大价格区间 */ - private String sectionMax; - /** 执行结果 */ - private String response; - /** 支付订单ID */ - private String payOrderId; - /** 状态 1.待执行 2.执行中 3.执行成功 4.执行失败 */ - private Integer status; - /** 留言 */ - private String amessage; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtClickFarmingExport.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtClickFarmingExport.java deleted file mode 100644 index d26f1cf..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtClickFarmingExport.java +++ /dev/null @@ -1,59 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.utils.excel.ExcelExport; -import me.zhengjie.utils.excel.ExcelImport; - -/** - * 刷单信息信息(CtCard)表实体类 Import - * - * @author rch - * @since 2022-08-16 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtClickFarmingExport { - /** 国家 */ - @ExcelExport(value = "国家") - private String country; - /** 账号 */ - @ExcelExport(value = "账号") - private String account; - /** 密码 */ - @ExcelExport(value = "密码") - private String pwd; - /** 店铺名称 */ - @ExcelExport(value = "店铺名称") - private String shopName; - /** 关键词 */ - @ExcelExport(value = "关键词") - private String keyWord; - /** 标题 */ - @ExcelExport(value = "标题") - private String title; - /** 链接 */ - @ExcelExport(value = "链接") - private String link; - /** 数量 */ - @ExcelExport(value = "数量") - private Integer number; - /** 规格 */ - @ExcelExport(value = "规格") - private String specification; - /** 颜色 */ - @ExcelExport(value = "颜色") - private String color; - /** item */ - @ExcelExport(value = "item") - private String item; - /** vpn分享链接 */ - @ExcelExport(value = "vpn分享链接") - private String vpnShare; - /** 异常信息 */ - @ExcelExport(value = "异常信息") - private String error; -} \ No newline at end of file diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtClickFarmingExportTemp.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtClickFarmingExportTemp.java deleted file mode 100644 index 2f3d623..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtClickFarmingExportTemp.java +++ /dev/null @@ -1,53 +0,0 @@ -package me.zhengjie.entity; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.utils.excel.ExcelExport; - -/** - * 刷单信息信息(CtCard)表实体类 Import - * - * @author rch - * @since 2022-08-16 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtClickFarmingExportTemp { - /** 账号 */ - @ExcelExport(value = "账号") - private String account; - /** 商品属性类型:1.关键词 2.链接 */ - @ExcelExport(value = "商品属性类型", kv = "1-关键词;2-链接") - private Integer paramsType; - /** 店铺名称 */ - @ExcelExport(value = "店铺名称") - private String shopName; - /** 关键词 */ - @ExcelExport(value = "关键词") - private String keyWord; - /** 标题 */ - @ExcelExport(value = "标题") - private String title; - /** 链接 */ - @ExcelExport(value = "链接") - private String link; - /** 数量 */ - @ExcelExport(value = "数量") - private Integer number; - /** 规格 */ - @ExcelExport(value = "规格") - private String specification; - /** 颜色 */ - @ExcelExport(value = "颜色") - private String color; - @ExcelExport(value = "优惠卷") - private String exchange; - /** 商品item */ - @ExcelExport(value = "商品item") - private String item; - /** 留言 */ - @ExcelExport(value = "留言") - private String amessage; -} \ No newline at end of file diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtClickFarmingImport.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtClickFarmingImport.java deleted file mode 100644 index 2144533..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtClickFarmingImport.java +++ /dev/null @@ -1,64 +0,0 @@ -package me.zhengjie.entity; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.utils.excel.ExcelImport; - -/** - * 刷单信息信息(CtCard)表实体类 Import - * - * @author rch - * @since 2022-08-16 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtClickFarmingImport { - - /** Excel 行号 */ - private int rowNum; - - /** Excel 错误提示 */ - private String rowTips; - - /** 买家id */ - private Long buyerId; - - /** 账号 */ - @ExcelImport(value = "账号", required = true, unique = true) - private String account; - /** 商品属性类型:1.关键词 2.链接 */ - @ExcelImport(value = "商品属性类型", kv = "1-关键词; 2-链接") - private Integer paramsType; - /** 店铺名称 */ - @ExcelImport(value = "店铺名称") - private String shopName; - /** 关键词 */ - @ExcelImport(value = "关键词") - private String keyWord; - /** 标题 */ - @ExcelImport(value = "标题") - private String title; - /** 链接 */ - @ExcelImport(value = "链接") - private String link; - /** 数量 */ - @ExcelImport(value = "数量") - private Integer number; - /** 规格 */ - @ExcelImport(value = "规格") - private String specification; - /** 颜色 */ - @ExcelImport(value = "颜色") - private String color; - /** item */ - @ExcelImport(value = "商品item") - private String item; - /** 优惠劵 */ - @ExcelImport(value = "优惠卷") - private String exchange; - /** 留言 */ - @ExcelImport(value = "留言", required = true) - private String amessage; -} \ No newline at end of file diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtClickFarmingOrderInfo.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtClickFarmingOrderInfo.java deleted file mode 100644 index 280ca9c..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtClickFarmingOrderInfo.java +++ /dev/null @@ -1,37 +0,0 @@ -package me.zhengjie.entity; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 刷单订单信息详情(刷单信息+订单信息) - * - * @author rch - * @since 2022-08-16 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtClickFarmingOrderInfo { - - private Long id; - /** 国家 */ - private String country; - /** 账号 */ - private String account; - /** 密码 */ - private String pwd; - /** vpn分享链接 */ - private String vpnShare; - - /** 订单id */ - private String orderId; - /** 评论 */ - private String comment; - /** 状态 1.待执行 2.执行中 3.执行成功 4.执行失败 */ - private Integer status; - /** 图片地址 */ - private String paths; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtClickOrder.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtClickOrder.java deleted file mode 100644 index 9e1ed52..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtClickOrder.java +++ /dev/null @@ -1,55 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 刷单-订单信息(CtClickOrder)表实体类 - * - * @author rch - * @since 2022-09-14 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtClickOrder extends Model { - @TableId(value = "id", type = IdType.AUTO) - private Long id; - @TableField(fill = FieldFill.INSERT) - private String createdAt; - @TableField(fill = FieldFill.INSERT_UPDATE) - private String updatedAt; - /** 操作人账号*/ - @TableField(fill = FieldFill.INSERT_UPDATE) - private String gmName; - /** 公司ID */ - private Long companyId; - /** 类型 1.导入 2.刷单*/ - private Integer type; - /** 总金额 */ - private String amount; - /** 状态描述 */ - private String paymentResults; - /** 店铺名称 */ - private String shop; - /** 购买数量 */ - private String pricesNumber; - /** 订单id */ - private String orderId; - /** 商品名称 */ - private String shopName; - /** 时间 */ - private String orderDate; - /** 评论 */ - private String comment; - /** 图片地址 */ - private String paths; - /** 状态 1.待执行 2.执行中 3.执行成功 4.执行失败 */ - private Integer status; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtClickOrderExport.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtClickOrderExport.java deleted file mode 100644 index 3e2935e..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtClickOrderExport.java +++ /dev/null @@ -1,37 +0,0 @@ -package me.zhengjie.entity; - - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.utils.excel.ExcelExport; - -/** - * 刷单订单实体类 导出模版对象信息 - * - * @author rch - * @since 2022-09-27 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtClickOrderExport { - - /** 公司名称 */ - @ExcelExport(value = "公司名称") - private String companyName; - /** 总金额 */ - @ExcelExport(value = "总金额") - private String amount; - /** 店铺名称 */ - @ExcelExport(value = "店铺名称") - private String shop; - /** 订单id */ - @ExcelExport(value = "订单id") - private String orderId; - /** 评论 */ - @ExcelExport(value = "评论") - private String comment; - @ExcelExport(value = "异常信息") - private String error; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtClickOrderExportTemple.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtClickOrderExportTemple.java deleted file mode 100644 index 49e25f7..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtClickOrderExportTemple.java +++ /dev/null @@ -1,39 +0,0 @@ -package me.zhengjie.entity; - - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.utils.excel.ExcelExport; -import me.zhengjie.utils.excel.ExcelImport; - -/** - * 刷单订单实体类 导出模版对象信息 - * - * @author rch - * @since 2022-09-27 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtClickOrderExportTemple { - - /** 平台名称 */ - @ExcelExport(value = "平台名称") - private Integer platformId; - /** 公司名称 */ - @ExcelExport(value = "公司名称") - private Long companyId; - /** 总金额 */ - @ExcelExport(value = "总金额") - private String amount; - /** 店铺名称 */ - @ExcelExport(value = "店铺名称") - private String shop; - /** 订单id */ - @ExcelExport(value = "订单id") - private String orderId; - /** 评论 */ - @ExcelExport(value = "评论") - private String comment; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtClickOrderImport.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtClickOrderImport.java deleted file mode 100644 index a4695dc..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtClickOrderImport.java +++ /dev/null @@ -1,40 +0,0 @@ -package me.zhengjie.entity; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.utils.excel.ExcelExport; -import me.zhengjie.utils.excel.ExcelImport; - -/** - * Vpn信息(CtVpn)表实体类 Import - * - * @author rch - * @since 2022-09-27 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtClickOrderImport { - private int rowNum; - - private String rowTips; - - /** 公司ID */ - private Long companyId; - /** 公司名称 */ - @ExcelImport(value = "公司名称", required = true) - private String companyName; - /** 总金额 */ - @ExcelImport(value = "总金额", required = true) - private String amount; - /** 店铺名称 */ - @ExcelImport(value = "店铺名称", required = true) - private String shop; - /** 订单id */ - @ExcelImport(value = "订单id", required = true) - private String orderId; - /** 评论 */ - @ExcelImport(value = "评论") - private String comment; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtClickOrderYdParams.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtClickOrderYdParams.java deleted file mode 100644 index 9a1b5e6..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtClickOrderYdParams.java +++ /dev/null @@ -1,33 +0,0 @@ -package me.zhengjie.entity; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 刷单订单影刀参数 - * - * @author rch - * @since 2022-10-21 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtClickOrderYdParams { - private Long id; - /** 国家 */ - private String country; - /** 账号 */ - private String account; - /** 密码 */ - private String pwd; - /** vpn分享链接 */ - private String vpnShare; - /** 订单id */ - private String orderId; - /** 评论 */ - private String comment; - /** 图片 */ - private String paths; - -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtCompany.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtCompany.java deleted file mode 100644 index eff48bf..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtCompany.java +++ /dev/null @@ -1,43 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 公司信息(CtCompany)表实体类 - * - * @author rch - * @since 2022-06-23 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtCompany extends Model { - - @TableId(value = "id", type = IdType.AUTO) - private Long id; - @TableField(fill = FieldFill.INSERT) - private String createdAt; - @TableField(fill = FieldFill.INSERT_UPDATE) - private String updatedAt; - /** 操作人账号*/ - @TableField(fill = FieldFill.INSERT_UPDATE) - private String gmName; - /** 名称 */ - private String name; - /** 地址 */ - private String address; - /** 电话 */ - private String phone; - /** 商户码(公司调用api公司唯一标识) */ - private String number; - /** 商户token(公司调用api公司token身份标识) */ - private String token; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtCompanyInfo.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtCompanyInfo.java deleted file mode 100644 index de0f007..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtCompanyInfo.java +++ /dev/null @@ -1,23 +0,0 @@ -package me.zhengjie.entity; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 公司信息(CtCompany)表实体类 - * - * @author zhw - * @since 2022-07-14 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtCompanyInfo { - - /** id */ - private Long id; - /** 名称 */ - private String name; - -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtDhPay.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtDhPay.java deleted file mode 100644 index 222896e..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtDhPay.java +++ /dev/null @@ -1,44 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.Date; - -/** - * 平台信息(CtDyPay)表实体类 - * - * @author rch - * @since 2022-07-28 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtDhPay extends Model { - - @TableId(value = "id", type = IdType.AUTO) - private Long id; - @TableField(fill = FieldFill.INSERT) - private String createdAt; - @TableField(fill = FieldFill.INSERT_UPDATE) - private String updatedAt; - /** 操作人账号*/ - @TableField(fill = FieldFill.INSERT_UPDATE) - private String gmName; - - /** 买家名称 */ - private String buyerName; - /** 支付订单ID(敦煌的) */ - private String orderId; - /** 请求响应详情 */ - private String response; - /** 状态 0.待处理 1.支付成功 2.支付失败 */ - private Integer status; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtDhPayExport.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtDhPayExport.java deleted file mode 100644 index 3586977..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtDhPayExport.java +++ /dev/null @@ -1,29 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.utils.excel.ExcelExport; - -/** - * 敦煌支付信息(CtDhPay)表实体类 Export - * - * @author rch - * @since 2022-07-28 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtDhPayExport extends Model { - /** 买家名称 */ - @ExcelExport(value = "买家账号") - private String buyerName; - /** 支付订单ID(敦煌的) */ - @ExcelExport(value = "支付订单") - private String orderId; - - /** 异常信息 */ - @ExcelExport(value = "异常信息") - private String error; -} \ No newline at end of file diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtDhPayExportTemple.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtDhPayExportTemple.java deleted file mode 100644 index 4f5614e..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtDhPayExportTemple.java +++ /dev/null @@ -1,25 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.utils.excel.ExcelExport; - -/** - * 敦煌支付信息(CtDhPay)表实体类 导出模版对象信息 - * - * @author rch - * @since 2022-07-28 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtDhPayExportTemple extends Model { - /** 买家名称 */ - @ExcelExport(value = "买家账号") - private String buyerName; - /** 支付订单ID(敦煌的) */ - @ExcelExport(value = "支付订单") - private String orderId; -} \ No newline at end of file diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtDhPayImport.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtDhPayImport.java deleted file mode 100644 index 863019c..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtDhPayImport.java +++ /dev/null @@ -1,40 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.utils.excel.ExcelImport; - -import java.math.BigDecimal; -import java.util.Date; - -/** - * 敦煌支付信息(CtDhPay)表实体类 Import - * - * @author rch - * @since 2022-07-28 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtDhPayImport{ - - /** Excel 行号 */ - private int rowNum; - - /** Excel 错误提示 */ - private String rowTips; - - /** 买家名称 */ - @ExcelImport(value = "买家账号", required = true, unique = true) - private String buyerName; - - /** 支付订单ID(敦煌的) */ - @ExcelImport(value = "支付订单", required = true, unique = true) - private String orderId; -} \ No newline at end of file diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtExcel.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtExcel.java deleted file mode 100644 index 4c9bef7..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtExcel.java +++ /dev/null @@ -1,41 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * Excel 导入信息(CtExcel)表实体类 - * - * @author rch - * @since 2022-06-23 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtExcel extends Model { - - @TableId(value = "id", type = IdType.AUTO) - private Long id; - @TableField(fill = FieldFill.INSERT) - private String createdAt; - @TableField(fill = FieldFill.INSERT_UPDATE) - private String updatedAt; - /** 操作人账号*/ - @TableField(fill = FieldFill.INSERT_UPDATE) - private String gmName; - - /** 备注 */ - private String remarks; - /** excel路径 */ - - private String path; - private String errorPath; - /** 状态 1.待导入 2.导入成功 3.导入失败 */ - private Integer status; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtExcelExportInfo.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtExcelExportInfo.java deleted file mode 100644 index f9954c3..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtExcelExportInfo.java +++ /dev/null @@ -1,40 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.utils.excel.ExcelExport; - -/** - * Excel 导出信息(CtExcelImportInfo)表实体类 - * - * @author rch - * @since 2022-07-18 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtExcelExportInfo extends Model { - - /** 公司主键 */ - @ExcelExport("公司主键") - private Long companyId; - - /** 鉴权枚举 */ - @ExcelExport("鉴权枚举") - private Long tokenEnum; - - /** 订单来源 */ - @ExcelExport("订单来源") - private String fromDetailInfo; - - /** 产品信息-JSON */ - @ExcelExport("产品信息") - private String cartList; - - /** 异常信息 */ - @ExcelExport(value = "异常信息") - private String error; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtExcelExportTemple.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtExcelExportTemple.java deleted file mode 100644 index cd9499b..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtExcelExportTemple.java +++ /dev/null @@ -1,33 +0,0 @@ -package me.zhengjie.entity; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.utils.excel.ExcelExport; - -/** - * EXCEL(CtExcel)表实体类 导出excel模板 - * @author zhw - * @since 2022-07-18 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtExcelExportTemple { - - /** 公司主键 */ - @ExcelExport("公司主键") - private Long companyId; - - /** 鉴权枚举 */ - @ExcelExport("鉴权枚举") - private Long tokenEnum; - - /** 订单来源 */ - @ExcelExport("订单来源") - private String fromDetailInfo; - - /** 产品信息-JSON */ - @ExcelExport("产品信息") - private String cartList; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtExcelImportInfo.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtExcelImportInfo.java deleted file mode 100644 index 153b8ca..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtExcelImportInfo.java +++ /dev/null @@ -1,59 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.utils.excel.ExcelImport; - -/** - * Excel导入信息(CtExcelImportInfo)表实体类 - * - * @author rch - * @since 2022-06-23 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtExcelImportInfo extends Model { - - @TableId(value = "id", type = IdType.AUTO) - private Long id; - @TableField(fill = FieldFill.INSERT) - private String createdAt; - @TableField(fill = FieldFill.INSERT_UPDATE) - private String updatedAt; - /** 操作人账号*/ - @TableField(fill = FieldFill.INSERT_UPDATE) - private String gmName; - - /** 公司主键 */ - @ExcelImport("公司主键") - private Long companyId; - - /** 鉴权枚举 */ - @ExcelImport("鉴权枚举") - private Long tokenEnum; - - /** 订单来源 */ - @ExcelImport("订单来源") - private String fromDetailInfo; - - /** 产品信息-JSON */ - @ExcelImport("产品信息") - private String cartList; - - /** 订单收货地址-JSON */ - private String contactInfo; - - /** 我们平台订单编号 */ - private String orderNo; - - /** 状态 1.待处理 2.处理成功 3.处理失败 */ - private Integer status; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtOrder.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtOrder.java deleted file mode 100644 index 8117c8b..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtOrder.java +++ /dev/null @@ -1,55 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * (CtOrder)表实体类 - * - * @author rch - * @since 2022-06-30 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtOrder extends Model { - - @TableId(value = "id", type = IdType.AUTO) - private Long id; - @TableField(fill = FieldFill.INSERT) - private String createdAt; - @TableField(fill = FieldFill.INSERT_UPDATE) - private String updatedAt; - - /** 公司Id */ - private Long companyId; - /** ExcelId 信息 */ - private Long excelInfoId; - /** 买家ID */ - private Long buyerId; - /** 买家buy_access_token */ - private String buyAccessToken; - /** 我们平台订单编号 */ - private String ctOrderNo; - /** 订单号,下单成功响应的订单号(冗余字段 下单成功响应订单信息里有) */ - private Long orderNo; - /** 下单成功响应的产品id( a,b,c 格式) (响应字段很多,先少些几个) */ - private Long responseProductId; - /** 下单成功响应的订单地址id(响应字段很多,先少些几个) */ - private Long responseOrderAddressId; - /** 下单成功响应的订单信息 (响应字段很多,先少些几个) */ - private Long responseOrderId; - /** 响应码信息 */ - private String orderResponseStatus; - /** 响应码信息 */ - private String payResponseStatus; - /** 状态 1.待支付(下单成功) 2.支付成功 3.支付失败*/ - private Integer status; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtParamContactInfo.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtParamContactInfo.java deleted file mode 100644 index 2feb27c..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtParamContactInfo.java +++ /dev/null @@ -1,39 +0,0 @@ -package me.zhengjie.entity; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 下单API请求参数订单收货地址信息 - * - * @author rch - * @since 2022-06-23 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtParamContactInfo { - /** 必须 所在国家; 示例值:US 所在国家 */ - private String country; - /** 必须 收货人lastname ;示例值:zhao 收货人firstname */ - private String firstname; - /** 必须 收货人联系电话,固定电话或者移动电话 ;示例值:1311111111 收货人联系电话,固定电话或者移动电话 */ - private String tel; - /** 否 收货人地址1 ;示例值:chengfulu road, hawio 收货人地址2 */ - private String addressline2; - /** 必须 所在州 ;示例值:California 所在州 */ - private String state; - /** 必须 所在城市; 示例值:Chicago 所在城市 */ - private String city; - /** 必须 收货人地址1 ;示例值:chengfulu road, hawio 收货人地址1 */ - private String addressline1; - /** 必须 地址邮编 ;示例值:12345 地址邮编 */ - private String postalcode; - /** 必须 收货人lastname ;示例值:yiyi 收货人lastname */ - private String lastname; - /** 否 税号:BR,AR,EC,AO,LB,TR,KR必填 税号 */ - private String vatNumber; - /** 否 Email地址 ;示例值:zhaoyiyi@163.com Email地址 */ - private String email; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtParamProduct.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtParamProduct.java deleted file mode 100644 index 0a8a937..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtParamProduct.java +++ /dev/null @@ -1,29 +0,0 @@ -package me.zhengjie.entity; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 下单Api请求产品信息参数实体类 - * - * @author rch - * @since 2022-06-23 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtParamProduct { - /** 必须 产品购买数量 示例值:2 产品数量 */ - private Integer quantity; - /** 否 可以从获取商品运费详情API获取expressType字段(分销API>物流API>dh.dropshipping.ship.get$1.0);示例值:ePacket 物流方式 */ - private String shipType; - /** 否 可根据国家字典查询国家详情(dh.base.countrys.get$1.0); 示例值:CN;默认值:CN 备货国家ID */ - private String stockin; - /** 否 站点 站点 */ - private String siteId; - /** 必须 产品itemcode ;示例值:634706114 产品编码 */ - private Long itemcode; - /** 必须 产品skuMd5,可以从商品详情API获取(分析API>商品API>dh.dropshipping.item.get$1.0) ;示例值:562e86410bd37a7bb4170cfe6e03203f 产品skuMd5 */ - private String skuMd5; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtPlatform.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtPlatform.java deleted file mode 100644 index 81ba872..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtPlatform.java +++ /dev/null @@ -1,40 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 平台信息(CtPlatform)表实体类 - * - * @author rch - * @since 2022-06-23 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtPlatform extends Model { - - @TableId(value = "id", type = IdType.AUTO) - private Long id; - @TableField(fill = FieldFill.INSERT) - private String createdAt; - @TableField(fill = FieldFill.INSERT_UPDATE) - private String updatedAt; - /** 操作人账号*/ - @TableField(fill = FieldFill.INSERT_UPDATE) - private String gmName; - - /** 名称 */ - private String name; - /** 地址 */ - private String address; - /** 电话 */ - private String phone; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtRebot.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtRebot.java deleted file mode 100644 index 9c6371d..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtRebot.java +++ /dev/null @@ -1,41 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.Date; - -/** - * 影刀设备-机器人信息(CtRebot)表实体类 - * - * @author rch - * @since 2022-07-23 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtRebot extends Model { - - @TableId(value = "id", type = IdType.AUTO) - private Long id; - @TableField(fill = FieldFill.INSERT) - private String createdAt; - @TableField(fill = FieldFill.INSERT_UPDATE) - private String updatedAt; - /** 操作人账号*/ - @TableField(fill = FieldFill.INSERT_UPDATE) - private String gmName; - - /** 机器人账号 */ - private String accountName; - /** 机器人Uuid信息 */ - private String robotClientUuid; - /** 状态 0.未占用 1.占用 */ - private Integer status; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtRebotExport.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtRebotExport.java deleted file mode 100644 index c486f3b..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtRebotExport.java +++ /dev/null @@ -1,31 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.utils.excel.ExcelExport; -import me.zhengjie.utils.excel.ExcelImport; - -/** - * 影刀机器人信息(ct_rebot) 导出 - * - * @Author zhw - * @Date 2022-07-25 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtRebotExport { - /** 机器人账号 */ - @ExcelExport(value = "机器人账号") - private String accountName; - /** 机器人Uuid信息 */ - @ExcelExport(value = "Uuid信息") - private String robotClientUuid; - @ExcelExport(value = "异常信息") - private String error; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtRebotExportTemple.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtRebotExportTemple.java deleted file mode 100644 index d7c80f7..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtRebotExportTemple.java +++ /dev/null @@ -1,24 +0,0 @@ -package me.zhengjie.entity; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.utils.excel.ExcelExport; - -/** - * 机器人模板EXCEL导出(ct_rebot) - * - * @Author zhw - * @Date 2022-07-23 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtRebotExportTemple { - /** 机器人账号 */ - @ExcelExport(value = "机器人账号") - private String accountName; - /** 机器人Uuid信息 */ - @ExcelExport(value = "Uuid信息") - private String robotClientUuid; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtRebotImport.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtRebotImport.java deleted file mode 100644 index 54fe190..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtRebotImport.java +++ /dev/null @@ -1,43 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.utils.excel.ExcelImport; - -/** - * 影刀机器人信息(ct_rebot) import - * - * @Author zhw - * @Date 2022-07-25 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtRebotImport { - - private int romNum; - private String rowTips; - - @TableId(value = "id", type = IdType.AUTO) - private Long id; - @TableField(fill = FieldFill.INSERT) - private String createdAt; - @TableField(fill = FieldFill.INSERT_UPDATE) - private String updatedAt; - /** 操作人账号*/ - @TableField(fill = FieldFill.INSERT_UPDATE) - private String gmName; - - /** 机器人账号 */ - @ExcelImport(value = "机器人账号", required = true) - private String accountName; - /** 机器人Uuid信息 */ - @ExcelImport(value = "Uuid信息", required = true) - private String robotClientUuid; - -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtResponseOrder.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtResponseOrder.java deleted file mode 100644 index 9d2e35f..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtResponseOrder.java +++ /dev/null @@ -1,67 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.Date; - -/** - * 下单成功响应订单商品信息(CtResponseOrder)表实体类 - * - * @author rch - * @since 2022-06-30 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtResponseOrder extends Model { - - @TableId(value = "id", type = IdType.AUTO) - private Long id; - @TableField(fill = FieldFill.INSERT) - private String createdAt; - @TableField(fill = FieldFill.INSERT_UPDATE) - private String updatedAt; - /** 操作人账号*/ - @TableField(fill = FieldFill.INSERT_UPDATE) - private String gmName; - - /** 运费 */ - private Double shipCost; - /** 产品总价 */ - private Double totalPriceOfProduct; - /** 备货期 */ - private Double leadingTime; - /** 订单总价 */ - private Double orderTotal; - /** 卖家Id */ - private String supplierId; - /** 卖家店铺coupon */ - private Double couponOfSeller; - /** 运输方式 */ - private String shipType; - /** 订单优惠 */ - private Double orderSave; - /** 税费手续费 */ - private Double taxCharge; - /** 买家Id */ - private String buyerId; - /** 税费 */ - private Double tax; - /** 促销折扣 */ - private Double promoDiscount; - /** 订单号--这个要特殊处理这个是对应响应的id字段 */ - private Long orderId; - /** DHcoupon */ - private Double couponDiscount; - /** 下单站点 */ - private String siteId; - /** 创建时间 */ - private Date createTime; -} \ No newline at end of file diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtResponseOrderAddress.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtResponseOrderAddress.java deleted file mode 100644 index cfecf60..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtResponseOrderAddress.java +++ /dev/null @@ -1,53 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 下注成功订单响应收货地址信息(CtResponseOrderAddress)表实体类 - * - * @author rch - * @since 2022-06-30 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtResponseOrderAddress extends Model { - - @TableId(value = "id", type = IdType.AUTO) - private Long id; - @TableField(fill = FieldFill.INSERT) - private String createdAt; - @TableField(fill = FieldFill.INSERT_UPDATE) - private String updatedAt; - /** 操作人账号*/ - @TableField(fill = FieldFill.INSERT_UPDATE) - private String gmName; - - /** 地址1 */ - private String addressline1; - /** 国家 */ - private String country; - /** 州 */ - private String state; - /** 电话 */ - private String tel; - /** lastname */ - private String lastname; - /** 税号 */ - private String vatNumber; - /** 城市 */ - private String city; - /** 地址2 */ - private String addressline2; - /** firstname */ - private String firstname; - /** 邮政编码 */ - private String postalcode; -} \ No newline at end of file diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtResponseOrderProduct.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtResponseOrderProduct.java deleted file mode 100644 index 9682b76..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtResponseOrderProduct.java +++ /dev/null @@ -1,96 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.math.BigDecimal; -import java.util.Date; - -/** - * 下单订单响应产品信息(CtResponseOrderProduct)表实体类 - * - * @author rch - * @since 2022-06-30 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtResponseOrderProduct extends Model { - - @TableId(value = "id", type = IdType.AUTO) - private Long id; - @TableField(fill = FieldFill.INSERT) - private String createdAt; - @TableField(fill = FieldFill.INSERT_UPDATE) - private String updatedAt; - /** 操作人账号*/ - @TableField(fill = FieldFill.INSERT_UPDATE) - private String gmName; - - /** 秒杀类型 */ - private String flashDeals; - /** 卖家设置价格 */ - private Double prodPriceOrg; - /** 产品skuId */ - private String skuId; - /** 购买数量 */ - private Integer cateDispId; - /** 商品总金额 */ - private Double amount; - /** 发布类目id */ - private String catePubId; - /** 促销折扣 */ - private Double promDis; - /** 产品单位名称 */ - private String measureName; - /** 短描 */ - private String shortDescription; - /** 卖家承诺运达天数 */ - private Integer promiseDays; - /** 备货国家 */ - private String stockin; - /** 产品图片(小图) */ - private String thumbnailImage; - /** 是否为样品 */ - private String isSample; - /** 最终运费 */ - private Double shipCost; - /** 卖家Id */ - private String supplierId; - /** 跨店满减金额 */ - private BigDecimal crossReduceAmount; - /** 产品itemcode */ - private Integer itemcode; - /** buyer选择的运输方式 */ - private String shipType; - /** 销售价格 */ - private Double originPrice; - /** 产品长描地址 */ - private String htmlUrl; - /** 产品图片(大图) */ - private String imageUrl; - /** 最终价格 */ - private Double price; - /** 产品URL */ - private String productUrl; - /** 备注 */ - private String remark; - /** lots */ - private Integer lots; - /** 产品名称 */ - private String productName; - /** 产品Id */ - private String productId; - /** 产品skumd5 */ - private String skuMd5; - /** 创建时间 */ - private Date createTime; - /** 产品单位Id */ - private String measureId; -} \ No newline at end of file diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtSettingSite.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtSettingSite.java deleted file mode 100644 index a2209ea..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtSettingSite.java +++ /dev/null @@ -1,43 +0,0 @@ -package me.zhengjie.entity; - - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 站点配置(CtSettingSite)表实体类 - * - * @author rch - * @since 2022-06-23 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtSettingSite extends Model { - - @TableId(value = "id", type = IdType.AUTO) - private Long id; - @TableField(fill = FieldFill.INSERT) - private String createdAt; - @TableField(fill = FieldFill.INSERT_UPDATE) - private String updatedAt; - /** 操作人账号*/ - @TableField(fill = FieldFill.INSERT_UPDATE) - private String gmName; - - /** 设置KEY */ - private String settingKey; - /** 设置value */ - private String settingValue; - /** 中文描述 */ - private String content; - /** 单位 */ - private String unit; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtVpn.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtVpn.java deleted file mode 100644 index 7e613ab..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtVpn.java +++ /dev/null @@ -1,55 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * VPN信息表(CtVpn)表实体类 - * - * @author rch - * @since 2022-07-07 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtVpn extends Model { - - @TableId(value = "id", type = IdType.AUTO) - private Long id; - @TableField(fill = FieldFill.INSERT) - private String createdAt; - @TableField(fill = FieldFill.INSERT_UPDATE) - private String updatedAt; - /** 操作人账号*/ - @TableField(fill = FieldFill.INSERT_UPDATE) - private String gmName; - - /** 所属国家简称 */ - private String contntryShort; - /** IP地址 */ - private String ipAddress; - /** 父ip地址 */ - private String parentIpAddress; - /** 端口 */ - private Integer port; - /** 名称 */ - private String name; - /** 密码 */ - private String pwd; - /** VPS类型 1.传统 */ - private Integer vpsType; - /** 经销商 1.V2 */ - private Integer dealer; - /** mac地址 */ - private String mac; - /** 链接 */ - private String link; - /** 经销商 1.可用 2.禁用 */ - private Integer status; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtVpnExport.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtVpnExport.java deleted file mode 100644 index cff274d..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtVpnExport.java +++ /dev/null @@ -1,45 +0,0 @@ -package me.zhengjie.entity; - - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.utils.excel.ExcelExport; - -/** - * Vpn信息(CtCard)表实体类 export - * - * @author zhw - * @since 2022-07-13 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtVpnExport { - - /** 所属国家简称 */ - @ExcelExport(value = "所属国家简称") - private String contntryShort; - /** IP地址 */ - @ExcelExport(value = "IP地址") - private String ipAddress; - @ExcelExport(value = "端口") - private Integer port; - /** 名称 */ - @ExcelExport(value = "名称") - private String name; - /** 密码 */ - @ExcelExport(value = "密码") - private String pwd; - /** VPS类型 1.传统 */ - @ExcelExport(value = "VPS类型", kv = "1-传统") - private Integer vpsType; - /** 经销商 1.V2 */ - @ExcelExport(value = "经销商", kv = "1-V2") - private Integer dealer; - @ExcelExport(value = "链接") - private String link; - @ExcelExport(value = "异常信息") - private String error; - -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtVpnExportTemple.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtVpnExportTemple.java deleted file mode 100644 index 1e3bca1..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtVpnExportTemple.java +++ /dev/null @@ -1,43 +0,0 @@ -package me.zhengjie.entity; - - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.utils.excel.ExcelExport; - -/** - * Vpn信息(CtVpn)表实体类 导出模版对象信息 - * - * @author zhw - * @since 2022-07-13 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtVpnExportTemple { - - /** 所属国家简称 */ - @ExcelExport(value = "所属国家简称", example = "中国") - private String contntryShort; - /** IP地址 */ - @ExcelExport(value = "IP地址", example = "192.0.0.1") - private String ipAddress; - @ExcelExport(value = "端口", example = "8088") - private Integer port; - /** 名称 */ - @ExcelExport(value = "名称", example = "示例") - private String name; - /** 密码 */ - @ExcelExport(value = "密码", example = "123123") - private String pwd; - /** VPS类型 1.传统 */ - @ExcelExport(value = "VPS类型", kv = "1-传统", example = "传统") - private Integer vpsType; - @ExcelExport(value = "链接", example = "vmess://ew0KICAidiI6ICIyIiwNCiAgInBzIjogIjEwNC4yMjEuMTk5LjgyIiwNCiAgImFkZCI6ICJ1cy1lczM0LmZvYmhlbHAuY29tIiwNCiAgInBvcnQiOiAiMzAwNDMiLA0KICAiaWQiOiAiYzA4NDk5ODQtZWNjNC01MzY3LTlmOTctYTI2ODljNTQ5N2QyIiwNCiAgImFpZCI6ICI2NCIsDQogICJzY3kiOiAiYXV0byIsDQogICJuZXQiOiAidGNwIiwNCiAgInR5cGUiOiAibm9uZSIsDQogICJob3N0IjogIiIsDQogICJwYXRoIjogIiIsDQogICJ0bHMiOiAiIiwNCiAgInNuaSI6ICIiDQp9") - private String link; - /** 经销商 1.V2 */ - @ExcelExport(value = "经销商", kv = "1-V2", example = "V2") - private Integer dealer; - -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtVpnImport.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtVpnImport.java deleted file mode 100644 index e1cb352..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtVpnImport.java +++ /dev/null @@ -1,66 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.utils.excel.ExcelImport; - -/** - * Vpn信息(CtVpn)表实体类 Import - * - * @author zhw - * @since 2022-07-13 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtVpnImport { - private int rowNum; - - private String rowTips; - - @TableId(value = "id", type = IdType.AUTO) - private Long id; - @TableField(fill = FieldFill.INSERT) - private String createdAt; - @TableField(fill = FieldFill.INSERT_UPDATE) - private String updatedAt; - /** 操作人账号*/ - @TableField(fill = FieldFill.INSERT_UPDATE) - private String gmName; - - /** 所属国家简称 */ - @ExcelImport(value = "所属国家简称", required = true) - private String contntryShort; - /** IP地址 */ - @ExcelImport(value = "IP地址", required = true, unique = true) - private String ipAddress; - /** 父ip地址 */ - private String parentIpAddress; - /** 端口 */ - @ExcelImport(value = "端口", required = true) - private Integer port; - /** 名称 */ - @ExcelImport(value = "名称", required = true) - private String name; - /** 密码 */ - @ExcelImport(value = "密码", required = true) - private String pwd; - /** VPS类型 1.传统 */ - @ExcelImport(value = "VPS类型", kv = "1-传统", required = true) - private Integer vpsType; - /** 经销商 1.V2 */ - @ExcelImport(value = "经销商", kv = "1-V2", required = true) - private Integer dealer; - /** mac地址 */ - private String mac; - /** 链接 */ - @ExcelImport(value = "链接", required = true, maxLength = 2000) - private String link; - /** 状态 1.可用 2.禁用 */ - private Integer status; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/CtVpnInfo.java b/wjcy-common/src/main/java/me/zhengjie/entity/CtVpnInfo.java deleted file mode 100644 index 2fd174b..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/CtVpnInfo.java +++ /dev/null @@ -1,23 +0,0 @@ -package me.zhengjie.entity; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - - -/** - * Vpn(CtVpn)表实体类 - * - * @author zhw - * @since 2022-07-14 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtVpnInfo { - - /** id */ - private Long id; - /** Ip地址 */ - private String ipAddress; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/DhAddCar.java b/wjcy-common/src/main/java/me/zhengjie/entity/DhAddCar.java deleted file mode 100644 index a0e2c3c..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/DhAddCar.java +++ /dev/null @@ -1,48 +0,0 @@ -package me.zhengjie.entity; - -import java.util.Date; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.io.Serializable; - -/** - * 敦煌加入购物车(DhAddCar)表实体类 - * - * @author rch - * @since 2022-11-17 09:11:54 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class DhAddCar extends Model { - - @TableId(value = "id", type = IdType.AUTO) - private Long id; - @TableField(fill = FieldFill.INSERT) - private String createdAt; - @TableField(fill = FieldFill.INSERT_UPDATE) - private String updatedAt; - /** 操作人账号*/ - @TableField(fill = FieldFill.INSERT_UPDATE) - private String gmName; - - /** 买家ID */ - private Long buyerId; - /** 商品属性类型:1.关键词 2.链接 */ - private Integer paramsType; - /** 加购物车商品ids */ - private String carGoodIds; - /** 执行结果 */ - private String response; - /** 状态 1.待执行 2.执行中 3.加购成功 4.加购失败 5.下单成功 6.支付成功 7.抓单成功 8.抓单失败 */ - private Integer status; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/DhAddCarOrder.java b/wjcy-common/src/main/java/me/zhengjie/entity/DhAddCarOrder.java deleted file mode 100644 index 6c656d4..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/DhAddCarOrder.java +++ /dev/null @@ -1,55 +0,0 @@ -package me.zhengjie.entity; - -import java.util.Date; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.io.Serializable; - -/** - * 敦煌-加购物车-订单(DhAddCarOrder)表实体类 - * - * @author rch - * @since 2022-11-17 09:11:58 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class DhAddCarOrder extends Model { - @TableId(value = "id", type = IdType.AUTO) - private Long id; - @TableField(fill = FieldFill.INSERT) - private String createdAt; - @TableField(fill = FieldFill.INSERT_UPDATE) - private String updatedAt; - /** 操作人账号*/ - @TableField(fill = FieldFill.INSERT_UPDATE) - private String gmName; - - /** 1.导入 2.刷单 */ - private Integer type; - /** 关联敦煌加购的id */ - private Long addCarId; -// /** 关联敦煌加购的ids */ -// private Long addCarIds; - /** 总金额 */ - private String amount; - /** 状态描述 */ - private String paymentResults; - /** 店铺名称 */ - private String shop; - /** 订单id */ - private String orderId; - /** 时间 */ - private String orderDate; - /** 状态 1.待执行 2.执行中 3.执行成功 4.执行失败 */ - private Integer status; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/DhCarGoods.java b/wjcy-common/src/main/java/me/zhengjie/entity/DhCarGoods.java deleted file mode 100644 index e19bc32..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/DhCarGoods.java +++ /dev/null @@ -1,62 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.Date; - -/** - * 敦煌-加入购物车商品信息(DhCarGoods)表实体类 - * - * @author makejava - * @since 2022-11-17 09:12:02 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class DhCarGoods extends Model { - - @TableId(value = "id", type = IdType.AUTO) - private Long id; - @TableField(fill = FieldFill.INSERT) - private String createdAt; - @TableField(fill = FieldFill.INSERT_UPDATE) - private String updatedAt; - /** 操作人账号*/ - @TableField(fill = FieldFill.INSERT_UPDATE) - private String gmName; - - /** 商品属性类型:1.关键词 2.链接 */ - private Integer paramsType; - /** 店铺名称 */ - private String shopName; - /** 关键词 */ - private String keyWord; - /** 标题 */ - private String title; - /** 链接 */ - private String link; - /** 数量 */ - private Integer number; - /** 规格 */ - private String specification; - /** 颜色 */ - private String color; - /** item */ - private String item; - /** 最小价格区间 */ - private String sectionMin; - /** 最大价格区间 */ - private String sectionMax; - /** 评论 */ - private String comment; - /** 图片url */ - private String paths; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/ExcelImportInfo.java b/wjcy-common/src/main/java/me/zhengjie/entity/ExcelImportInfo.java deleted file mode 100644 index 4090e67..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/ExcelImportInfo.java +++ /dev/null @@ -1,38 +0,0 @@ -//package me.zhengjie.entity; -// -//import lombok.AllArgsConstructor; -//import lombok.Data; -//import lombok.NoArgsConstructor; -//import me.zhengjie.utils.excel.ExcelImport; -// -///** -// * Excel导入信息实体类 -// * -// * @author rch -// * @create 2022-06-23 -// */ -//@Data -//@AllArgsConstructor -//@NoArgsConstructor -//public class ExcelImportInfo { -// /** 公司主键 */ -// @ExcelImport("公司主键") -// private Long companyId; -// -// /** 鉴权枚举 */ -// @ExcelImport("鉴权枚举") -// private Integer tokenEnum; -// -// /** 订单来源 */ -// @ExcelImport("订单来源") -// private String fromDetailInfo; -// -// /** 产品信息-JSON */ -// @ExcelImport("产品信息") -// private String cartList; -// -// /** 订单收货地址-JSON */ -// @ExcelImport("订单收货地址") -// private String contactInfo; -// -//} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/LoginIp.java b/wjcy-common/src/main/java/me/zhengjie/entity/LoginIp.java deleted file mode 100644 index 8a20668..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/LoginIp.java +++ /dev/null @@ -1,39 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.Data; - -/** - * (LoginIp)表实体类 - * - * @author rch - * @since 2022-06-23 - */ -@Data -public class LoginIp extends Model { - - @TableId(value = "id", type = IdType.AUTO) - private Integer id; - @TableField(fill = FieldFill.INSERT) - private String createdAt; - @TableField(fill = FieldFill.INSERT_UPDATE) - private String updatedAt; - - /** 开始IP */ - private String ipStart; - /** 结束IP */ - private String ipEnd; - /** 备注 */ - private String remark; - /** 有效截至时间 */ - private String vaildTime; - /** 操作账号 */ - @TableField(fill = FieldFill.INSERT_UPDATE) - private String gmName; - -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/QueryWrapperAndPage.java b/wjcy-common/src/main/java/me/zhengjie/entity/QueryWrapperAndPage.java deleted file mode 100644 index 48d8f52..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/QueryWrapperAndPage.java +++ /dev/null @@ -1,15 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@AllArgsConstructor -@NoArgsConstructor -public class QueryWrapperAndPage { - QueryWrapper queryWrapper; - Page page; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/ResultObj.java b/wjcy-common/src/main/java/me/zhengjie/entity/ResultObj.java deleted file mode 100644 index 21e6c83..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/ResultObj.java +++ /dev/null @@ -1,20 +0,0 @@ -package me.zhengjie.entity; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 影刀回调响应-resultObj - * - * @author rch - * @create 2022-08-23 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class ResultObj { - private String name; - private String type; - private String value; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/ReturnObje.java b/wjcy-common/src/main/java/me/zhengjie/entity/ReturnObje.java deleted file mode 100644 index 46d863c..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/ReturnObje.java +++ /dev/null @@ -1,28 +0,0 @@ -package me.zhengjie.entity; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.List; - -/** - * 影刀回调返回值-ReturnObj - * - * @author rch - * @create 2022-08-23 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class ReturnObje { - private String msg; - private List result; - private String jobUuid; - private String robotClientName; - private String robotName; - private String robotClientUuid; - private String startTime; - private String endTime; - private String status; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/SysQuartzJob.java b/wjcy-common/src/main/java/me/zhengjie/entity/SysQuartzJob.java deleted file mode 100644 index cdab873..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/SysQuartzJob.java +++ /dev/null @@ -1,70 +0,0 @@ -package me.zhengjie.entity; - -import java.util.Date; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotNull; -import java.io.Serializable; - -/** - * 定时任务(SysQuartzJob)表实体类 - * - * @author rch - * @since 2022-07-20 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class SysQuartzJob extends Model { - - public static final String JOB_KEY = "JOB_KEY"; - - @TableId(value = "job_id", type = IdType.AUTO) - private Long jobId; - - private String createTime; - private String updateTime; - /** 操作人账号*/ - @TableField(fill = FieldFill.INSERT_UPDATE) - private String gmName; - - private Long taskNum; - /** 类型 1.普通 2.影刀 */ - private Integer type; - /** Spring Bean名称 */ - private String beanName; - /** cron 表达式 */ - private String cronExpression; - /** 状态:1暂停、0启用 */ - private Integer isPause; - /** 任务名称 */ - private String jobName; - /** 方法名称 */ - private String methodName; - /** 参数 */ - private String params; - /** 参数类型 */ - private Integer paramsType; - /** 备注 */ - private String description; - /** 负责人 */ - private String personInCharge; - /** 报警邮箱 */ - private String email; - /** 子任务ID */ - private String subTask; - /** 任务失败后是否暂停 */ - private Integer pauseAfterFailure; - /** 创建者 */ - private String createBy; - /** 更新者 */ - private String updateBy; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/SysQuartzLog.java b/wjcy-common/src/main/java/me/zhengjie/entity/SysQuartzLog.java deleted file mode 100644 index 3ed54bf..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/SysQuartzLog.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.sql.Timestamp; - -/** - * @author rch - * @date 2022-07-20 - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -public class SysQuartzLog extends Model { - - private Long logId; - /** bean名称 */ - private String beanName; - /** 方法名称 */ - private String methodName; - - /** 参数 */ - private String params; - - /** cron表达式 */ - private String cronExpression; - - /** 状态 */ - private Boolean isSuccess; - - /** 异常详情 */ - private String exceptionDetail; - - /** 执行耗时 */ - private Long time; - - /** 创建时间 */ - private Timestamp createTime; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/YdSign.java b/wjcy-common/src/main/java/me/zhengjie/entity/YdSign.java deleted file mode 100644 index 7e69897..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/YdSign.java +++ /dev/null @@ -1,32 +0,0 @@ -package me.zhengjie.entity; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 影刀 鉴权 - * - * @author rch - * @since 2022-07-26 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class YdSign extends Model { - - /** 时间戳 */ - private Long timestamp; - /** accessKeyId */ - private String accessKeyId; - /** accessKeySecret */ - private String accessKeySecret; - /** bodyMd5 */ - private String bodyMd5; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/YdStartReturn.java b/wjcy-common/src/main/java/me/zhengjie/entity/YdStartReturn.java deleted file mode 100644 index abf9b72..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/YdStartReturn.java +++ /dev/null @@ -1,24 +0,0 @@ -package me.zhengjie.entity; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 调用影刀启动任务响应信息 - * - * @author rch - * @create 2022-08-24 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class YdStartReturn { - private String code; - private Boolean success; - private TaskUuid data; -} - -class TaskUuid { - private String taskUuid; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/quartz/Boss.java b/wjcy-common/src/main/java/me/zhengjie/entity/quartz/Boss.java deleted file mode 100644 index b6cd0db..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/quartz/Boss.java +++ /dev/null @@ -1,23 +0,0 @@ -package me.zhengjie.entity.quartz; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.List; - -/** - * 调用影刀json信息 - * - * @author rch - * @create 2022-08-01 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class Boss { - private String accountName; - private String robotUuid; - private Long applyId; - private List params; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/quartz/DataInfo.java b/wjcy-common/src/main/java/me/zhengjie/entity/quartz/DataInfo.java deleted file mode 100644 index 97d9a32..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/quartz/DataInfo.java +++ /dev/null @@ -1,19 +0,0 @@ -package me.zhengjie.entity.quartz; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 调用影刀响应子集信息 - * - * @author rch - * @create 2022-08-01 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class DataInfo { - private String accessToken; - private String expiresIn; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/quartz/JobQueryByUuid.java b/wjcy-common/src/main/java/me/zhengjie/entity/quartz/JobQueryByUuid.java deleted file mode 100644 index f80e95d..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/quartz/JobQueryByUuid.java +++ /dev/null @@ -1,18 +0,0 @@ -package me.zhengjie.entity.quartz; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 根据影刀任务ID查询影刀任务执行信息 - * - * @author rch - * @create 2022-08-01 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class JobQueryByUuid { - private String jobUuid; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/quartz/JobQueryByUuidData.java b/wjcy-common/src/main/java/me/zhengjie/entity/quartz/JobQueryByUuidData.java deleted file mode 100644 index 54bc9f6..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/quartz/JobQueryByUuidData.java +++ /dev/null @@ -1,28 +0,0 @@ -package me.zhengjie.entity.quartz; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 根据影刀任务id 查询影刀任务详情信息 - * - * @author rch - * @create 2022-08-01 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class JobQueryByUuidData { - private JobQueryByUuidRobotParams robotParams; - private String jobUuid; - private String status; - private String statusName; - private String robotUuid; - private String robotName; - private String startTime; - private String endTime; - private String remark; - private String robotClientUuid; - private String robotClientName; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/quartz/JobQueryByUuidReturn.java b/wjcy-common/src/main/java/me/zhengjie/entity/quartz/JobQueryByUuidReturn.java deleted file mode 100644 index 3217b49..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/quartz/JobQueryByUuidReturn.java +++ /dev/null @@ -1,93 +0,0 @@ -package me.zhengjie.entity.quartz; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 根据影刀任务id 查询影刀任务详情信息 - * - * @author rch - * @create 2022-08-01 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class JobQueryByUuidReturn { - private String code; - private Boolean success; - private JobQueryByUuidData data; - - /** - * { - * "data": { - * "jobUuid": "e925cd35-6857-48ae-a4ef-40ceea975e50", - * "status": "error", - * "statusName": "异常", - * "robotUuid": "9107fa36-a6d0-4ac6-932f-8fcbb7deb89b", - * "robotName": "刷单系统", - * "startTime": "2022-09-09 15:14:32", - * "endTime": "2022-09-09 15:15:52", - * "remark": "【e925cd35-6857-48ae-a4ef-40ceea975e50】任务失败,在【1-2清空浏览器数据】中第1行:出错:The tab was closed.", - * "robotParams": { - * "inputs": [ - * { - * "name": "id", - * "value": "4", - * "type": "str" - * }, - * { - * "name": "country", - * "value": "Korea", - * "type": "str" - * }, - * { - * "name": "account", - * "value": "borislanphere553@gmail.com", - * "type": "str" - * }, - * { - * "name": "pwd", - * "value": "sdwjcy2021", - * "type": "str" - * }, - * { - * "name": "keyWord", - * "value": "neck electric massage", - * "type": "str" - * }, - * { - * "name": "number", - * "value": "10", - * "type": "str" - * }, - * { - * "name": "specification", - * "value": "type-c", - * "type": "str" - * }, - * { - * "name": "color", - * "value": "Full Function", - * "type": "str" - * }, - * { - * "name": "item", - * "value": "1005001346919788", - * "type": "str" - * }, - * { - * "name": "vpnShare", - * "value": "ew0KICAidiI6ICIyIiwNCiAgInBzIjogIjEwNC4yMjEuMTk5LjgyIiwNCiAgImFkZCI6ICJ1cy1lczM0LmZvYmhlbHAuY29tIiwNCiAgInBvcnQiOiAiMzAwNDMiLA0KICAiaWQiOiAiYzA4NDk5ODQtZWNjNC01MzY3LTlmOTctYTI2ODljNTQ5N2QyIiwNCiAgImFpZCI6ICI2NCIsDQogICJzY3kiOiAiYXV0byIsDQogICJuZXQiOiAidGNwIiwNCiAgInR5cGUiOiAibm9uZSIsDQogICJob3N0IjogIiIsDQogICJwYXRoIjogIiIsDQogICJ0bHMiOiAiIiwNCiAgInNuaSI6ICIiDQp9", - * "type": "str" - * } - * ] - * }, - * "robotClientUuid": "13d29cc7-3feb-46b5-a02c-66dced9dfeca", - * "robotClientName": "linbiaoyuan@vogocm" - * }, - * "code": 200, - * "success": true - * } - */ -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/quartz/JobQueryByUuidRobotParams.java b/wjcy-common/src/main/java/me/zhengjie/entity/quartz/JobQueryByUuidRobotParams.java deleted file mode 100644 index 64c3501..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/quartz/JobQueryByUuidRobotParams.java +++ /dev/null @@ -1,22 +0,0 @@ -package me.zhengjie.entity.quartz; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.entity.ResultObj; - -import java.util.List; - -/** - * 根据影刀任务id查询影刀 - * - * @author rch - * @create 2022-09-09 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class JobQueryByUuidRobotParams { - private List inputs; - private List outputs; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/quartz/JobQueryReturnResult.java b/wjcy-common/src/main/java/me/zhengjie/entity/quartz/JobQueryReturnResult.java deleted file mode 100644 index 5958ca9..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/quartz/JobQueryReturnResult.java +++ /dev/null @@ -1,22 +0,0 @@ -package me.zhengjie.entity.quartz; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 根据影刀任务id 查询影刀任务详情信息 - * - * @author rch - * @create 2022-08-01 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class JobQueryReturnResult { - private String id; - private String status; - private String statusName; - private String code; - private Boolean success; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/quartz/Param.java b/wjcy-common/src/main/java/me/zhengjie/entity/quartz/Param.java deleted file mode 100644 index 921efcd..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/quartz/Param.java +++ /dev/null @@ -1,20 +0,0 @@ -package me.zhengjie.entity.quartz; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 调用影刀真正入参信息 - * - * @author rch - * @create 2022-08-01 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class Param { - private String name; - private String value; - private String type = "str"; -} \ No newline at end of file diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/quartz/Params.java b/wjcy-common/src/main/java/me/zhengjie/entity/quartz/Params.java deleted file mode 100644 index a5782be..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/quartz/Params.java +++ /dev/null @@ -1,22 +0,0 @@ -package me.zhengjie.entity.quartz; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.List; - -/** - * 调用影刀json信息 params里的 params是一个跟业务相关的主建 - * - * @author rch - * @create 2022-08-01 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class Params { - private String accountName; - private Long applyId; - private String params; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/quartz/RebotStatu.java b/wjcy-common/src/main/java/me/zhengjie/entity/quartz/RebotStatu.java deleted file mode 100644 index 415baad..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/quartz/RebotStatu.java +++ /dev/null @@ -1,19 +0,0 @@ -package me.zhengjie.entity.quartz; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 机器人相应信息子集 - * - * @author rch - * @create 2022-08-01 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class RebotStatu { - private String robotClientUuid; - private String accountName; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/quartz/RebotStatuInfo.java b/wjcy-common/src/main/java/me/zhengjie/entity/quartz/RebotStatuInfo.java deleted file mode 100644 index 33f5e40..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/quartz/RebotStatuInfo.java +++ /dev/null @@ -1,29 +0,0 @@ -package me.zhengjie.entity.quartz; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 影刀机器人状态信息 - * - * @author rch - * @create 2022-08-01 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class RebotStatuInfo { - /** 状态 connected:已连接 idle:空闲 running:运行中 allocated:已分配 abnormal:异常 offline:离线 */ - private String status; - /** 机器人客户端ip */ - private String clientIp; - /** 机器人uuid */ - private String robotClientUuid; - /** 机器人名称 */ - private String robotClientName; - /** 机器人备注 */ - private String description; - /** 运行备注 */ - private String remark; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/quartz/RebotStatuReturn.java b/wjcy-common/src/main/java/me/zhengjie/entity/quartz/RebotStatuReturn.java deleted file mode 100644 index 20b7669..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/quartz/RebotStatuReturn.java +++ /dev/null @@ -1,20 +0,0 @@ -package me.zhengjie.entity.quartz; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 机器人相应信息 - * - * @author rch - * @create 2022-08-01 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class RebotStatuReturn { - private String code; - private Boolean success; - private RebotStatuInfo data; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/quartz/SecreInfo.java b/wjcy-common/src/main/java/me/zhengjie/entity/quartz/SecreInfo.java deleted file mode 100644 index c835970..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/quartz/SecreInfo.java +++ /dev/null @@ -1,21 +0,0 @@ -package me.zhengjie.entity.quartz; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 调用影刀相应信息 - * - * @author rch - * @create 2022-08-01 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class SecreInfo { - private String code; - private Boolean success; - private String requestId; - private DataInfo data; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/entity/quartz/StartYdReturnInfo.java b/wjcy-common/src/main/java/me/zhengjie/entity/quartz/StartYdReturnInfo.java deleted file mode 100644 index fffefe0..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/entity/quartz/StartYdReturnInfo.java +++ /dev/null @@ -1,22 +0,0 @@ -package me.zhengjie.entity.quartz; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 启动影刀任务响应信息 - * - * @author rch - * @create 2022-10-27 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class StartYdReturnInfo { - private String code; - private Boolean success; - private String requestId; - private String serverInstName; - private String msg; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/enums/BuyerLevelEnum.java b/wjcy-common/src/main/java/me/zhengjie/enums/BuyerLevelEnum.java deleted file mode 100644 index cb93bf3..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/enums/BuyerLevelEnum.java +++ /dev/null @@ -1,77 +0,0 @@ -package me.zhengjie.enums; - -import me.zhengjie.enums.interfaces.IntegerEnum; -import org.apache.commons.lang3.EnumUtils; - -/** - *

- * 用户等级 1.普通 2.精品 3.压力 4.内部账号 - *

- * - * @Author rch - * @Date 2022-07-18 - **/ -public enum BuyerLevelEnum implements IntegerEnum { - /** - * 用户等级 1.普通 2.精品 3.压力 4.内部账号 - */ - - GENERAL(1), - BOUTIQUR(2), - PRESSURE(3), - INNER_ACCOUNT(4); - - private final Integer value; - - private BuyerLevelEnum(Integer value) { - this.value = value; - } - - - @Override - public Integer value() { - return this.value; - } - - /** - * 判断是否存在指定值 - * - * @param value - * @return - */ - public static boolean hasValue(Integer value) { - boolean hasVal = false; - if (getEnum(value) != null) { - hasVal = true; - } - return hasVal; - } - - /** - * 判断是否不存在指定值 - * - * @param value - * @return - */ - public static boolean notHasValue(Integer value) { - return !hasValue(value); - } - - /** - * 获取指定值对应的枚举 - * - * @param value - * @return - */ - public static BuyerLevelEnum getEnum(Integer value) { - if (value == null) { - return null; - } - for (BuyerLevelEnum obj : EnumUtils.getEnumList(BuyerLevelEnum.class)) { - if (obj.eqValue(value)) { - return obj; - } - } - return null; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/enums/BuyerOccupyStatusEnum.java b/wjcy-common/src/main/java/me/zhengjie/enums/BuyerOccupyStatusEnum.java deleted file mode 100644 index 3c09adb..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/enums/BuyerOccupyStatusEnum.java +++ /dev/null @@ -1,75 +0,0 @@ -package me.zhengjie.enums; - -import me.zhengjie.enums.interfaces.IntegerEnum; -import org.apache.commons.lang3.EnumUtils; - -/** - *

- * 占用状态 1.已占用 2.未占用 - *

- * - * @Author rch - * @Date 2022-07-18 - **/ -public enum BuyerOccupyStatusEnum implements IntegerEnum { - /** - * 占用状态 1.已占用 2.未占用 - */ - - OCCUPIED(1), - UN_OCCUPIED(2); - - private final Integer value; - - private BuyerOccupyStatusEnum(Integer value) { - this.value = value; - } - - - @Override - public Integer value() { - return this.value; - } - - /** - * 判断是否存在指定值 - * - * @param value - * @return - */ - public static boolean hasValue(Integer value) { - boolean hasVal = false; - if (getEnum(value) != null) { - hasVal = true; - } - return hasVal; - } - - /** - * 判断是否不存在指定值 - * - * @param value - * @return - */ - public static boolean notHasValue(Integer value) { - return !hasValue(value); - } - - /** - * 获取指定值对应的枚举 - * - * @param value - * @return - */ - public static BuyerOccupyStatusEnum getEnum(Integer value) { - if (value == null) { - return null; - } - for (BuyerOccupyStatusEnum obj : EnumUtils.getEnumList(BuyerOccupyStatusEnum.class)) { - if (obj.eqValue(value)) { - return obj; - } - } - return null; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/enums/BuyerStatusEnum.java b/wjcy-common/src/main/java/me/zhengjie/enums/BuyerStatusEnum.java deleted file mode 100644 index eb64052..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/enums/BuyerStatusEnum.java +++ /dev/null @@ -1,80 +0,0 @@ -package me.zhengjie.enums; - -import me.zhengjie.enums.interfaces.IntegerEnum; -import org.apache.commons.lang3.EnumUtils; - -/** - *

- * 状态(导入默认正常) 1.待注册 2待验证 3.待完善 4.正常 5.异常 6.可用但已用 7.删除 - *

- * - * @Author rch - * @Date 2022-06-23 - **/ -public enum BuyerStatusEnum implements IntegerEnum { - /** - * 状态(导入默认正常) 1.待注册 2待验证 3.待完善 4.正常 5.异常 6.可用但已用 7.删除', - */ - - TOBE_REGISTER(1), - TOBE_CHECKING(2), - TOBE_PERFECT(3), - NORMAL(4), - AB_NORMAL(5), - AVAILABLE_BUT_USED(6), - DEL(7); - - private final Integer value; - - private BuyerStatusEnum(Integer value) { - this.value = value; - } - - - @Override - public Integer value() { - return this.value; - } - - /** - * 判断是否存在指定值 - * - * @param value - * @return - */ - public static boolean hasValue(Integer value) { - boolean hasVal = false; - if (getEnum(value) != null) { - hasVal = true; - } - return hasVal; - } - - /** - * 判断是否不存在指定值 - * - * @param value - * @return - */ - public static boolean notHasValue(Integer value) { - return !hasValue(value); - } - - /** - * 获取指定值对应的枚举 - * - * @param value - * @return - */ - public static BuyerStatusEnum getEnum(Integer value) { - if (value == null) { - return null; - } - for (BuyerStatusEnum obj : EnumUtils.getEnumList(BuyerStatusEnum.class)) { - if (obj.eqValue(value)) { - return obj; - } - } - return null; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/enums/CardDealerTypeEnum.java b/wjcy-common/src/main/java/me/zhengjie/enums/CardDealerTypeEnum.java deleted file mode 100644 index de8c646..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/enums/CardDealerTypeEnum.java +++ /dev/null @@ -1,75 +0,0 @@ -package me.zhengjie.enums; - -import me.zhengjie.enums.interfaces.IntegerEnum; -import org.apache.commons.lang3.EnumUtils; - -/** - *

- * 信用卡所属厂商类型 枚举 - *

- * - * @Author rch - * @Date 2022-07-09 - **/ -public enum CardDealerTypeEnum implements IntegerEnum { - /** - * 所属厂商:1.AmzKeys 2.Airwallex - */ - - AMZKEYS(1), - AIRWALLEX(2); - - private final Integer value; - - private CardDealerTypeEnum(Integer value) { - this.value = value; - } - - - @Override - public Integer value() { - return this.value; - } - - /** - * 判断是否存在指定值 - * - * @param value - * @return - */ - public static boolean hasValue(Integer value) { - boolean hasVal = false; - if (getEnum(value) != null) { - hasVal = true; - } - return hasVal; - } - - /** - * 判断是否不存在指定值 - * - * @param value - * @return - */ - public static boolean notHasValue(Integer value) { - return !hasValue(value); - } - - /** - * 获取指定值对应的枚举 - * - * @param value - * @return - */ - public static CardDealerTypeEnum getEnum(Integer value) { - if (value == null) { - return null; - } - for (CardDealerTypeEnum obj : EnumUtils.getEnumList(CardDealerTypeEnum.class)) { - if (obj.eqValue(value)) { - return obj; - } - } - return null; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/enums/CardStatusEnum.java b/wjcy-common/src/main/java/me/zhengjie/enums/CardStatusEnum.java deleted file mode 100644 index 7c2966e..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/enums/CardStatusEnum.java +++ /dev/null @@ -1,76 +0,0 @@ -package me.zhengjie.enums; - -import me.zhengjie.enums.interfaces.IntegerEnum; -import org.apache.commons.lang3.EnumUtils; - -/** - *

- * 信用卡类状态枚举 - *

- * - * @Author rch - * @Date 2022-07-11 - **/ -public enum CardStatusEnum implements IntegerEnum { - /** - * 状态:1.正常、2.异常、3.已删除 - */ - - NORMAL(1), - AB_NORMAL(2), - DEL(3); - - private final Integer value; - - private CardStatusEnum(Integer value) { - this.value = value; - } - - - @Override - public Integer value() { - return this.value; - } - - /** - * 判断是否存在指定值 - * - * @param value - * @return - */ - public static boolean hasValue(Integer value) { - boolean hasVal = false; - if (getEnum(value) != null) { - hasVal = true; - } - return hasVal; - } - - /** - * 判断是否不存在指定值 - * - * @param value - * @return - */ - public static boolean notHasValue(Integer value) { - return !hasValue(value); - } - - /** - * 获取指定值对应的枚举 - * - * @param value - * @return - */ - public static CardStatusEnum getEnum(Integer value) { - if (value == null) { - return null; - } - for (CardStatusEnum obj : EnumUtils.getEnumList(CardStatusEnum.class)) { - if (obj.eqValue(value)) { - return obj; - } - } - return null; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/enums/CardTypeEnum.java b/wjcy-common/src/main/java/me/zhengjie/enums/CardTypeEnum.java deleted file mode 100644 index 24db1b5..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/enums/CardTypeEnum.java +++ /dev/null @@ -1,76 +0,0 @@ -package me.zhengjie.enums; - -import me.zhengjie.enums.interfaces.IntegerEnum; -import org.apache.commons.lang3.EnumUtils; - -/** - *

- * 信用卡类型 枚举 - *

- * - * @Author rch - * @Date 2022-07-09 - **/ -public enum CardTypeEnum implements IntegerEnum { - /** - * 信用卡类型 1.Payoneer 2.万事达虚拟卡 3.Visa信用卡 - */ - - PAYONEER(1), - WSD_INVENTED(2), - VISA(3); - - private final Integer value; - - private CardTypeEnum(Integer value) { - this.value = value; - } - - - @Override - public Integer value() { - return this.value; - } - - /** - * 判断是否存在指定值 - * - * @param value - * @return - */ - public static boolean hasValue(Integer value) { - boolean hasVal = false; - if (getEnum(value) != null) { - hasVal = true; - } - return hasVal; - } - - /** - * 判断是否不存在指定值 - * - * @param value - * @return - */ - public static boolean notHasValue(Integer value) { - return !hasValue(value); - } - - /** - * 获取指定值对应的枚举 - * - * @param value - * @return - */ - public static CardTypeEnum getEnum(Integer value) { - if (value == null) { - return null; - } - for (CardTypeEnum obj : EnumUtils.getEnumList(CardTypeEnum.class)) { - if (obj.eqValue(value)) { - return obj; - } - } - return null; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/enums/ClickBrowseStatusEnum.java b/wjcy-common/src/main/java/me/zhengjie/enums/ClickBrowseStatusEnum.java deleted file mode 100644 index 650fd7d..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/enums/ClickBrowseStatusEnum.java +++ /dev/null @@ -1,77 +0,0 @@ -package me.zhengjie.enums; - -import me.zhengjie.enums.interfaces.IntegerEnum; -import org.apache.commons.lang3.EnumUtils; - -/** - *

- * 浏览好评状态枚举 - *

- * - * @Author rch - * @Date 2022-11-07 - **/ -public enum ClickBrowseStatusEnum implements IntegerEnum { - /** - * 状态 1.待执行 2.执行中 3.执行成功 4.执行失败 - */ - - TOBE_EXECUTION(1), - IN_EXECUTION(2), - EXECUTION_SUCCESS(3), - EXECUTION_FAILE(4); - - private final Integer value; - - private ClickBrowseStatusEnum(Integer value) { - this.value = value; - } - - - @Override - public Integer value() { - return this.value; - } - - /** - * 判断是否存在指定值 - * - * @param value - * @return - */ - public static boolean hasValue(Integer value) { - boolean hasVal = false; - if (getEnum(value) != null) { - hasVal = true; - } - return hasVal; - } - - /** - * 判断是否不存在指定值 - * - * @param value - * @return - */ - public static boolean notHasValue(Integer value) { - return !hasValue(value); - } - - /** - * 获取指定值对应的枚举 - * - * @param value - * @return - */ - public static ClickBrowseStatusEnum getEnum(Integer value) { - if (value == null) { - return null; - } - for (ClickBrowseStatusEnum obj : EnumUtils.getEnumList(ClickBrowseStatusEnum.class)) { - if (obj.eqValue(value)) { - return obj; - } - } - return null; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/enums/ClickFarmingStatusEnum.java b/wjcy-common/src/main/java/me/zhengjie/enums/ClickFarmingStatusEnum.java deleted file mode 100644 index 2f0ae99..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/enums/ClickFarmingStatusEnum.java +++ /dev/null @@ -1,79 +0,0 @@ -package me.zhengjie.enums; - -import me.zhengjie.enums.interfaces.IntegerEnum; -import org.apache.commons.lang3.EnumUtils; - -/** - *

- * 刷单状态枚举 - *

- * - * @Author rch - * @Date 2022-07-11 - **/ -public enum ClickFarmingStatusEnum implements IntegerEnum { - /** - * 状态 1.待执行 2.执行中 3.执行成功 4.执行失败 5.待支付 6.支付成功异常 (加购比较特殊 判断是否有订单号, 执行成功没有订单号是加购物车成功,区分抓单成功) - */ - - TOBE_EXECUTION(1), - IN_EXECUTION(2), - EXECUTION_SUCCESS(3), - EXECUTION_FAILE(4), - AWAITING_PAYMENT(5), - PAY_OK_ERROR(6); - - private final Integer value; - - private ClickFarmingStatusEnum(Integer value) { - this.value = value; - } - - - @Override - public Integer value() { - return this.value; - } - - /** - * 判断是否存在指定值 - * - * @param value - * @return - */ - public static boolean hasValue(Integer value) { - boolean hasVal = false; - if (getEnum(value) != null) { - hasVal = true; - } - return hasVal; - } - - /** - * 判断是否不存在指定值 - * - * @param value - * @return - */ - public static boolean notHasValue(Integer value) { - return !hasValue(value); - } - - /** - * 获取指定值对应的枚举 - * - * @param value - * @return - */ - public static ClickFarmingStatusEnum getEnum(Integer value) { - if (value == null) { - return null; - } - for (ClickFarmingStatusEnum obj : EnumUtils.getEnumList(ClickFarmingStatusEnum.class)) { - if (obj.eqValue(value)) { - return obj; - } - } - return null; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/enums/ClickOrderStatusEnum.java b/wjcy-common/src/main/java/me/zhengjie/enums/ClickOrderStatusEnum.java deleted file mode 100644 index 5530634..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/enums/ClickOrderStatusEnum.java +++ /dev/null @@ -1,77 +0,0 @@ -package me.zhengjie.enums; - -import me.zhengjie.enums.interfaces.IntegerEnum; -import org.apache.commons.lang3.EnumUtils; - -/** - *

- * 刷单订单状态枚举 - *

- * - * @Author rch - * @Date 2022-07-11 - **/ -public enum ClickOrderStatusEnum implements IntegerEnum { - /** - * 状态 1.待执行 2.执行中 3.执行成功 4.执行失败 - */ - - TOBE_EXECUTION(1), - IN_EXECUTION(2), - EXECUTION_SUCCESS(3), - EXECUTION_FAILE(4); - - private final Integer value; - - private ClickOrderStatusEnum(Integer value) { - this.value = value; - } - - - @Override - public Integer value() { - return this.value; - } - - /** - * 判断是否存在指定值 - * - * @param value - * @return - */ - public static boolean hasValue(Integer value) { - boolean hasVal = false; - if (getEnum(value) != null) { - hasVal = true; - } - return hasVal; - } - - /** - * 判断是否不存在指定值 - * - * @param value - * @return - */ - public static boolean notHasValue(Integer value) { - return !hasValue(value); - } - - /** - * 获取指定值对应的枚举 - * - * @param value - * @return - */ - public static ClickOrderStatusEnum getEnum(Integer value) { - if (value == null) { - return null; - } - for (ClickOrderStatusEnum obj : EnumUtils.getEnumList(ClickOrderStatusEnum.class)) { - if (obj.eqValue(value)) { - return obj; - } - } - return null; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/enums/CtReboteStatusEnum.java b/wjcy-common/src/main/java/me/zhengjie/enums/CtReboteStatusEnum.java deleted file mode 100644 index a4e828b..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/enums/CtReboteStatusEnum.java +++ /dev/null @@ -1,75 +0,0 @@ -package me.zhengjie.enums; - -import me.zhengjie.enums.interfaces.IntegerEnum; -import org.apache.commons.lang3.EnumUtils; - -/** - *

- * 机器人 状态0.未占用 1.占用 - *

- * - * @Author xxs - * @Date 2021/9/26 - **/ -public enum CtReboteStatusEnum implements IntegerEnum { - /** - * 状态0.未占用 1.占用 - */ - - UNOCCUPIED(0), - OCCUPY(1); - - private final Integer value; - - private CtReboteStatusEnum(Integer value) { - this.value = value; - } - - - @Override - public Integer value() { - return this.value; - } - - /** - * 判断是否存在指定值 - * - * @param value - * @return - */ - public static boolean hasValue(Integer value) { - boolean hasVal = false; - if (getEnum(value) != null) { - hasVal = true; - } - return hasVal; - } - - /** - * 判断是否不存在指定值 - * - * @param value - * @return - */ - public static boolean notHasValue(Integer value) { - return !hasValue(value); - } - - /** - * 获取指定值对应的枚举 - * - * @param value - * @return - */ - public static CtReboteStatusEnum getEnum(Integer value) { - if (value == null) { - return null; - } - for (CtReboteStatusEnum obj : EnumUtils.getEnumList(CtReboteStatusEnum.class)) { - if (obj.eqValue(value)) { - return obj; - } - } - return null; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/enums/DhAddCarStatusEnum.java b/wjcy-common/src/main/java/me/zhengjie/enums/DhAddCarStatusEnum.java deleted file mode 100644 index 9c7ed42..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/enums/DhAddCarStatusEnum.java +++ /dev/null @@ -1,82 +0,0 @@ -package me.zhengjie.enums; - -import me.zhengjie.enums.interfaces.IntegerEnum; -import org.apache.commons.lang3.EnumUtils; - -/** - *

- * 敦煌加购状态枚举 - *

- * - * @Author rch - * @Date 2022-07-11 - **/ -public enum DhAddCarStatusEnum implements IntegerEnum { - /** - * 状态 1.待执行 2.执行中 3.加购成功 4.加购失败 5.下单成功 6.待抓单 7.抓单中 8.抓单成功 9.抓单失败 - */ - - TOBE_EXECUTION(1), - IN_EXECUTION(2), - Add_CARD_SUCCESS(3), - ADD_CARD_FAILE(4), - ORDER_SUCCESS(5), - TO_BE_CATCH_ORDER(6), - CATCH_ORDER_ING(7), - CATCH_ORDER_SUCCESS(8), - CATCH_ORDER_FAILE(9); - - private final Integer value; - - private DhAddCarStatusEnum(Integer value) { - this.value = value; - } - - - @Override - public Integer value() { - return this.value; - } - - /** - * 判断是否存在指定值 - * - * @param value - * @return - */ - public static boolean hasValue(Integer value) { - boolean hasVal = false; - if (getEnum(value) != null) { - hasVal = true; - } - return hasVal; - } - - /** - * 判断是否不存在指定值 - * - * @param value - * @return - */ - public static boolean notHasValue(Integer value) { - return !hasValue(value); - } - - /** - * 获取指定值对应的枚举 - * - * @param value - * @return - */ - public static DhAddCarStatusEnum getEnum(Integer value) { - if (value == null) { - return null; - } - for (DhAddCarStatusEnum obj : EnumUtils.getEnumList(DhAddCarStatusEnum.class)) { - if (obj.eqValue(value)) { - return obj; - } - } - return null; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/enums/DhPayStatusEnum.java b/wjcy-common/src/main/java/me/zhengjie/enums/DhPayStatusEnum.java deleted file mode 100644 index a232181..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/enums/DhPayStatusEnum.java +++ /dev/null @@ -1,77 +0,0 @@ -package me.zhengjie.enums; - -import me.zhengjie.enums.interfaces.IntegerEnum; -import org.apache.commons.lang3.EnumUtils; - -/** - *

- * 敦煌支付状态枚举 - *

- * - * @Author rch - * @Date 2022-07-28 - **/ -public enum DhPayStatusEnum implements IntegerEnum { - /** - * 状态 0.待处理 1.支付成功 2.支付失败 - */ - - TO_BE(0), - PAY_SUCCESS(1), - PAY_FAIL(2), - DEL(3); - - private final Integer value; - - private DhPayStatusEnum(Integer value) { - this.value = value; - } - - - @Override - public Integer value() { - return this.value; - } - - /** - * 判断是否存在指定值 - * - * @param value - * @return - */ - public static boolean hasValue(Integer value) { - boolean hasVal = false; - if (getEnum(value) != null) { - hasVal = true; - } - return hasVal; - } - - /** - * 判断是否不存在指定值 - * - * @param value - * @return - */ - public static boolean notHasValue(Integer value) { - return !hasValue(value); - } - - /** - * 获取指定值对应的枚举 - * - * @param value - * @return - */ - public static DhPayStatusEnum getEnum(Integer value) { - if (value == null) { - return null; - } - for (DhPayStatusEnum obj : EnumUtils.getEnumList(DhPayStatusEnum.class)) { - if (obj.eqValue(value)) { - return obj; - } - } - return null; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/enums/ExcelInfoRequestTypeEnum.java b/wjcy-common/src/main/java/me/zhengjie/enums/ExcelInfoRequestTypeEnum.java deleted file mode 100644 index 65a14d2..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/enums/ExcelInfoRequestTypeEnum.java +++ /dev/null @@ -1,75 +0,0 @@ -package me.zhengjie.enums; - -import me.zhengjie.enums.interfaces.IntegerEnum; -import org.apache.commons.lang3.EnumUtils; - -/** - *

- * 请求类型:1.下单请求 2.支付请求 - *

- * - * @Author rch - * @Date 2022-06-23 - **/ -public enum ExcelInfoRequestTypeEnum implements IntegerEnum { - /** - * 请求类型:1.下单请求 2.支付请求 - */ - - BUY_ORDER(1), - PAY_ORDER(2); - - private final Integer value; - - private ExcelInfoRequestTypeEnum(Integer value) { - this.value = value; - } - - - @Override - public Integer value() { - return this.value; - } - - /** - * 判断是否存在指定值 - * - * @param value - * @return - */ - public static boolean hasValue(Integer value) { - boolean hasVal = false; - if (getEnum(value) != null) { - hasVal = true; - } - return hasVal; - } - - /** - * 判断是否不存在指定值 - * - * @param value - * @return - */ - public static boolean notHasValue(Integer value) { - return !hasValue(value); - } - - /** - * 获取指定值对应的枚举 - * - * @param value - * @return - */ - public static ExcelInfoRequestTypeEnum getEnum(Integer value) { - if (value == null) { - return null; - } - for (ExcelInfoRequestTypeEnum obj : EnumUtils.getEnumList(ExcelInfoRequestTypeEnum.class)) { - if (obj.eqValue(value)) { - return obj; - } - } - return null; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/enums/ExcelStatusEnum.java b/wjcy-common/src/main/java/me/zhengjie/enums/ExcelStatusEnum.java deleted file mode 100644 index 9cdce5e..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/enums/ExcelStatusEnum.java +++ /dev/null @@ -1,76 +0,0 @@ -package me.zhengjie.enums; - -import me.zhengjie.enums.interfaces.IntegerEnum; -import org.apache.commons.lang3.EnumUtils; - -/** - *

- * 状态1.待导入 2.导入成功 3.导入失败 - *

- * - * @Author rch - * @Date 2022-06-23 - **/ -public enum ExcelStatusEnum implements IntegerEnum { - /** - * 状态1.待导入 2.导入成功 3.导入失败 - */ - - TOBE(1), - SUCCESS(2), - FAILE(3); - - private final Integer value; - - private ExcelStatusEnum(Integer value) { - this.value = value; - } - - - @Override - public Integer value() { - return this.value; - } - - /** - * 判断是否存在指定值 - * - * @param value - * @return - */ - public static boolean hasValue(Integer value) { - boolean hasVal = false; - if (getEnum(value) != null) { - hasVal = true; - } - return hasVal; - } - - /** - * 判断是否不存在指定值 - * - * @param value - * @return - */ - public static boolean notHasValue(Integer value) { - return !hasValue(value); - } - - /** - * 获取指定值对应的枚举 - * - * @param value - * @return - */ - public static ExcelStatusEnum getEnum(Integer value) { - if (value == null) { - return null; - } - for (ExcelStatusEnum obj : EnumUtils.getEnumList(ExcelStatusEnum.class)) { - if (obj.eqValue(value)) { - return obj; - } - } - return null; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/enums/LanguageEnum.java b/wjcy-common/src/main/java/me/zhengjie/enums/LanguageEnum.java deleted file mode 100644 index 79ce4d8..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/enums/LanguageEnum.java +++ /dev/null @@ -1,38 +0,0 @@ -package me.zhengjie.enums; - -/** - * 多语言枚举类 - * - * @author zeng - * @since 2021/08/24 10:08 - */ - -public enum LanguageEnum { - - ZH("简体中文"), - - EN("英文"), - - CW("繁体中文"), - ; - - private final String des; - - LanguageEnum(String des) { - this.des = des; - } - - public String getValue() { - return this.name().toLowerCase(); - } - - public static boolean isInclude(String language) { - for (LanguageEnum value : LanguageEnum.values()) { - if (value.getValue().equals(language)) { - return true; - } - } - return false; - } - -} diff --git a/wjcy-common/src/main/java/me/zhengjie/enums/OrderTypeEnum.java b/wjcy-common/src/main/java/me/zhengjie/enums/OrderTypeEnum.java deleted file mode 100644 index 238cda8..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/enums/OrderTypeEnum.java +++ /dev/null @@ -1,75 +0,0 @@ -package me.zhengjie.enums; - -import me.zhengjie.enums.interfaces.IntegerEnum; -import org.apache.commons.lang3.EnumUtils; - -/** - *

- * 刷单订单类型枚举 - *

- * - * @Author rch - * @Date 2022-10-24 - **/ -public enum OrderTypeEnum implements IntegerEnum { - /** - * 状态 1.导入 2.刷单 - */ - - IMPORT(1), - CLICK_FARMING(2); - - private final Integer value; - - private OrderTypeEnum(Integer value) { - this.value = value; - } - - - @Override - public Integer value() { - return this.value; - } - - /** - * 判断是否存在指定值 - * - * @param value - * @return - */ - public static boolean hasValue(Integer value) { - boolean hasVal = false; - if (getEnum(value) != null) { - hasVal = true; - } - return hasVal; - } - - /** - * 判断是否不存在指定值 - * - * @param value - * @return - */ - public static boolean notHasValue(Integer value) { - return !hasValue(value); - } - - /** - * 获取指定值对应的枚举 - * - * @param value - * @return - */ - public static OrderTypeEnum getEnum(Integer value) { - if (value == null) { - return null; - } - for (OrderTypeEnum obj : EnumUtils.getEnumList(OrderTypeEnum.class)) { - if (obj.eqValue(value)) { - return obj; - } - } - return null; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/enums/ParamsTypeEnum.java b/wjcy-common/src/main/java/me/zhengjie/enums/ParamsTypeEnum.java deleted file mode 100644 index 59a9f18..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/enums/ParamsTypeEnum.java +++ /dev/null @@ -1,75 +0,0 @@ -package me.zhengjie.enums; - -import me.zhengjie.enums.interfaces.IntegerEnum; -import org.apache.commons.lang3.EnumUtils; - -/** - *

- * 参数类型类型 枚举 - *

- * - * @Author rch - * @Date 2022-07-09 - **/ -public enum ParamsTypeEnum implements IntegerEnum { - /** - * 商品属性类型:1.关键词 2.链接 - */ - - KEY_WORD(1), - LINK(2); - - private final Integer value; - - private ParamsTypeEnum(Integer value) { - this.value = value; - } - - - @Override - public Integer value() { - return this.value; - } - - /** - * 判断是否存在指定值 - * - * @param value - * @return - */ - public static boolean hasValue(Integer value) { - boolean hasVal = false; - if (getEnum(value) != null) { - hasVal = true; - } - return hasVal; - } - - /** - * 判断是否不存在指定值 - * - * @param value - * @return - */ - public static boolean notHasValue(Integer value) { - return !hasValue(value); - } - - /** - * 获取指定值对应的枚举 - * - * @param value - * @return - */ - public static ParamsTypeEnum getEnum(Integer value) { - if (value == null) { - return null; - } - for (ParamsTypeEnum obj : EnumUtils.getEnumList(ParamsTypeEnum.class)) { - if (obj.eqValue(value)) { - return obj; - } - } - return null; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/enums/PlatTypeEnum.java b/wjcy-common/src/main/java/me/zhengjie/enums/PlatTypeEnum.java deleted file mode 100644 index 3b96ba6..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/enums/PlatTypeEnum.java +++ /dev/null @@ -1,92 +0,0 @@ -package me.zhengjie.enums; - -import org.apache.commons.lang3.EnumUtils; - -import java.util.Arrays; - -/** - *

- * 平台类型 1.敦煌 - *

- * - * @Author rch - * @Date 2022-07-06 - **/ -public enum PlatTypeEnum { - - //平台类型 1.敦煌 - DH(1, "敦煌"), - SMT(2, "速卖通"), - MB(3, "马帮"); - - - private final Integer type; - private final String desc; - - private PlatTypeEnum(Integer type, String desc) { - this.type = type; - this.desc = desc; - } - - public static String getDescByType(Integer type) { - if (type == null) { - return ""; - } - PlatTypeEnum[] enumAry = PlatTypeEnum.values(); - for(int i = 0; i < Arrays.asList(enumAry).size(); i++){ - if (enumAry[i].getType().equals(type)) { - return enumAry[i].getDesc(); - } - } - return ""; - } - - public static Integer getValueByDesc(String desc) { - PlatTypeEnum[] enumAry = PlatTypeEnum.values(); - for (PlatTypeEnum currencyTypeEnum : enumAry) { - if (currencyTypeEnum.getDesc().equals(desc)) { - return currencyTypeEnum.getType(); - } - } - return null; - } - - /** - * 获取指定值对应的枚举 - * - * @param value - * @return - */ - public static PlatTypeEnum getEnum(Integer value) { - if (value == null) { - return null; - } - for (PlatTypeEnum obj : EnumUtils.getEnumList(PlatTypeEnum.class)) { - if (obj.eqValue(value)) { - return obj; - } - } - return null; - } - - /** - * 值相等 - * - * @param value - * @return - */ - public boolean eqValue(Integer value) { - if (value != null && type.equals(value)) { - return true; - } - return false; - } - - public Integer getType() { - return type; - } - - public String getDesc() { - return desc; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/enums/RobotStatusEnum.java b/wjcy-common/src/main/java/me/zhengjie/enums/RobotStatusEnum.java deleted file mode 100644 index adcaa1c..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/enums/RobotStatusEnum.java +++ /dev/null @@ -1,77 +0,0 @@ -package me.zhengjie.enums; - -import org.apache.commons.lang3.EnumUtils; - -/** - *

- * 机器人状态 枚举 - *

- * - * @Author rch - * @Date 2022-07-09 - **/ -public enum RobotStatusEnum{ - /** - * 状态 connected:已连接 idle:空闲 running:运行中 allocated:已分配 abnormal:异常 offline:离线 - */ - - CONNECTED("connected"), - IDLE("idle"), - RUNNING("running"), - ALLOCATED("allocated"), - ABNORMAL("abnormal"), - OFFLINE("offline"); - - private final String value; - - private RobotStatusEnum(String value) { - this.value = value; - } - - - public String value() { - return this.value; - } - - /** - * 判断是否存在指定值 - * - * @param value - * @return - */ - public static boolean hasValue(String value) { - boolean hasVal = false; - if (getEnum(value) != null) { - hasVal = true; - } - return hasVal; - } - - /** - * 判断是否不存在指定值 - * - * @param value - * @return - */ - public static boolean notHasValue(String value) { - return !hasValue(value); - } - - /** - * 获取指定值对应的枚举 - * - * @param value - * @return - */ - public static RobotStatusEnum getEnum(String value) { - if (value == null) { - return null; - } - for (RobotStatusEnum obj : EnumUtils.getEnumList(RobotStatusEnum.class)) { - if (obj.value().equals(value)) { - return obj; - } - } - return null; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/enums/TaskInfoEnum.java b/wjcy-common/src/main/java/me/zhengjie/enums/TaskInfoEnum.java deleted file mode 100644 index 421bff1..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/enums/TaskInfoEnum.java +++ /dev/null @@ -1,54 +0,0 @@ -package me.zhengjie.enums; - -import java.util.Arrays; - -/** - *

- * Task 信息枚举 包含task基本信息 - *

- * - * @Author rch - * @Date 2022-08-01 - **/ -public enum TaskInfoEnum { - - // 1.Demo-Task - BOSS_TASK("bossTask", "run"), - CLICK_FARMING("clickFarmTask", "run"), - CLICK_FARMING_SUPPLE_MENY("clickFarmSuppleMentTask", "run"), - WELL_RECEIVED("wellReceivedTask", "run"), - BROWSE("browseTask", "run"), - DH_ADD_CAR_FARMING("dhAddCarTask", "run"), - DH_ADD_CAR_CATCH_ORDER("dhCatchOrderTask", "run"), - DH_WELL_RECEIVED("dhWellReceivedTask", "run"); - - - private final String taskName; - private final String methodName; - - private TaskInfoEnum(String taskName, String methodName) { - this.taskName = taskName; - this.methodName = methodName; - } - - public static String getMethodNameByTaskName(String taskName) { - if (taskName == null) { - return ""; - } - TaskInfoEnum[] enumAry = TaskInfoEnum.values(); - for(int i = 0; i < Arrays.asList(enumAry).size(); i++){ - if (enumAry[i].getTaskName().equals(taskName)) { - return enumAry[i].getMethodName(); - } - } - return ""; - } - - public String getTaskName() { - return taskName; - } - - public String getMethodName() { - return methodName; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/enums/TaskIsPauseEnum.java b/wjcy-common/src/main/java/me/zhengjie/enums/TaskIsPauseEnum.java deleted file mode 100644 index 440f9f0..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/enums/TaskIsPauseEnum.java +++ /dev/null @@ -1,75 +0,0 @@ -package me.zhengjie.enums; - -import me.zhengjie.enums.interfaces.IntegerEnum; -import org.apache.commons.lang3.EnumUtils; - -/** - *

- * 状态 1.暂停 2.启用 - *

- * - * @Author rch - * @Date 2022-10-06 - **/ -public enum TaskIsPauseEnum implements IntegerEnum { - /** - * 类型 1.暂停 0.启用 - */ - - IS_PAUSE(1), - NOT_PAUSE(0); - - private final Integer value; - - private TaskIsPauseEnum(Integer value) { - this.value = value; - } - - - @Override - public Integer value() { - return this.value; - } - - /** - * 判断是否存在指定值 - * - * @param value - * @return - */ - public static boolean hasValue(Integer value) { - boolean hasVal = false; - if (getEnum(value) != null) { - hasVal = true; - } - return hasVal; - } - - /** - * 判断是否不存在指定值 - * - * @param value - * @return - */ - public static boolean notHasValue(Integer value) { - return !hasValue(value); - } - - /** - * 获取指定值对应的枚举 - * - * @param value - * @return - */ - public static TaskIsPauseEnum getEnum(Integer value) { - if (value == null) { - return null; - } - for (TaskIsPauseEnum obj : EnumUtils.getEnumList(TaskIsPauseEnum.class)) { - if (obj.eqValue(value)) { - return obj; - } - } - return null; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/enums/TaskTypeEnum.java b/wjcy-common/src/main/java/me/zhengjie/enums/TaskTypeEnum.java deleted file mode 100644 index 6f25196..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/enums/TaskTypeEnum.java +++ /dev/null @@ -1,75 +0,0 @@ -package me.zhengjie.enums; - -import me.zhengjie.enums.interfaces.IntegerEnum; -import org.apache.commons.lang3.EnumUtils; - -/** - *

- * 类型 1.普通 2.影刀 - *

- * - * @Author rch - * @Date 2022-07-20 - **/ -public enum TaskTypeEnum implements IntegerEnum { - /** - * 类型 1.普通 2.影刀 - */ - - ORDINARY(1), - SHADOW_KNIFE(2); - - private final Integer value; - - private TaskTypeEnum(Integer value) { - this.value = value; - } - - - @Override - public Integer value() { - return this.value; - } - - /** - * 判断是否存在指定值 - * - * @param value - * @return - */ - public static boolean hasValue(Integer value) { - boolean hasVal = false; - if (getEnum(value) != null) { - hasVal = true; - } - return hasVal; - } - - /** - * 判断是否不存在指定值 - * - * @param value - * @return - */ - public static boolean notHasValue(Integer value) { - return !hasValue(value); - } - - /** - * 获取指定值对应的枚举 - * - * @param value - * @return - */ - public static TaskTypeEnum getEnum(Integer value) { - if (value == null) { - return null; - } - for (TaskTypeEnum obj : EnumUtils.getEnumList(TaskTypeEnum.class)) { - if (obj.eqValue(value)) { - return obj; - } - } - return null; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/enums/VpnDealerEnum.java b/wjcy-common/src/main/java/me/zhengjie/enums/VpnDealerEnum.java deleted file mode 100644 index b08953e..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/enums/VpnDealerEnum.java +++ /dev/null @@ -1,74 +0,0 @@ -package me.zhengjie.enums; - -import me.zhengjie.enums.interfaces.IntegerEnum; -import org.apache.commons.lang3.EnumUtils; - -/** - *

- * VPN经销商枚举 - *

- * - * @Author zhw - * @Date 2022-07-18 - **/ -public enum VpnDealerEnum implements IntegerEnum { - /** - * 状态:1.V2 - */ - - V2(1); - - private final Integer value; - - private VpnDealerEnum(Integer value) { - this.value = value; - } - - - @Override - public Integer value() { - return this.value; - } - - /** - * 判断是否存在指定值 - * - * @param value - * @return - */ - public static boolean hasValue(Integer value) { - boolean hasVal = false; - if (getEnum(value) != null) { - hasVal = true; - } - return hasVal; - } - - /** - * 判断是否不存在指定值 - * - * @param value - * @return - */ - public static boolean notHasValue(Integer value) { - return !hasValue(value); - } - - /** - * 获取指定值对应的枚举 - * - * @param value - * @return - */ - public static VpnDealerEnum getEnum(Integer value) { - if (value == null) { - return null; - } - for (VpnDealerEnum obj : EnumUtils.getEnumList(VpnDealerEnum.class)) { - if (obj.eqValue(value)) { - return obj; - } - } - return null; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/enums/VpnStatusEnum.java b/wjcy-common/src/main/java/me/zhengjie/enums/VpnStatusEnum.java deleted file mode 100644 index b246388..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/enums/VpnStatusEnum.java +++ /dev/null @@ -1,75 +0,0 @@ -package me.zhengjie.enums; - -import me.zhengjie.enums.interfaces.IntegerEnum; -import org.apache.commons.lang3.EnumUtils; - -/** - *

- * VPN类状态枚举 - *

- * - * @Author zhw - * @Date 2022-07-18 - **/ -public enum VpnStatusEnum implements IntegerEnum { - /** - * 状态:1.可用、2.禁用 - */ - - AVAILABLE(1), - DISABLED(2); - - private final Integer value; - - private VpnStatusEnum(Integer value) { - this.value = value; - } - - - @Override - public Integer value() { - return this.value; - } - - /** - * 判断是否存在指定值 - * - * @param value - * @return - */ - public static boolean hasValue(Integer value) { - boolean hasVal = false; - if (getEnum(value) != null) { - hasVal = true; - } - return hasVal; - } - - /** - * 判断是否不存在指定值 - * - * @param value - * @return - */ - public static boolean notHasValue(Integer value) { - return !hasValue(value); - } - - /** - * 获取指定值对应的枚举 - * - * @param value - * @return - */ - public static VpnStatusEnum getEnum(Integer value) { - if (value == null) { - return null; - } - for (VpnStatusEnum obj : EnumUtils.getEnumList(VpnStatusEnum.class)) { - if (obj.eqValue(value)) { - return obj; - } - } - return null; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/enums/VpnTypeEnum.java b/wjcy-common/src/main/java/me/zhengjie/enums/VpnTypeEnum.java deleted file mode 100644 index b52d540..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/enums/VpnTypeEnum.java +++ /dev/null @@ -1,74 +0,0 @@ -package me.zhengjie.enums; - -import me.zhengjie.enums.interfaces.IntegerEnum; -import org.apache.commons.lang3.EnumUtils; - -/** - *

- * VPN类型枚举 - *

- * - * @Author zhw - * @Date 2022-07-18 - **/ -public enum VpnTypeEnum implements IntegerEnum { - /** - * 状态:1.传统 - */ - - TRADITION(1); - - private final Integer value; - - private VpnTypeEnum(Integer value) { - this.value = value; - } - - - @Override - public Integer value() { - return this.value; - } - - /** - * 判断是否存在指定值 - * - * @param value - * @return - */ - public static boolean hasValue(Integer value) { - boolean hasVal = false; - if (getEnum(value) != null) { - hasVal = true; - } - return hasVal; - } - - /** - * 判断是否不存在指定值 - * - * @param value - * @return - */ - public static boolean notHasValue(Integer value) { - return !hasValue(value); - } - - /** - * 获取指定值对应的枚举 - * - * @param value - * @return - */ - public static VpnTypeEnum getEnum(Integer value) { - if (value == null) { - return null; - } - for (VpnTypeEnum obj : EnumUtils.getEnumList(VpnTypeEnum.class)) { - if (obj.eqValue(value)) { - return obj; - } - } - return null; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/enums/YesOrNoEnum.java b/wjcy-common/src/main/java/me/zhengjie/enums/YesOrNoEnum.java deleted file mode 100644 index 5b58315..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/enums/YesOrNoEnum.java +++ /dev/null @@ -1,75 +0,0 @@ -package me.zhengjie.enums; - -import me.zhengjie.enums.interfaces.IntegerEnum; -import org.apache.commons.lang3.EnumUtils; - -/** - *

- * Yes or No - *

- * - * @Author xxs - * @Date 2021/9/26 - **/ -public enum YesOrNoEnum implements IntegerEnum { - /** - * 类型型(1.YES 0.NO ) - */ - - YES(1), - NO(0); - - private final Integer value; - - private YesOrNoEnum(Integer value) { - this.value = value; - } - - - @Override - public Integer value() { - return this.value; - } - - /** - * 判断是否存在指定值 - * - * @param value - * @return - */ - public static boolean hasValue(Integer value) { - boolean hasVal = false; - if (getEnum(value) != null) { - hasVal = true; - } - return hasVal; - } - - /** - * 判断是否不存在指定值 - * - * @param value - * @return - */ - public static boolean notHasValue(Integer value) { - return !hasValue(value); - } - - /** - * 获取指定值对应的枚举 - * - * @param value - * @return - */ - public static YesOrNoEnum getEnum(Integer value) { - if (value == null) { - return null; - } - for (YesOrNoEnum obj : EnumUtils.getEnumList(YesOrNoEnum.class)) { - if (obj.eqValue(value)) { - return obj; - } - } - return null; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/enums/interfaces/IntegerEnum.java b/wjcy-common/src/main/java/me/zhengjie/enums/interfaces/IntegerEnum.java deleted file mode 100644 index f944411..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/enums/interfaces/IntegerEnum.java +++ /dev/null @@ -1,40 +0,0 @@ -package me.zhengjie.enums.interfaces; - -/** - *

- * Integer类型枚举 - *

- * - * @Author xx - * @Date 2021/7/22 - **/ -public interface IntegerEnum { - - /**值 - * @return - */ - Integer value(); - - /** - * 值相等 - * - * @param value - * @return - */ - default boolean eqValue(Integer value) { - if (value != null && value().equals(value)) { - return true; - } - return false; - } - - /** - * 值不相等 - * - * @param value - * @return - */ - default boolean neValue(Integer value) { - return !eqValue(value); - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/enums/interfaces/LongEnum.java b/wjcy-common/src/main/java/me/zhengjie/enums/interfaces/LongEnum.java deleted file mode 100644 index 8b210fa..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/enums/interfaces/LongEnum.java +++ /dev/null @@ -1,40 +0,0 @@ -package me.zhengjie.enums.interfaces; - -/** - *

- * Long类型枚举 - *

- * - * @Author xx - * @Date 2021/7/22 - **/ -public interface LongEnum { - - /**值 - * @return - */ - Long value(); - - /** - * 值相等 - * - * @param value - * @return - */ - default boolean eqValue(Long value) { - if (value != null && value().equals(value)) { - return true; - } - return false; - } - - /** - * 值不相等 - * - * @param value - * @return - */ - default boolean neValue(Long value) { - return !eqValue(value); - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/enums/interfaces/MemberIsUsedEnum.java b/wjcy-common/src/main/java/me/zhengjie/enums/interfaces/MemberIsUsedEnum.java deleted file mode 100644 index e5992be..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/enums/interfaces/MemberIsUsedEnum.java +++ /dev/null @@ -1,71 +0,0 @@ -package me.zhengjie.enums.interfaces; - -import org.apache.commons.lang3.EnumUtils; -/** - *

- * 用户是否使用过 - *

- * - * @Author xx - * @Date 2021/8/11 - **/ -public enum MemberIsUsedEnum implements IntegerEnum { - /** 未使用 */ - UN_USED(0), - /** 已使用*/ - IS_USED(1); - - private final Integer value; - - private MemberIsUsedEnum(Integer value) { - this.value = value; - } - - @Override - public Integer value() { - return this.value; - } - - /** - * 判断是否存在指定值 - * - * @param value - * @return - */ - public static boolean hasValue(Integer value) { - boolean hasVal = false; - if (getEnum(value) != null) { - hasVal = true; - } - return hasVal; - } - - /** - * 判断是否不存在指定值 - * - * @param value - * @return - */ - public static boolean notHasValue(Integer value) { - return !hasValue(value); - } - - /** - * 获取指定值对应的枚举 - * - * @param value - * @return - */ - public static MemberIsUsedEnum getEnum(Integer value) { - if (value == null) { - return null; - } - for (MemberIsUsedEnum obj : EnumUtils.getEnumList(MemberIsUsedEnum.class)) { - if (obj.eqValue(value)) { - return obj; - } - } - return null; - } -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/error/ErrorCodeEnum.java b/wjcy-common/src/main/java/me/zhengjie/error/ErrorCodeEnum.java deleted file mode 100644 index 834a36e..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/error/ErrorCodeEnum.java +++ /dev/null @@ -1,143 +0,0 @@ -package me.zhengjie.error; - -import cn.hutool.core.convert.Convert; -import me.zhengjie.utils.PropertiesUtil; -import me.zhengjie.utils.RequestHolder; - -/** - *

- * 返回错误枚举类型 - *

- * - * @Author xx - * @Date 2021/7/19 - **/ -public enum ErrorCodeEnum { - RETURN_SUCCESS(200, "响应成功"), - UNKNOWN_ERROR(2000,"服务器开小差了....,请稍后再试!"), - BAD_CREDENTIALS(2001,"坏的凭证"), - ENTITY_EXIST(2003,"信息重复添加"), - ENTITY_NOT_FOUND(2004,"数据不存在"), - METHOD_ARGUMENT_NOT_VALID(2005,"数据验证失败异常"), - VALIDATION_ERROR(2006,"参数验证失败"), - HANDLE_BIND_ERROR(2007,"参数绑定失败"), - MESSAGE_NOT_READABLE(2008,"参数解析失败"), - MISSING_REQUEST_HEADER(2009,"缺少请求头参数"), - NO_HANDLER_FOUND(2010,"Not Found"), - METHOD_NOT_SUPPORTED(2011,"不支持当前请求方法"), - MEDIA_TYPE_NOT_SUPPORTED(2012,"不支持当前媒体类型"), - MAX_UPLOAD_SIZE_EXCEEDED(2013,"文件上传-文件大小超过限制"), - NO_PERMISSION_FOR_THIS_OPERATION(1328, "暂无权限"), - UPLOAD_IMG_FORMAT_ERROR(2015,"上传图片格式错误"), - REQUEST_PARAMS_NULL_ERROR(2016,"请求参数空值异常,请检查后重试!"), - SERVER_DESERTION_ERROR(2017,"服务器开小差了....,请稍后再试!"), - FORM_SUBMISSION_REPETITION_ERROR(1360, "操作过于频繁,请稍后再试"), - LOGIN_PWD_ERROR(2218, "密码错误!"), - BLOCKED_ACCOUNT_ERROR(2219, "多次输人错误的密码,账户已被冻结!"), - LOGIN_IP_FORMAT_ERROR(2220, "IP地址格式错误!"), - BLOCKED_LOGIN_IP_ERROR(2221, "非法IP!"), - ERROR_2222(2222, "验证码错误!"), - ERROR_2223(2223, "验证码不存在或已过期!"), - - // 业务 - // 买家 - ERROR_NOT_FIND_BUYER_USER(3000, "买家信息不存在!"), - ERROR_EXIST_FIND_BUYER_USER(3001, "买家信息已存在!"), - ERROR_NOT_UPDATE_EXIST_ORDER_BUYER_USER(3002, "买家存在订单信息,不允许修改token和平台信息"), - ERROR_NOT_DEL_EXIST_ORDER_BUYER_USER(3003, "买家存在订单信息,不允许删除"), - - - // EXCEL - ERROR_NOT_FIND_EXCEL_USER(3100, "卖家信息不存在!"), - - - // 平台 - ERROR_NOT_FIND_PLAT_USER(3200, "平台信息不存在!"), - ERROR_EXITS_COMPANY_INFO(3201,"该平台下存在公司,不允许删除!"), - - // 公司 - ERROR_NOT_FIND_COMPANY(3300, "公司信息不存在!"), - ERROR_EXITS_CT_ORDER_INFO(3201,"该公司下存在订单信息,不允许删除!"), - - // 信用卡 - ERROR_NOT_FIND_CARD_INFO(3300, "信用卡信息不存在,或者已删除或异常!"), - ERROR_NOT_FIND_CARD(3301, "信用卡信息不存在!"), - - //VPN - ERROR_NOT_FIND_VPN(3300, "VPN信息不存在,或者已删除!"), - - //影刀任务信息 - ERROR_NOT_FIND_JOB(3400,"影刀任务信息不存在,或者已删除"), - ERROR_NOT_FIND_TASK(3401,"影刀应用信息异常, 请检查后重试!"), - - //应用信息Apply - ERROR_NOT_FIND_APPLY(3500,"应用信息不存在,或者已删除"), - - //影刀机器人信息 rebot - ERROR_NOT_FIND_REBOT(3600,"机器人信息不存在,或者已删除"), - ERROR_NOT_FIND_OR_OCCUPY(3601, "机器人不存在,或者已占用"), - - // 影刀回调 - ERROR_PARAM_NULL(3700, "影刀回调参数空值异常!"), - ERROR_CALLBACK_SIGN_NULL(3701, "影刀回调鉴权异常!"), - - - // 敦煌支付 - ERROR_DH_PAY_NOT_FIND_OR_SUCCESS(3800,"敦煌支付信息不存在,或已删除!"), - - // 刷单流程 - ERROR_NOT_FIND_CLICKFARMING_INFO(3900, "刷单信息不存在!"), - ERROR_DEL_CLICKFARMING_INFO(3901, "只有待执行的刷单信息才允许删除!"), - ERROR_CLICKFARMING_NOT_TOBE(3902, "刷单信息非待执行状态,请检查后重新操作!"), - ERROR_CLICKFARMING_NOT_SUPPLEMENT(3903, "仅支付成功失败状态才允许补录!"), - ERROR_CLICK_ORDER_NOT_COMMENT(3904, "仅刷单成功状态,才拥有订单信息!"), - - // 订单信息 - ERROR_NOT_FIND_CLICK_ORDER_INFO(4100, "订单信息不存在"), - ERROR_NOT_NULL_ERP_AUTH_TOKEN(4101, "鉴权信息不能为空!"), - ERROR_ERP_AUTH_TOKEN(4102, "鉴权信息错误,请检查后重试!"), - - // 应用 - ERROR_NOT_REPEAT_ID(4200, "应用ID存在重复!"), - ERROR_NOT_FIND_METHOD_NAME(4201, "不存在对应方法名称!"), - - // 浏览信息不存在 - ERROR_NOT_FIND_BROWSE(4300, "浏览信息不存在!"), - - // 敦煌加购 - ERROR_ADD_CAR_KEY_NULL(4400, "关键词类型-商品关键词属性不能为空"), - ERROR_ADD_CAR_LINK_NULL(4401, "链接类型-商品关键词属性不能为空"), - ERROR_ADD_CAR_GOODS_NULL(4403, "商品属性不能为空"), - ERROR_NOT_FIND_ADD_CAR_INFO(4404, "敦煌加购信息不存在,或者已删除或异常!"), - ERROR_DEL_ADD_CAR_INFO(4405, "只有待执行的刷单信息才允许删除!"), - ERROR_NOT_EDIT_ADD_CAR_INFO(4406, "敦煌加购信息仅带执行才允许修改!"), - ERROR_NOT_WELL_RECEIVED_ADD_CAR_INFO(4407, "敦煌加购信息仅抓单成功才允许评论!"); - - private int code; - - private String desc; - /** 初始化 */ - ErrorCodeEnum(int code, String desc) { - this.code = code; - this.desc = desc; - } - /** 获取错误状态码 */ - public int getCode() { - return code; - } - /** 设置错误状态码 */ - public void setCode(int code) { - this.code = code; - } - /** 获取错误描述 */ - public String getDesc() { -// String language = RequestHolder.getLanguage(); -// String message = Convert.toStr(PropertiesUtil.getByCode(code, language), desc); - return desc; - } - /** 设置错误描述 */ - public void setDesc(String desc) { - this.desc = desc; - } - -} diff --git a/wjcy-common/src/main/java/me/zhengjie/exception/BadConfigurationException.java b/wjcy-common/src/main/java/me/zhengjie/exception/BadConfigurationException.java deleted file mode 100644 index ede3691..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/exception/BadConfigurationException.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2019-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.exception; - -/** - * 统一关于错误配置信息 异常 - * - * @author: liaojinlong - * @date: 2020/6/10 18:06 - */ -public class BadConfigurationException extends RuntimeException { - /** - * Constructs a new runtime exception with {@code null} as its - * detail message. The cause is not initialized, and may subsequently be - * initialized by a call to {@link #initCause}. - */ - public BadConfigurationException() { - super(); - } - - /** - * Constructs a new runtime exception with the specified detail message. - * The cause is not initialized, and may subsequently be initialized by a - * call to {@link #initCause}. - * - * @param message the detail message. The detail message is saved for - * later retrieval by the {@link #getMessage()} method. - */ - public BadConfigurationException(String message) { - super(message); - } - - /** - * Constructs a new runtime exception with the specified detail message and - * cause.

Note that the detail message associated with - * {@code cause} is not automatically incorporated in - * this runtime exception's detail message. - * - * @param message the detail message (which is saved for later retrieval - * by the {@link #getMessage()} method). - * @param cause the cause (which is saved for later retrieval by the - * {@link #getCause()} method). (A {@code null} value is - * permitted, and indicates that the cause is nonexistent or - * unknown.) - * @since 1.4 - */ - public BadConfigurationException(String message, Throwable cause) { - super(message, cause); - } - - /** - * Constructs a new runtime exception with the specified cause and a - * detail message of {@code (cause==null ? null : cause.toString())} - * (which typically contains the class and detail message of - * {@code cause}). This constructor is useful for runtime exceptions - * that are little more than wrappers for other throwables. - * - * @param cause the cause (which is saved for later retrieval by the - * {@link #getCause()} method). (A {@code null} value is - * permitted, and indicates that the cause is nonexistent or - * unknown.) - * @since 1.4 - */ - public BadConfigurationException(Throwable cause) { - super(cause); - } - - /** - * Constructs a new runtime exception with the specified detail - * message, cause, suppression enabled or disabled, and writable - * stack trace enabled or disabled. - * - * @param message the detail message. - * @param cause the cause. (A {@code null} value is permitted, - * and indicates that the cause is nonexistent or unknown.) - * @param enableSuppression whether or not suppression is enabled - * or disabled - * @param writableStackTrace whether or not the stack trace should - * be writable - * @since 1.7 - */ - protected BadConfigurationException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/exception/BadRequestException.java b/wjcy-common/src/main/java/me/zhengjie/exception/BadRequestException.java deleted file mode 100644 index 3501adc..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/exception/BadRequestException.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.exception; - -import lombok.Getter; -import me.zhengjie.error.ErrorCodeEnum; -import org.springframework.http.HttpStatus; -import static org.springframework.http.HttpStatus.BAD_REQUEST; - -/** - * @author Zheng Jie - * @date 2018-11-23 - * 统一异常处理 - */ -@Getter -public class BadRequestException extends RuntimeException{ - - - private Integer status = BAD_REQUEST.value(); - - public BadRequestException(String msg){ - super(msg); - } - - public BadRequestException(HttpStatus status,String msg){ - super(msg); - this.status = status.value(); - } - public BadRequestException(Integer status,String msg){ - super(msg); - this.status = status; - } - public BadRequestException(ErrorCodeEnum errorCodeEnum){ - super(errorCodeEnum.getDesc()); - this.status = errorCodeEnum.getCode(); - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/exception/EntityExistException.java b/wjcy-common/src/main/java/me/zhengjie/exception/EntityExistException.java deleted file mode 100644 index 03f9bf2..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/exception/EntityExistException.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.exception; - -import org.springframework.util.StringUtils; - -/** - * @author Zheng Jie - * @date 2018-11-23 - */ -public class EntityExistException extends RuntimeException { - - public EntityExistException(Class clazz, String field, String val) { - super(EntityExistException.generateMessage(clazz.getSimpleName(), field, val)); - } - - private static String generateMessage(String entity, String field, String val) { - return StringUtils.capitalize(entity) - + " with " + field + " "+ val + " existed"; - } -} \ No newline at end of file diff --git a/wjcy-common/src/main/java/me/zhengjie/exception/EntityNotFoundException.java b/wjcy-common/src/main/java/me/zhengjie/exception/EntityNotFoundException.java deleted file mode 100644 index bcdc956..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/exception/EntityNotFoundException.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.exception; - -import org.springframework.util.StringUtils; - -/** - * @author Zheng Jie - * @date 2018-11-23 - */ -public class EntityNotFoundException extends RuntimeException { - - public EntityNotFoundException(Class clazz, String field, String val) { - super(EntityNotFoundException.generateMessage(clazz.getSimpleName(), field, val)); - } - - private static String generateMessage(String entity, String field, String val) { - return StringUtils.capitalize(entity) - + " with " + field + " "+ val + " does not exist"; - } -} \ No newline at end of file diff --git a/wjcy-common/src/main/java/me/zhengjie/exception/handler/ApiError.java b/wjcy-common/src/main/java/me/zhengjie/exception/handler/ApiError.java deleted file mode 100644 index 5112730..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/exception/handler/ApiError.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.exception.handler; - -import com.fasterxml.jackson.annotation.JsonFormat; -import lombok.Data; -import java.time.LocalDateTime; - -/** - * @author Zheng Jie - * @date 2018-11-23 - */ -@Data -class ApiError { - - private Integer status = 400; - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - private LocalDateTime timestamp; - private String message; - - private ApiError() { - timestamp = LocalDateTime.now(); - } - - public static ApiError error(String message){ - ApiError apiError = new ApiError(); - apiError.setMessage(message); - return apiError; - } - - public static ApiError error(Integer status, String message){ - ApiError apiError = new ApiError(); - apiError.setStatus(status); - apiError.setMessage(message); - return apiError; - } -} - - diff --git a/wjcy-common/src/main/java/me/zhengjie/exception/handler/GlobalExceptionHandler.java b/wjcy-common/src/main/java/me/zhengjie/exception/handler/GlobalExceptionHandler.java deleted file mode 100644 index 4561bae..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/exception/handler/GlobalExceptionHandler.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.exception.handler; - -import cn.hutool.core.util.ObjectUtil; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.dto.Dto; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.exception.EntityExistException; -import me.zhengjie.exception.EntityNotFoundException; -import me.zhengjie.utils.ThrowableUtil; -import org.springframework.http.converter.HttpMessageNotReadableException; -import org.springframework.security.access.AccessDeniedException; -import org.springframework.security.authentication.BadCredentialsException; -import org.springframework.validation.BindException; -import org.springframework.validation.FieldError; -import org.springframework.validation.ObjectError; -import org.springframework.web.HttpMediaTypeNotSupportedException; -import org.springframework.web.HttpRequestMethodNotSupportedException; -import org.springframework.web.bind.MethodArgumentNotValidException; -import org.springframework.web.bind.MissingRequestHeaderException; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.RestControllerAdvice; -import org.springframework.web.multipart.MaxUploadSizeExceededException; -import org.springframework.web.servlet.NoHandlerFoundException; - -import javax.annotation.Resource; -import javax.validation.ValidationException; -import java.util.List; - -import static me.zhengjie.error.ErrorCodeEnum.*; -import static me.zhengjie.error.ErrorCodeEnum.MAX_UPLOAD_SIZE_EXCEEDED; - -/** - * @author Zheng Jie - * @date 2018-11-23 - */ -@Slf4j -@RestControllerAdvice -public class GlobalExceptionHandler { - - /** - * 不允许访问的异常 - */ - @ExceptionHandler(AccessDeniedException.class) - public Dto accessDeniedException(Throwable e) { - // 打印堆栈信息 - log.error(NO_PERMISSION_FOR_THIS_OPERATION.getCode()+ThrowableUtil.getStackTrace(e)); - return Dto.getInstance(NO_PERMISSION_FOR_THIS_OPERATION); - } - - /** - * 处理所有不可知的异常 - */ - @ExceptionHandler(Throwable.class) - public Dto handleException(Throwable e) { - // 打印堆栈信息 - log.error(UNKNOWN_ERROR.getCode()+ThrowableUtil.getStackTrace(e)); - return Dto.getInstance(UNKNOWN_ERROR); - } - - /** - * BadCredentialsException - */ - @ExceptionHandler(BadCredentialsException.class) - public Dto badCredentialsException(BadCredentialsException e) { - // 打印堆栈信息 - log.error(BAD_CREDENTIALS.getCode()+ThrowableUtil.getStackTrace(e)); - return Dto.getInstance(BAD_CREDENTIALS); - } - - /** - * 处理自定义异常 - */ - @ExceptionHandler(value = BadRequestException.class) - public Dto badRequestException(BadRequestException e) { - // 打印堆栈信息 - log.error(e.getStatus()+ThrowableUtil.getStackTrace(e)); - Dto dto = Dto.returnResult(false); - dto.setCode(e.getStatus()); - dto.setMessage(e.getMessage()); - return dto; - } - - /** - * 处理 EntityExist - */ - @ExceptionHandler(value = EntityExistException.class) - public Dto entityExistException(EntityExistException e) { - // 打印堆栈信息 - log.error(ENTITY_EXIST.getCode()+ThrowableUtil.getStackTrace(e)); - return Dto.getInstance(ENTITY_EXIST); - } - - /** - * 处理 EntityNotFound - */ - @ExceptionHandler(value = EntityNotFoundException.class) - public Dto entityNotFoundException(EntityNotFoundException e) { - // 打印堆栈信息 - log.error(ENTITY_NOT_FOUND.getCode()+ThrowableUtil.getStackTrace(e)); - return Dto.getInstance(ENTITY_NOT_FOUND); - } - - /** - * 处理所有接口数据验证异常 - */ - @ExceptionHandler(MethodArgumentNotValidException.class) - public Dto handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { - // 打印堆栈信息 - log.error(ThrowableUtil.getStackTrace(e)); - StringBuffer sbf = new StringBuffer(); - List allErrors = e.getBindingResult().getAllErrors(); - for (ObjectError allError : allErrors) { - if (allError instanceof FieldError) { - FieldError fieldError = (FieldError)allError; - sbf.append("["+fieldError.getField() + ":" + fieldError.getDefaultMessage() + "] "); - } - } - Dto dto = Dto.getInstance(METHOD_ARGUMENT_NOT_VALID); - if (ObjectUtil.isNotEmpty(sbf)) { - dto.setMessage(sbf.toString()); - } - return dto; - } - - @ExceptionHandler(ValidationException.class) - @ResponseBody - public Dto handleValidationException(ValidationException e) { - log.error(VALIDATION_ERROR.getCode()+ThrowableUtil.getStackTrace(e)); - return Dto.getInstance(VALIDATION_ERROR); - } - - @ExceptionHandler(BindException.class) - @ResponseBody - public Dto handleBindException(BindException e) { - log.error(HANDLE_BIND_ERROR.getCode()+ThrowableUtil.getStackTrace(e)); - return Dto.getInstance(HANDLE_BIND_ERROR); - } - - @ExceptionHandler(HttpMessageNotReadableException.class) - @ResponseBody - public Dto handleHttpMessageNotReadableException(HttpMessageNotReadableException e) { - log.error(MESSAGE_NOT_READABLE.getCode()+ThrowableUtil.getStackTrace(e)); - return Dto.getInstance(MESSAGE_NOT_READABLE); - } - - @ExceptionHandler(MissingRequestHeaderException.class) - @ResponseBody - public Dto missingRequestHeaderException(MissingRequestHeaderException e) { - log.error(MISSING_REQUEST_HEADER.getCode()+ThrowableUtil.getStackTrace(e)); - return Dto.getInstance(MISSING_REQUEST_HEADER); - } - - @ExceptionHandler(NoHandlerFoundException.class) - @ResponseBody - public Dto noHandlerFoundException(NoHandlerFoundException e) { - log.error(NO_HANDLER_FOUND.getCode()+ThrowableUtil.getStackTrace(e)); - return Dto.getInstance(NO_HANDLER_FOUND); - } - - @ExceptionHandler(HttpRequestMethodNotSupportedException.class) - @ResponseBody - public Dto handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) { - log.error(METHOD_NOT_SUPPORTED.getCode()+ThrowableUtil.getStackTrace(e)); - return Dto.getInstance(METHOD_NOT_SUPPORTED); - } - - @ExceptionHandler(HttpMediaTypeNotSupportedException.class) - @ResponseBody - public Dto handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e) { - log.error(MEDIA_TYPE_NOT_SUPPORTED.getCode()+ThrowableUtil.getStackTrace(e)); - return Dto.getInstance(MEDIA_TYPE_NOT_SUPPORTED); - } - - @ExceptionHandler(value = MaxUploadSizeExceededException.class) - @ResponseBody - public Dto maxUploadSizeExceededException(MaxUploadSizeExceededException e) { - log.error(MAX_UPLOAD_SIZE_EXCEEDED.getCode()+ThrowableUtil.getStackTrace(e)); - return Dto.getInstance(MAX_UPLOAD_SIZE_EXCEEDED); - } - -} diff --git a/wjcy-common/src/main/java/me/zhengjie/mybatis/LambdaQueryWrapperImpl.java b/wjcy-common/src/main/java/me/zhengjie/mybatis/LambdaQueryWrapperImpl.java deleted file mode 100644 index d1911cb..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/mybatis/LambdaQueryWrapperImpl.java +++ /dev/null @@ -1,29 +0,0 @@ -package me.zhengjie.mybatis; - -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; - -/* - * - * @Description - * @Date 2021/12/6 - * @Author zeng - */ -public class LambdaQueryWrapperImpl extends LambdaQueryWrapper { - - private String name; - - @Override - public String getCustomSqlSegment() { - String customSqlSegment = super.getCustomSqlSegment(); - if (ObjectUtil.isNotEmpty(name)) { - customSqlSegment = customSqlSegment.replaceAll("ew.", name + "."); - } - return customSqlSegment; - } - - public void setName(String name) { - this.name = name; - } - -} diff --git a/wjcy-common/src/main/java/me/zhengjie/service/CtApplyService.java b/wjcy-common/src/main/java/me/zhengjie/service/CtApplyService.java deleted file mode 100644 index c67a12d..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/CtApplyService.java +++ /dev/null @@ -1,42 +0,0 @@ -package me.zhengjie.service; - -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.service.IService; -import me.zhengjie.entity.CtApply; -import me.zhengjie.service.vo.CtApplyListVO; -import me.zhengjie.utils.PageUtils; - -import java.util.List; - -/** - * 影刀应用信息(CtApply)表服务接口 - * - * @author rch - * @since 2022-07-23 - */ -public interface CtApplyService extends IService { - - /** - * 分页查询 - * @param page - * @param ew - * @return PageUtils - */ - PageUtils searchPageList(IPage page, Wrapper ew); - - /** - * 查询所有应用信息 - * @return LIST - */ - List getAllApplyName(); - - /** - * 根据方法应用对应的TaskName和Method查询应用信息 - * @param taskName - * @param method - * @return - */ - CtApply getApplyByTaskAndMethod(String taskName, String method); -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/CtBrowseService.java b/wjcy-common/src/main/java/me/zhengjie/service/CtBrowseService.java deleted file mode 100644 index b0b8401..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/CtBrowseService.java +++ /dev/null @@ -1,41 +0,0 @@ -package me.zhengjie.service; - -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.service.IService; -import me.zhengjie.entity.CtBrowse; -import me.zhengjie.service.vo.CtBrowseDetailVO; -import me.zhengjie.service.vo.CtBrowseListVO; -import me.zhengjie.utils.PageUtils; - -/** - * 浏览收藏(CtBrowse)表服务接口 - * - * @author rch - * @since 2022-11-04 09:45:32 - */ -public interface CtBrowseService extends IService { - - /** - * 分页查询 - * @param page - * @param ew - * @return - */ - PageUtils searchPageList(IPage page, Wrapper ew); - - /** - * 获取好评刷单信息-加锁 - * @param id - * @return - */ - CtBrowse getByIdLock(Long id); - - /** - * 根据id获取详情 - * @param id - * @return - */ - CtBrowseDetailVO getBrowseDetailById(Long id); -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/CtBuyerService.java b/wjcy-common/src/main/java/me/zhengjie/service/CtBuyerService.java deleted file mode 100644 index b6c71d9..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/CtBuyerService.java +++ /dev/null @@ -1,50 +0,0 @@ -package me.zhengjie.service; - -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.service.IService; -import me.zhengjie.entity.CtBuyer; -import me.zhengjie.service.vo.CtBuyerDetailVO; -import me.zhengjie.service.vo.CtBuyerListVO; -import me.zhengjie.utils.PageUtils; - -import java.util.List; -import java.util.Map; - -/** - * 买家表(CtBuyer)表服务接口 - * - * @author rch - * @since 2022-06-22 - */ -public interface CtBuyerService extends IService { - - /** - * 分页查询买家信息 - * @param page - * @param ew - * @return - */ - PageUtils searchPageList(IPage page, Wrapper ew); - - /** - * 根据Id获取详情信息 - * @param id - * @return - */ - CtBuyerDetailVO getDetailById(Long id); - - List getAllAccount(); - - String getPwdByName(String name); - - CtBuyer getBuyerOccupyStatusLock(String buyerName); - - /** - * 根据买家账号 返回存在的买家信息 - * @param buyerAccountList - * @return - */ - Map getBuyerList(List buyerAccountList); -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/CtCardService.java b/wjcy-common/src/main/java/me/zhengjie/service/CtCardService.java deleted file mode 100644 index 6727e2e..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/CtCardService.java +++ /dev/null @@ -1,26 +0,0 @@ -package me.zhengjie.service; - -import com.baomidou.mybatisplus.extension.service.IService; -import me.zhengjie.entity.CtCard; -import me.zhengjie.entity.CtCardInfo; - -import java.util.List; - -/** - * 信用卡信息(CtCard)表服务接口 - * - * @author rch - * @since 2022-07-07 - */ -public interface CtCardService extends IService { - - List getNumberList(); - - /** - * 根据信用卡号查询信用卡信息 - * @param number - * @return ctCardInfo(id,number) - */ - List getCardInfoByNumber(List number); -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/CtClickFarmingService.java b/wjcy-common/src/main/java/me/zhengjie/service/CtClickFarmingService.java deleted file mode 100644 index f88d31f..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/CtClickFarmingService.java +++ /dev/null @@ -1,36 +0,0 @@ -package me.zhengjie.service; - -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.service.IService; -import me.zhengjie.entity.CtBuyerClickSuccess; -import me.zhengjie.entity.CtClickFarmYdParams; -import me.zhengjie.entity.CtClickFarming; -import me.zhengjie.service.vo.CtClickFarmEditDetailVO; -import me.zhengjie.service.vo.CtClickFarmingDetailVO; -import me.zhengjie.service.vo.CtClickFarmingVO; -import me.zhengjie.utils.PageUtils; - -import java.util.List; - -/** - * 刷单Excel信息(CtClickFarming)表服务接口 - * - * @author rch - * @since 2022-08-16 - */ -public interface CtClickFarmingService extends IService { - - PageUtils searchPageList(IPage page, Wrapper ew); - - CtClickFarming getByIdLock(Long id); - - CtClickFarmEditDetailVO getEditDetailById(Long id); - - CtClickFarmingDetailVO getDetailById(Long id); - - List ruleGetCtBuyer(String buyerAccount, String country, String shopName); - - CtClickFarmYdParams getCtClickFarmYdParams(Long valueOf); -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/CtClickOrderService.java b/wjcy-common/src/main/java/me/zhengjie/service/CtClickOrderService.java deleted file mode 100644 index 30b471c..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/CtClickOrderService.java +++ /dev/null @@ -1,65 +0,0 @@ -package me.zhengjie.service; - -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.service.IService; -import me.zhengjie.entity.CtClickFarmingOrderInfo; -import me.zhengjie.entity.CtClickOrder; -import me.zhengjie.service.vo.CtClickOrderDetailVO; -import me.zhengjie.service.vo.CtClickOrderListVO; -import me.zhengjie.utils.PageUtils; - -import java.util.List; - -/** - * 刷单-订单信息(CtClickOrder)表服务接口 - * - * @author rch - * @since 2022-09-14 - */ -public interface CtClickOrderService extends IService { - - /** - * 返回实际存在的订单id - * @param importOrderIdList - * @return - */ - List getOrderId(List importOrderIdList); - - /** - * 分页查询 - * @param page - * @param ew - * @return - */ - PageUtils searchPageList(IPage page, Wrapper ew); - - /** - * 手动补录刷单信息对应的订单信息 - * @param clickFarmingId - * @param ctClickOrder - */ - Boolean supplement(Long clickFarmingId, CtClickOrder ctClickOrder); - - /** - * 根据订单id 获取刷单订单详情信息 - * @param orderId - * @return - */ - CtClickFarmingOrderInfo getClickFarmOrderById(Long orderId); - - /** - * 悲观锁根据id获取刷单订单信息 - * @param valueOf - * @return - */ - CtClickOrder getByIdLock(Long valueOf); - - /** - * 根据订单Id获取订单详情 - * @param id - * @return - */ - CtClickOrderDetailVO getClickOrderDetailById(Long id); -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/CtCompanyService.java b/wjcy-common/src/main/java/me/zhengjie/service/CtCompanyService.java deleted file mode 100644 index 10d4c04..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/CtCompanyService.java +++ /dev/null @@ -1,34 +0,0 @@ -package me.zhengjie.service; - -import com.baomidou.mybatisplus.extension.service.IService; -import me.zhengjie.entity.CtCompany; -import me.zhengjie.entity.CtCompanyInfo; - -import java.util.List; -import java.util.Map; - -/** - * 公司信息(CtCompany)表服务接口 - * - * @author makejava - * @since 2022-06-23 10:37:44 - */ -public interface CtCompanyService extends IService { - - /** - * 根据公司名字 获取公司信息 - * @param name - * @return - */ - List getByNmae(List name); - - List getCompanyList(); - - /** - * 根据名称返回存在的公司信息 Map形式 key:id value:公司名称 - * @param platNameList - * @return - */ - Map getNameList(List platNameList); -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/CtDhPayService.java b/wjcy-common/src/main/java/me/zhengjie/service/CtDhPayService.java deleted file mode 100644 index 22612f4..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/CtDhPayService.java +++ /dev/null @@ -1,29 +0,0 @@ -package me.zhengjie.service; - -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.service.IService; -import me.zhengjie.entity.CtDhPay; -import me.zhengjie.service.vo.CtDhPayListVO; -import me.zhengjie.utils.PageUtils; - -/** - * 平台信息(CtDyPay)表服务接口 - * - * @author rch - * @since 2022-07-28 - */ -public interface CtDhPayService extends IService { - - PageUtils searchPageList(IPage page, Wrapper ew); - - void toPay(); - - /** - * 调用支付接口 - * @param ctDhPay - * @return - */ - public Boolean payOrderApi(CtDhPay ctDhPay); -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/CtExcelImportInfoService.java b/wjcy-common/src/main/java/me/zhengjie/service/CtExcelImportInfoService.java deleted file mode 100644 index 9f2ba5a..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/CtExcelImportInfoService.java +++ /dev/null @@ -1,23 +0,0 @@ -package me.zhengjie.service; - -import com.baomidou.mybatisplus.extension.service.IService; -import me.zhengjie.entity.CtExcelImportInfo; - -import java.io.IOException; - -/** - * Excel导入信息(CtExcelImportInfo)表服务接口 - * - * @author rch - * @since 2022-06-23 - */ -public interface CtExcelImportInfoService extends IService { - - /** - * Excel 数据导入Mysql - * - * TODO 先做一版批量导入的,如果导入过程错误先不考虑 - */ - void importExcel() throws IOException; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/CtExcelService.java b/wjcy-common/src/main/java/me/zhengjie/service/CtExcelService.java deleted file mode 100644 index a3d470b..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/CtExcelService.java +++ /dev/null @@ -1,15 +0,0 @@ -package me.zhengjie.service; - -import com.baomidou.mybatisplus.extension.service.IService; -import me.zhengjie.entity.CtExcel; - -/** - * Excel 导入信息(CtExcel)表服务接口 - * - * @author makejava - * @since 2022-06-23 10:37:44 - */ -public interface CtExcelService extends IService { - -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/CtOrderService.java b/wjcy-common/src/main/java/me/zhengjie/service/CtOrderService.java deleted file mode 100644 index 0bba1ec..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/CtOrderService.java +++ /dev/null @@ -1,31 +0,0 @@ -package me.zhengjie.service; - -import com.baomidou.mybatisplus.extension.service.IService; -import me.zhengjie.entity.CtExcelImportInfo; -import me.zhengjie.entity.CtOrder; -import org.springframework.stereotype.Service; - -/** - * (CtOrder)表服务接口 - * - * @author rch - * @since 2022-07-01 - */ -@Service -public interface CtOrderService extends IService { - - /** - * Excel 数据转换存储到订单表里 Order 一对多 - */ - void excelToOrder(); - - Boolean buyOrderApi(CtExcelImportInfo ctExcelImportInfo); - - /** - * 订单支付 - */ - void toPay(); - - Boolean payOrderApi(CtOrder ctOrder); -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/CtPlatformService.java b/wjcy-common/src/main/java/me/zhengjie/service/CtPlatformService.java deleted file mode 100644 index 37611dd..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/CtPlatformService.java +++ /dev/null @@ -1,24 +0,0 @@ -package me.zhengjie.service; - -import com.baomidou.mybatisplus.extension.service.IService; -import me.zhengjie.entity.CtPlatform; - -import java.util.List; -import java.util.Map; - -/** - * 平台信息(CtPlatform)表服务接口 - * - * @author makejava - * @since 2022-06-23 10:37:44 - */ -public interface CtPlatformService extends IService { - - /** - * 返回存在的对应名称的平台信息名称 - * @param platNameList - * @return - */ - Map getNameList(List platNameList); -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/CtRebotService.java b/wjcy-common/src/main/java/me/zhengjie/service/CtRebotService.java deleted file mode 100644 index b784caf..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/CtRebotService.java +++ /dev/null @@ -1,63 +0,0 @@ -package me.zhengjie.service; - -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.service.IService; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.CtRebot; -import me.zhengjie.service.vo.CtRebotListVO; -import me.zhengjie.utils.PageUtils; -import org.springframework.data.convert.JodaTimeConverters; -import org.springframework.web.multipart.MultipartFile; - -import javax.servlet.http.HttpServletResponse; -import java.util.List; - -/** - * 影刀设备-机器人信息(CtRebot)表服务接口 - * - * @author rch - * @since 2022-07-23 - */ -public interface CtRebotService extends IService { - - CtRebot getByAccountNameLock(String accountName); - - /** - * 分页查询 影刀机器人信息 - * @param page - * @param wr - * @return PageUtils - */ - PageUtils searchPageList(IPage page, Wrapper wr); - - /** - * excel导入机器人信息 - * @param file - * @param response - * @return Dto - */ - Dto importRebot(MultipartFile file, HttpServletResponse response) throws Exception; - - /** - * 获取所有机器人名称 - * @return LIST - */ - List getAccountNameList(); - - /** - * 获取所有uuid信息 - * @return LIST - */ - List getClientUuidList(); - - /** - * 根据id和老状态 修改新状态 - * @param id - * @param newStatus - * @param oldStatus - * @return - */ - Boolean updateNewStatusByOldStatus(Long id, Integer newStatus, Integer oldStatus); -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/CtResponseOrderAddressService.java b/wjcy-common/src/main/java/me/zhengjie/service/CtResponseOrderAddressService.java deleted file mode 100644 index c639064..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/CtResponseOrderAddressService.java +++ /dev/null @@ -1,17 +0,0 @@ -package me.zhengjie.service; - -import com.baomidou.mybatisplus.extension.service.IService; -import me.zhengjie.entity.CtResponseOrderAddress; -import org.springframework.stereotype.Service; - -/** - * 下注成功订单响应收货地址信息(CtResponseOrderAddress)表服务接口 - * - * @author rch - * @since 2022-07-01 - */ -@Service -public interface CtResponseOrderAddressService extends IService { - -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/CtResponseOrderProductService.java b/wjcy-common/src/main/java/me/zhengjie/service/CtResponseOrderProductService.java deleted file mode 100644 index 956fb20..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/CtResponseOrderProductService.java +++ /dev/null @@ -1,17 +0,0 @@ -package me.zhengjie.service; - -import com.baomidou.mybatisplus.extension.service.IService; -import me.zhengjie.entity.CtResponseOrderProduct; -import org.springframework.stereotype.Service; - -/** - * 下单订单响应产品信息(CtResponseOrderProduct)表服务接口 - * - * @author rch - * @since 2022-07-01 - */ -@Service -public interface CtResponseOrderProductService extends IService { - -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/CtResponseOrderService.java b/wjcy-common/src/main/java/me/zhengjie/service/CtResponseOrderService.java deleted file mode 100644 index 99d8a84..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/CtResponseOrderService.java +++ /dev/null @@ -1,17 +0,0 @@ -package me.zhengjie.service; - -import com.baomidou.mybatisplus.extension.service.IService; -import me.zhengjie.entity.CtResponseOrder; -import org.springframework.stereotype.Service; - -/** - * 下单成功响应订单商品信息(CtResponseOrder)表服务接口 - * - * @author rch - * @since 2022-07-01 - */ -@Service -public interface CtResponseOrderService extends IService { - -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/CtVpnService.java b/wjcy-common/src/main/java/me/zhengjie/service/CtVpnService.java deleted file mode 100644 index d4327c2..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/CtVpnService.java +++ /dev/null @@ -1,24 +0,0 @@ -package me.zhengjie.service; - -import com.baomidou.mybatisplus.extension.service.IService; -import me.zhengjie.entity.CtVpn; -import me.zhengjie.entity.CtVpnInfo; - -import java.util.List; - -/** - * VPN信息表(CtVpn)表服务接口 - * - * @author rch - * @since 2022-07-07 - */ -public interface CtVpnService extends IService { - - List getIpList(); - - /** - * 根据ip地址查询vpn信息(id、ip地址) - */ - List getVpnInfoByIp(List ipAddress); -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/DhAddCarOrderService.java b/wjcy-common/src/main/java/me/zhengjie/service/DhAddCarOrderService.java deleted file mode 100644 index 861fc33..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/DhAddCarOrderService.java +++ /dev/null @@ -1,41 +0,0 @@ -package me.zhengjie.service; - -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.service.IService; -import me.zhengjie.entity.DhAddCarOrder; -import me.zhengjie.service.vo.dhcarorder.DhAddCarOrderListVO; -import me.zhengjie.service.vo.dhcarorder.DhCarOrderParamsVO; -import me.zhengjie.utils.PageUtils; - -/** - * 敦煌-加购物车-订单(DhAddCarOrder)表服务接口 - * - * @author rch - * @since 2022-11-17 09:11:59 - */ -public interface DhAddCarOrderService extends IService { - - /** - * 加锁获取敦煌购物车抓单信息 - * @param valueOf - * @return - */ - DhAddCarOrder getByIdLock(Long valueOf); - - /** - * 分页查询 - * @param page - * @param ew - * @return - */ - PageUtils searchPageList(IPage page, Wrapper ew); - - /** - * 获取敦煌加购-好评影刀参数 - * @param valueOf - * @return - */ - DhCarOrderParamsVO getYdParams(Long valueOf); -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/DhAddCarService.java b/wjcy-common/src/main/java/me/zhengjie/service/DhAddCarService.java deleted file mode 100644 index 59c02b5..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/DhAddCarService.java +++ /dev/null @@ -1,49 +0,0 @@ -package me.zhengjie.service; - -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.service.IService; -import me.zhengjie.entity.DhAddCar; -import me.zhengjie.service.vo.dhaddcar.DhAddCarVO; -import me.zhengjie.service.vo.dhaddcar.DhAddCarListVO; -import me.zhengjie.service.vo.dhaddcar.DhAddCarYdParamsVO; -import me.zhengjie.utils.PageUtils; - -/** - * 敦煌加入购物车(DhAddCar)表服务接口 - * - * @author makejava - * @since 2022-11-17 09:11:55 - */ -public interface DhAddCarService extends IService { - - /** - * 分页查询 - * @param page - * @param ew - * @return - */ - PageUtils searchPageList(IPage page, Wrapper ew); - - /** - * 根据id获取加购信息 - * @param id - * @return - */ - DhAddCarVO getDetailById(Long id); - - /** - * 根据id加悲观锁查询 - * @param id - * @return - */ - DhAddCar getByIdLock(Long id); - - /** - * 拼接影刀参数 - * @param id - * @return - */ - DhAddCarYdParamsVO getAddCarYdParams(Long id); -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/DhCarGoodsService.java b/wjcy-common/src/main/java/me/zhengjie/service/DhCarGoodsService.java deleted file mode 100644 index 7546ef4..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/DhCarGoodsService.java +++ /dev/null @@ -1,15 +0,0 @@ -package me.zhengjie.service; - -import com.baomidou.mybatisplus.extension.service.IService; -import me.zhengjie.entity.DhCarGoods; - -/** - * 敦煌-加入购物车商品信息(DhCarGoods)表服务接口 - * - * @author makejava - * @since 2022-11-17 09:12:03 - */ -public interface DhCarGoodsService extends IService { - -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/FileUploadService.java b/wjcy-common/src/main/java/me/zhengjie/service/FileUploadService.java deleted file mode 100644 index e7af6ee..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/FileUploadService.java +++ /dev/null @@ -1,20 +0,0 @@ -package me.zhengjie.service; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.List; - -/** - *

- * 图片上传服务 - *

- * - * @Author xx - * @Date 2021/7/26 - **/ -public interface FileUploadService { - - List uploadify(HttpServletRequest request, HttpServletResponse response) - throws IOException; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/service/LoginIpService.java b/wjcy-common/src/main/java/me/zhengjie/service/LoginIpService.java deleted file mode 100644 index a0bfcad..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/LoginIpService.java +++ /dev/null @@ -1,58 +0,0 @@ -package me.zhengjie.service; - -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.service.IService; -import me.zhengjie.entity.LoginIp; -import me.zhengjie.utils.PageUtils; - -import java.util.List; - -/** - * (LoginIp)表服务接口 - * - * @author zeng - * @since 2022-03-21 14:07:01 - */ -public interface LoginIpService extends IService { - - String LOGIN_IP_LIST = "LOGIN_IP_LIST"; - - /** - * 获取IP列表 - * @author: zeng - * @param iPage - */ - PageUtils getList(IPage iPage); - - /** - * 新增 - * @author: zeng - */ - boolean addIp(LoginIp ip); - - /** - * 查询所有有效白名单IP段 - * @return - */ - List getAll(); - - /** - * 编辑 - * @author: zeng - */ - boolean updateIp(LoginIp ip); - - /** - * 删除 - * @author: zeng - */ - boolean deleteIp(Integer id); - - /** - * 是否是白名单 - * @author: zeng - */ - boolean whiteListFlag(String ip); - -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/SettingSiteService.java b/wjcy-common/src/main/java/me/zhengjie/service/SettingSiteService.java deleted file mode 100644 index a3a2097..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/SettingSiteService.java +++ /dev/null @@ -1,25 +0,0 @@ -package me.zhengjie.service; - -import com.baomidou.mybatisplus.extension.service.IService; -import me.zhengjie.entity.CtSettingSite; - -/** - * 站点配置(CtSettingSite)表服务接口 - * - * @author xxs - * @since 2021-11-17 - */ -public interface SettingSiteService extends IService { - - String getValue(String key); - - boolean saveOrUpdateByKey(String key, String value); - - /** - * Google认证器开关 - * @auth xxs - * @return - */ - Boolean getGooleAuthSwitch(); -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/SysQuartzLogService.java b/wjcy-common/src/main/java/me/zhengjie/service/SysQuartzLogService.java deleted file mode 100644 index 0b56c21..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/SysQuartzLogService.java +++ /dev/null @@ -1,21 +0,0 @@ -package me.zhengjie.service; - -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.service.IService; -import me.zhengjie.entity.SysQuartzJob; -import me.zhengjie.entity.SysQuartzLog; -import me.zhengjie.service.vo.SysQuartzLogListVO; -import me.zhengjie.utils.PageUtils; - -/** - * 定时任务(SysQuartzJob)表服务接口 - * - * @author rch - * @since 2022-07-20 - */ -public interface SysQuartzLogService extends IService { - - PageUtils searchPageList(IPage page, Wrapper wrapper); -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/YdQuartzService.java b/wjcy-common/src/main/java/me/zhengjie/service/YdQuartzService.java deleted file mode 100644 index 619bdf5..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/YdQuartzService.java +++ /dev/null @@ -1,74 +0,0 @@ -package me.zhengjie.service; - -import me.zhengjie.entity.quartz.JobQueryByUuidReturn; -import me.zhengjie.service.redission.LockCallBack; - -/** - * 影刀定时任务Service - * - * @author rch - * @since 2022-08-01 - */ -public interface YdQuartzService{ - - Object executeOnLock(String lockKey, long time, long timeout, LockCallBack callBack) throws Exception; - - public String exec(String str) throws Exception; - - - /** - * 刷单 任务执行逻辑 - * @param str - * @return - * @throws Exception - */ - public Boolean clickFarmExec(String str) throws Exception; - - /** - * 敦煌加购 任务执行逻辑 - * @param str - * @return - * @throws Exception - */ - public Boolean addCarExec(String str) throws Exception; - - - /** - * 敦煌-加购-抓单 - * @param str - * @return - * @throws Exception - */ - public Boolean catchOrderExec(String str) throws Exception; - - public JobQueryByUuidReturn queryJobUuid(String uuid, String accessKeyId, String accessKeySecret); - - /** - * 刷单任务-补录(有订单信息-支付失败) - * @param str - * @return - */ - Boolean clickFarmSuppleMentExec(String str) throws Exception; - - /** - * 敦煌 - * @param str - * @return - * @throws Exception - */ - public Object dhWellReceivedExec(String str) throws Exception; - /** - * 好评 - * @param str - * @return - */ - Object wellReceivedExec(String str) throws Exception; - - /** - * 浏览收藏 - * @param str - * @return - */ - Object browseTaskExec(String str) throws Exception; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtApplyServiceImpl.java b/wjcy-common/src/main/java/me/zhengjie/service/impl/CtApplyServiceImpl.java deleted file mode 100644 index c0b0190..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtApplyServiceImpl.java +++ /dev/null @@ -1,44 +0,0 @@ -package me.zhengjie.service.impl; - -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import me.zhengjie.dao.CtApplyDao; -import me.zhengjie.entity.CtApply; -import me.zhengjie.service.CtApplyService; -import me.zhengjie.service.vo.CtApplyListVO; -import me.zhengjie.utils.PageUtils; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; - -/** - * 影刀应用信息(CtApply)表服务实现类 - * - * @author rch - * @since 2022-07-23 - */ -@Service -public class CtApplyServiceImpl extends ServiceImpl implements CtApplyService { - - @Resource - private CtApplyDao ctApplyDao; - - @Override - public PageUtils searchPageList(IPage page, Wrapper ew) { - ctApplyDao.searchPageList(page, ew); - return new PageUtils<>(page.getTotal(),page.getRecords()); - } - - @Override - public List getAllApplyName() { - return ctApplyDao.getAllApplyName(); - } - - @Override - public CtApply getApplyByTaskAndMethod(String taskName, String method) { - return ctApplyDao.getApplyByTaskAndMethod(taskName, method); - } -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtBrowseServiceImpl.java b/wjcy-common/src/main/java/me/zhengjie/service/impl/CtBrowseServiceImpl.java deleted file mode 100644 index 2b7896d..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtBrowseServiceImpl.java +++ /dev/null @@ -1,44 +0,0 @@ -package me.zhengjie.service.impl; - -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import me.zhengjie.dao.CtBrowseDao; -import me.zhengjie.entity.CtBrowse; -import me.zhengjie.service.CtBrowseService; -import me.zhengjie.service.vo.CtBrowseDetailVO; -import me.zhengjie.service.vo.CtBrowseListVO; -import me.zhengjie.utils.PageUtils; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; - -/** - * 浏览收藏(CtBrowse)表服务实现类 - * - * @author rch - * @since 2022-11-04 09:45:33 - */ -@Service -public class CtBrowseServiceImpl extends ServiceImpl implements CtBrowseService { - - @Resource - private CtBrowseDao ctBrowseDao; - - @Override - public PageUtils searchPageList(IPage page, Wrapper ew) { - ctBrowseDao.searchPageList(page, ew); - return new PageUtils(page.getTotal(), page.getRecords()); - } - - @Override - public CtBrowse getByIdLock(Long id) { - return ctBrowseDao.getByIdLock(id); - } - - @Override - public CtBrowseDetailVO getBrowseDetailById(Long id) { - return ctBrowseDao.getBrowseDetailById(id); - } -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtBuyerServiceImpl.java b/wjcy-common/src/main/java/me/zhengjie/service/impl/CtBuyerServiceImpl.java deleted file mode 100644 index 889a0ca..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtBuyerServiceImpl.java +++ /dev/null @@ -1,69 +0,0 @@ -package me.zhengjie.service.impl; - -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import me.zhengjie.dao.CtBuyerDao; -import me.zhengjie.entity.CtBuyer; -import me.zhengjie.service.CtBuyerService; -import me.zhengjie.service.vo.CtBuyerDetailVO; -import me.zhengjie.service.vo.CtBuyerListVO; -import me.zhengjie.utils.PageUtils; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * 买家表(CtBuyer)表服务实现类 - * - * @author rch - * @since 2022-06-22 - */ -@Service -public class CtBuyerServiceImpl extends ServiceImpl implements CtBuyerService { - - @Resource - private CtBuyerDao ctBuyerDao; - - @Override - public PageUtils searchPageList(IPage page, Wrapper ew) { - ctBuyerDao.searchPageList(page, ew); - return new PageUtils(page.getTotal(), page.getRecords()); - } - - @Override - public CtBuyerDetailVO getDetailById(Long id) { - return ctBuyerDao.getDetailById(id); - } - - @Override - public List getAllAccount(){ return ctBuyerDao.getAllAccount();} - - @Override - public String getPwdByName(String name) { - return ctBuyerDao.getPwdByName(name); - } - - @Override - public CtBuyer getBuyerOccupyStatusLock(String buyerName) { - return ctBuyerDao.getBuyerOccupyStatusLock(buyerName); - } - - @Override - public Map getBuyerList(List buyerAccountList) { - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.in("account", buyerAccountList); - - List ctBuyerList = list(queryWrapper); - if (ObjectUtil.isNotEmpty(ctBuyerList)) { - return ctBuyerList.stream().collect(Collectors.toMap(CtBuyer::getAccount, CtBuyer->CtBuyer)); - } - return null; - } -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtCardServiceImpl.java b/wjcy-common/src/main/java/me/zhengjie/service/impl/CtCardServiceImpl.java deleted file mode 100644 index e36521c..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtCardServiceImpl.java +++ /dev/null @@ -1,33 +0,0 @@ -package me.zhengjie.service.impl; - -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import me.zhengjie.dao.CtCardDao; -import me.zhengjie.entity.CtCard; -import me.zhengjie.entity.CtCardInfo; -import me.zhengjie.service.CtCardService; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; - -/** - * 信用卡信息(CtCard)表服务实现类 - * - * @author rch - * @since 2022-07-07 - */ -@Service -public class CtCardServiceImpl extends ServiceImpl implements CtCardService { - - @Resource - private CtCardDao ctCardDao; - - @Override - public List getNumberList() { - return ctCardDao.getNumberList(); - } - - @Override - public List getCardInfoByNumber(List number){ return ctCardDao.getCardInfoByNumber(number);} -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtClickFarmingServiceImpl.java b/wjcy-common/src/main/java/me/zhengjie/service/impl/CtClickFarmingServiceImpl.java deleted file mode 100644 index ea01a9d..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtClickFarmingServiceImpl.java +++ /dev/null @@ -1,62 +0,0 @@ -package me.zhengjie.service.impl; - -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import me.zhengjie.dao.CtClickFarmingDao; -import me.zhengjie.entity.CtBuyerClickSuccess; -import me.zhengjie.entity.CtClickFarmYdParams; -import me.zhengjie.entity.CtClickFarming; -import me.zhengjie.service.CtClickFarmingService; -import me.zhengjie.service.vo.CtClickFarmEditDetailVO; -import me.zhengjie.service.vo.CtClickFarmingDetailVO; -import me.zhengjie.service.vo.CtClickFarmingVO; -import me.zhengjie.utils.PageUtils; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; - -/** - * 刷单Excel信息(CtClickFarming)表服务实现类 - * - * @author rch - * @since 2022-08-16 - */ -@Service -public class CtClickFarmingServiceImpl extends ServiceImpl implements CtClickFarmingService { - - @Resource - private CtClickFarmingDao ctClickFarmingDao; - @Override - public PageUtils searchPageList(IPage page, Wrapper ew) { - ctClickFarmingDao.searchPageList(page, ew); - return new PageUtils(page.getTotal(), page.getRecords()); - } - - @Override - public CtClickFarming getByIdLock(Long id) { - return ctClickFarmingDao.getByIdLock(id); - } - - @Override - public CtClickFarmEditDetailVO getEditDetailById(Long id) { - return ctClickFarmingDao.getEditDetailById(id); - } - - @Override - public CtClickFarmingDetailVO getDetailById(Long id) { - return ctClickFarmingDao.getDetailById(id); - } - - @Override - public List ruleGetCtBuyer(String buyerAccount, String country, String shopName) { - return ctClickFarmingDao.ruleGetCtBuyer(buyerAccount, country, shopName); - } - - @Override - public CtClickFarmYdParams getCtClickFarmYdParams(Long id) { - return ctClickFarmingDao.getCtClickFarmYdParams(id); - } -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtClickOrderServiceImpl.java b/wjcy-common/src/main/java/me/zhengjie/service/impl/CtClickOrderServiceImpl.java deleted file mode 100644 index 1b0f3e1..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtClickOrderServiceImpl.java +++ /dev/null @@ -1,90 +0,0 @@ -package me.zhengjie.service.impl; - -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import me.zhengjie.dao.CtClickOrderDao; -import me.zhengjie.entity.CtClickFarming; -import me.zhengjie.entity.CtClickFarmingOrderInfo; -import me.zhengjie.entity.CtClickOrder; -import me.zhengjie.enums.ClickFarmingStatusEnum; -import me.zhengjie.service.CtClickFarmingService; -import me.zhengjie.service.CtClickOrderService; -import me.zhengjie.service.vo.CtClickOrderDetailVO; -import me.zhengjie.service.vo.CtClickOrderListVO; -import me.zhengjie.utils.PageUtils; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import javax.annotation.Resource; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -/** - * 刷单-订单信息(CtClickOrder)表服务实现类 - * - * @author rch - * @since 2022-09-14 - */ -@Service -public class CtClickOrderServiceImpl extends ServiceImpl implements CtClickOrderService { - - @Resource - private CtClickOrderDao ctClickOrderDao; - @Resource - private CtClickFarmingService ctClickFarmingService; - - @Override - public List getOrderId(List importOrderIdList) { - List orderIdList = new ArrayList<>(); - QueryWrapper queryWrapper = new QueryWrapper(); - queryWrapper.in("order_id", importOrderIdList) - .select("order_id"); - List queryClickOrderIdList = list(queryWrapper); - if (ObjectUtil.isNotEmpty(queryClickOrderIdList)) { - orderIdList = queryClickOrderIdList.stream().map(q->q.getOrderId()).collect(Collectors.toList()); - } - return orderIdList; - } - - @Override - public PageUtils searchPageList(IPage page, Wrapper ew) { - ctClickOrderDao.searchPageList(page, ew); - return new PageUtils(page.getTotal(), page.getRecords()); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public Boolean supplement(Long clickFarmingId, CtClickOrder ctClickOrder) { - Boolean saveBoolean = save(ctClickOrder); - if (!saveBoolean) { - return false; - } - Long ctOrderId = ctClickOrder.getId(); - CtClickFarming ctClickFarming = new CtClickFarming(); - ctClickFarming.setId(clickFarmingId); - ctClickFarming.setCtClickOrderId(ctOrderId); - ctClickFarming.setStatus(ClickFarmingStatusEnum.EXECUTION_SUCCESS.value()); - - return ctClickFarmingService.updateById(ctClickFarming); - } - - @Override - public CtClickFarmingOrderInfo getClickFarmOrderById(Long orderId) { - return ctClickOrderDao.getClickFarmOrderById(orderId); - } - - @Override - public CtClickOrder getByIdLock(Long id) { - return ctClickOrderDao.getByIdLock(id); - } - - @Override - public CtClickOrderDetailVO getClickOrderDetailById(Long id) { - return ctClickOrderDao.getClickOrderDetailById(id); - } -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtCompanyServiceImpl.java b/wjcy-common/src/main/java/me/zhengjie/service/impl/CtCompanyServiceImpl.java deleted file mode 100644 index e5948ac..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtCompanyServiceImpl.java +++ /dev/null @@ -1,53 +0,0 @@ -package me.zhengjie.service.impl; - -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import me.zhengjie.dao.CtCompanyDao; -import me.zhengjie.entity.CtCompany; -import me.zhengjie.entity.CtCompanyInfo; -import me.zhengjie.entity.CtPlatform; -import me.zhengjie.service.CtCompanyService; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * 公司信息(CtCompany)表服务实现类 - * - * @author makejava - * @since 2022-06-23 10:37:44 - */ -@Service -public class CtCompanyServiceImpl extends ServiceImpl implements CtCompanyService { - - @Resource - private CtCompanyDao ctCompanyDao; - - @Override - public List getByNmae(List name) { - return ctCompanyDao.getByName(name); - } - - @Override - public List getCompanyList() { - return ctCompanyDao.getCompanyList(); - } - - @Override - public Map getNameList(List platNameList) { - Map ctCompanyMap = new HashMap<>(16); - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.in("name", platNameList).select("id", "name"); - List ctCompanyList = list(queryWrapper); - if (ObjectUtil.isNotEmpty(ctCompanyList)) { - ctCompanyMap = ctCompanyList.stream().collect(Collectors.toMap(CtCompany::getId, CtCompany::getName)); - } - return ctCompanyMap; - } -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtDhPayServiceImpl.java b/wjcy-common/src/main/java/me/zhengjie/service/impl/CtDhPayServiceImpl.java deleted file mode 100644 index bf25565..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtDhPayServiceImpl.java +++ /dev/null @@ -1,100 +0,0 @@ -package me.zhengjie.service.impl; - -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.json.JSONUtil; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import me.zhengjie.config.DhApiProperties; -import me.zhengjie.constant.PublicConstant; -import me.zhengjie.dao.CtDhPayDao; -import me.zhengjie.entity.CtDhPay; -import me.zhengjie.entity.CtDhPayExport; -import me.zhengjie.enums.DhPayStatusEnum; -import me.zhengjie.enums.ExcelStatusEnum; -import me.zhengjie.service.CtBuyerService; -import me.zhengjie.service.CtDhPayService; -import me.zhengjie.service.vo.CtBuyerListVO; -import me.zhengjie.service.vo.CtDhPayListVO; -import me.zhengjie.service.vo.PayOrderVO; -import me.zhengjie.utils.HttpClientUtil; -import me.zhengjie.utils.PageUtils; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * 平台信息(CtDyPay)表服务实现类 - * - * @author rch - * @since 2022-07-28 - */ -@Service -public class CtDhPayServiceImpl extends ServiceImpl implements CtDhPayService { - - @Resource - private CtDhPayDao ctDhPayDao; - - @Resource - private CtBuyerService ctBuyerService; - - @Override - public PageUtils searchPageList(IPage page, Wrapper ew) { - ctDhPayDao.searchPageList(page, ew); - return new PageUtils(page.getTotal(), page.getRecords()); - } - - @Override - public void toPay() { - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.eq("status", DhPayStatusEnum.TO_BE.value()); - List ctDhPayList = list(queryWrapper); - - // for 循环下单处理 - for (CtDhPay ctDhPay :ctDhPayList) { - payOrderApi(ctDhPay); - } - } - - @Override - public Boolean payOrderApi(CtDhPay ctDhPay) { - - // TODO 参数检验验证 - - String buyerName = ctDhPay.getBuyerName(); - String pwd = ctBuyerService.getPwdByName(buyerName); - if (ObjectUtil.isEmpty(pwd)) { - return false; - } - - Map params = new HashMap<>(16); - // 统一请求参数 - params.put("timestamp", System.currentTimeMillis()); - params.put("v", DhApiProperties.PAY_ORDER_V); - params.put("access_token", pwd); - params.put("method", DhApiProperties.PAY_ORDER_METHOD); - - // boby - params.put("orderNo", ctDhPay.getOrderId()); - - String responseStr = HttpClientUtil.doPostHttp(DhApiProperties.PAY_ORDER_URL, params); - PayOrderVO payOrderVO = JSONUtil.toBean(responseStr, PayOrderVO.class); - Boolean requestBoolean = false; - // 成功 修改订单状态 以及填充接口响应信息 - if (ObjectUtil.isNotEmpty(payOrderVO) && PublicConstant.RESPONSE_SUCCESS.equals(payOrderVO.getResult()) && PublicConstant.DH_REQUEST_SUCCESS_STATUS_CODE.equals(payOrderVO.getStatus().getCode())) { - requestBoolean = true; - } - - Integer status = requestBoolean ? DhPayStatusEnum.PAY_SUCCESS.value() : DhPayStatusEnum.PAY_FAIL.value(); - CtDhPay updateCtDhPay = new CtDhPay(); - updateCtDhPay.setId(ctDhPay.getId()); - updateCtDhPay.setResponse(JSONUtil.toJsonStr(payOrderVO)); - updateCtDhPay.setStatus(status); - return updateById(updateCtDhPay); - } -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtExcelImportInfoServiceImpl.java b/wjcy-common/src/main/java/me/zhengjie/service/impl/CtExcelImportInfoServiceImpl.java deleted file mode 100644 index 0a86ff5..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtExcelImportInfoServiceImpl.java +++ /dev/null @@ -1,174 +0,0 @@ -package me.zhengjie.service.impl; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.lang.Snowflake; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.json.JSONUtil; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.config.PropertiesConfig; -import me.zhengjie.config.SystemConfig; -import me.zhengjie.constant.PublicConstant; -import me.zhengjie.dao.CtExcelImportInfoDao; -import me.zhengjie.entity.*; -import me.zhengjie.enums.ExcelInfoRequestTypeEnum; -import me.zhengjie.enums.ExcelStatusEnum; -import me.zhengjie.service.CtBuyerService; -import me.zhengjie.service.CtCompanyService; -import me.zhengjie.service.CtExcelImportInfoService; -import me.zhengjie.service.CtExcelService; -import me.zhengjie.utils.excel.ExcelUtils; -import org.springframework.beans.BeanUtils; -import org.springframework.context.annotation.Bean; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -/** - * Excel导入信息(CtExcelImportInfo)表服务实现类 - * - * @author rch - * @since 2022-06-23 - */ -@Slf4j -@Service -public class CtExcelImportInfoServiceImpl extends ServiceImpl implements CtExcelImportInfoService { - - @Resource - private CtExcelService ctExcelService; - @Resource - private CtCompanyService ctCompanyService; - @Resource - private CtBuyerService ctBuyerService; - @Resource - private PropertiesConfig propertiesConfig; - @Resource - private Snowflake snowflake; - - @Override - public void importExcel() throws IOException { - LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); - queryWrapper.eq(CtExcel::getStatus, ExcelStatusEnum.TOBE.value()); - - List ctExcelList = ctExcelService.list(queryWrapper); - // 导入存储数据库业务逻辑 - if (ObjectUtil.isNotEmpty(ctExcelList)) { - - // TODO -判断公司和token 是否匹配 不匹配则导入失败 - - // 符合条件的往下走 - String errorUrlPath = saveExcel(ctExcelList); - LambdaQueryWrapper updateStatusQW = new LambdaQueryWrapper<>(); - List ctExcelIdList = ctExcelList.stream().map(CtExcel::getId).collect(Collectors.toList()); - updateStatusQW.in(CtExcel::getId, ctExcelIdList); - - int status = ObjectUtil.isEmpty(errorUrlPath) ? ExcelStatusEnum.SUCCESS.value() : ExcelStatusEnum.FAILE.value(); - // 不符合条件的 直接失败 - CtExcel updateCtExcel = new CtExcel(); - updateCtExcel.setErrorPath(errorUrlPath); - updateCtExcel.setStatus(status); - ctExcelService.update(updateCtExcel, updateStatusQW); - } - } - - /** - * 导入业务逻辑 - * @param ctExcelList - * @return - */ - public String saveExcel(List ctExcelList) throws IOException { - - String returnDataStr = null; - List excelImportInfoList = new ArrayList<>(); - - for (CtExcel ctExcel:ctExcelList) { - String platImageUrl = SystemConfig.IMG_PATH; - String pathUrl = ctExcel.getPath(); - String excelPathUrl = platImageUrl + pathUrl; - - // 读取文件 - File file = new File(excelPathUrl); - try { - List excelImportInfoTempList = ExcelUtils.readFile(file, CtExcelImportInfo.class); - if (ObjectUtil.isNotEmpty(excelImportInfoTempList)) { - excelImportInfoList.addAll(excelImportInfoTempList); - } - } catch (Exception exception) { - System.out.println(exception.getMessage()); - } - } - - // 存储mysql - if (ObjectUtil.isNotEmpty(excelImportInfoList)) { - - - List addCtExcelImportInfoList = new ArrayList<>(); - List errorCtExcelExportInfoList = new ArrayList<>(); - - List companyIdList = excelImportInfoList.stream().map(CtExcelImportInfo::getCompanyId).collect(Collectors.toList()); - QueryWrapper queryWrapperCompany = new QueryWrapper<>(); - queryWrapperCompany.in("id", companyIdList); - List ctCompanyList = ctCompanyService.list(queryWrapperCompany); - - List buyerIdList = excelImportInfoList.stream().map(CtExcelImportInfo::getTokenEnum).collect(Collectors.toList()); - QueryWrapper queryWrapperBuyer = new QueryWrapper<>(); - queryWrapperBuyer.in("id", buyerIdList); - List ctBuyerList = ctBuyerService.list(queryWrapperBuyer); - - // 新增订单编号 - for (CtExcelImportInfo ctExcelImportInfo:excelImportInfoList) { - CtExcelExportInfo ctExcelExportInfo = new CtExcelExportInfo(); - BeanUtil.copyProperties(ctExcelImportInfo, ctExcelExportInfo); - // TODO 检验Excel 导入的文件是否符合要求 符合要求导入 不符合要求则直接Excel错误信息导出 - StringBuffer errorStrBuf = new StringBuffer(); - if (ObjectUtil.isEmpty(ctCompanyList) - || ctCompanyList.stream().filter(c->c.getId().equals(ctExcelImportInfo.getCompanyId())).count() <= 0) { - errorStrBuf.append("公司信息不存在!"); - errorStrBuf.append(";"); - } - - if (ObjectUtil.isEmpty(ctBuyerList) - || ctBuyerList.stream().filter(c->c.getId().equals(ctExcelImportInfo.getTokenEnum())).count() <= 0) { - errorStrBuf.append("买家信息不存在!"); - errorStrBuf.append(";"); - } - - if (ObjectUtil.isNotEmpty(errorStrBuf)) { - ctExcelExportInfo.setError(errorStrBuf.toString()); - errorCtExcelExportInfoList.add(ctExcelExportInfo); - } else { - CtBuyerContactInfo ctBuyerContactInfo = new CtBuyerContactInfo(); - CtBuyer ctBuyer = ctBuyerList.stream().filter(c->c.getId().equals(ctExcelImportInfo.getTokenEnum())).findFirst().get(); - // 取出收款地址信息 - BeanUtil.copyProperties(ctBuyer, ctBuyerContactInfo); - - ctExcelImportInfo.setOrderNo(snowflake.nextIdStr()); - ctExcelImportInfo.setContactInfo(JSONUtil.toJsonStr(ctBuyerContactInfo)); - addCtExcelImportInfoList.add(ctExcelImportInfo); - } - } - - // TODO 不符合条件的 Excel 导出 返回导出excel url url = errorExcelUrl; - String filePath = propertiesConfig.getUploadImgPath().get(PublicConstant.EXPORT_EXCEL_FILE_TYPE); - String fileName = "下单信息导入异常信息表-" + snowflake.nextIdStr(); - if (ObjectUtil.isNotEmpty(errorCtExcelExportInfoList)) { - ExcelUtils.exportFile(SystemConfig.IMG_PATH + filePath, fileName, errorCtExcelExportInfoList); - returnDataStr = SystemConfig.FILE_VISIT_ADDR + filePath + fileName + ".xlsx"; - // returnDataStr = "http://localhost:8008/file" + filePath + fileName + ".xlsx"; - } - // 如何条件的导入 - if (ObjectUtil.isNotEmpty(addCtExcelImportInfoList)) { - saveBatch(addCtExcelImportInfoList); - } - } - return returnDataStr; - } -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtExcelServiceImpl.java b/wjcy-common/src/main/java/me/zhengjie/service/impl/CtExcelServiceImpl.java deleted file mode 100644 index 6cfbb08..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtExcelServiceImpl.java +++ /dev/null @@ -1,19 +0,0 @@ -package me.zhengjie.service.impl; - -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import me.zhengjie.dao.CtExcelDao; -import me.zhengjie.entity.CtExcel; -import me.zhengjie.service.CtExcelService; -import org.springframework.stereotype.Service; - -/** - * Excel 导入信息(CtExcel)表服务实现类 - * - * @author makejava - * @since 2022-06-23 10:37:44 - */ -@Service -public class CtExcelServiceImpl extends ServiceImpl implements CtExcelService { - -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtOrderServiceImpl.java b/wjcy-common/src/main/java/me/zhengjie/service/impl/CtOrderServiceImpl.java deleted file mode 100644 index 9fe1f5b..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtOrderServiceImpl.java +++ /dev/null @@ -1,196 +0,0 @@ -package me.zhengjie.service.impl; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.json.JSONUtil; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import me.zhengjie.config.DhApiProperties; -import me.zhengjie.constant.PublicConstant; -import me.zhengjie.dao.CtOrderDao; -import me.zhengjie.entity.*; -import me.zhengjie.enums.ExcelStatusEnum; -import me.zhengjie.service.*; -import me.zhengjie.service.vo.*; -import me.zhengjie.utils.HttpClientUtil; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import javax.annotation.Resource; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * (CtOrder)表服务实现类 - * - * @author rch - * @since 2022-07-01 - */ -@Service -public class CtOrderServiceImpl extends ServiceImpl implements CtOrderService { - - @Resource - private CtExcelImportInfoService ctExcelImportInfoService; - @Resource - private CtResponseOrderService ctResponseOrderService; - @Resource - private CtResponseOrderAddressService ctResponseOrderAddressService; - @Resource - private CtResponseOrderProductService ctResponseOrderProductService; - @Resource - private CtBuyerService ctBuyerService; - - @Override - public void excelToOrder() { - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.eq("status", ExcelStatusEnum.TOBE.value()); - List ctExcelImportInfoList = ctExcelImportInfoService.list(queryWrapper); - - for (CtExcelImportInfo ctExcelImportInfo:ctExcelImportInfoList) { - buyOrderApi(ctExcelImportInfo); - } - } - - @Transactional(rollbackFor = Exception.class) - public Boolean buyOrderApi(CtExcelImportInfo ctExcelImportInfo) { - - // TODO 请求参数解析 检验 -先不做 - - // 获取买家access_token - Long buyerId = ctExcelImportInfo.getTokenEnum(); - CtBuyer ctBuyer = ctBuyerService.getById(buyerId); - - Map params = new HashMap<>(); - // 统一请求参数 - params.put("timestamp", System.currentTimeMillis()); - params.put("v", DhApiProperties.BUY_ORDER_V); - params.put("access_token", ctBuyer.getPwd()); - params.put("method", DhApiProperties.BUY_ORDER_METHOD); - - // boby - params.put("fromDetailInfo", ctExcelImportInfo.getFromDetailInfo()); - String carList = ctExcelImportInfo.getCartList(); - String contacInfo = ctExcelImportInfo.getContactInfo(); - params.put("cartList", carList); - params.put("contactInfo", contacInfo); - - - String responseStr = HttpClientUtil.doPostHttp(DhApiProperties.BUY_ORDER_URL, params); - - // 请求响应转对象 - BuyOrderVO buyOrderVO = JSONUtil.toBean(responseStr, BuyOrderVO.class); - System.out.println("buyOrderVO: " + buyOrderVO.toString()); - - Boolean saveOrderBathResult = false; - // 业务逻辑处理 数据处理 - if (ObjectUtil.isNotEmpty(buyOrderVO) && PublicConstant.DH_REQUEST_SUCCESS_STATUS_CODE.equals(buyOrderVO.getStatus().getCode())) { - // 接口响应码以及响应信息 - OrderResponStatusVO orderResponStatus = buyOrderVO.getStatus(); - // 请求接口响应内容 - List OrderResponseList = buyOrderVO.getOrderList(); - - List orderList = new ArrayList<>(); - Long companyId = ctExcelImportInfo.getCompanyId(); - - for (OrderResponseVO orderResponseVO:OrderResponseList) { - CtOrder ctOrder = new CtOrder(); - ctOrder.setCompanyId(companyId); - ctOrder.setBuyerId(buyerId); - ctOrder.setBuyAccessToken(ctBuyer.getPwd()); - ctOrder.setExcelInfoId(ctExcelImportInfo.getId()); - ctOrder.setCtOrderNo(ctExcelImportInfo.getOrderNo()); - ctOrder.setOrderResponseStatus(JSONUtil.toJsonStr(orderResponStatus)); - - // ct_response_order - CtResponseOrder ctResponseOrder = new CtResponseOrder(); - BuyOrderResponseOrderVO buyOrderResponseOrderVO = orderResponseVO.getOrderInfo(); - BeanUtil.copyProperties(buyOrderResponseOrderVO, ctResponseOrder); - System.out.println("======ctResponseOrder:" + ctResponseOrder); - // order 特殊处理 对应响应的id - Long responseOrderId = buyOrderResponseOrderVO.getId(); - ctResponseOrder.setOrderId(responseOrderId); - ctResponseOrderService.save(ctResponseOrder); - Long saveResponseOrderId = ctResponseOrder.getId(); - ctOrder.setResponseOrderId(saveResponseOrderId); - ctOrder.setOrderNo(responseOrderId); - - // ct_response_address - CtResponseOrderAddress ctResponseOrderAddress = new CtResponseOrderAddress(); - BuyOrderResponseAddressVO buyOrderResponseAddress = orderResponseVO.getOrderContactInfo(); - BeanUtil.copyProperties(buyOrderResponseAddress, ctResponseOrderAddress); - System.out.println("======ctResponseOrderAddress:" + ctResponseOrderAddress); - ctResponseOrderAddressService.save(ctResponseOrderAddress); - Long responseOrderAddressId = ctResponseOrderAddress.getId(); - ctOrder.setResponseOrderAddressId(responseOrderAddressId); - - // ct_response_product - // TODO -这里商品响应是一个集合 这里目前看都是单个,先不考虑 - CtResponseOrderProduct ctResponseOrderProduct = new CtResponseOrderProduct(); - List buyOrderResponseProductList = orderResponseVO.getCartList(); - BeanUtil.copyProperties(buyOrderResponseProductList.get(0), ctResponseOrderProduct); - System.out.println("======ctResponseOrderProduct:" + ctResponseOrderProduct); - ctResponseOrderProductService.save(ctResponseOrderProduct); - Long responseproductId = ctResponseOrderProduct.getId(); - ctOrder.setResponseProductId(responseproductId); - - orderList.add(ctOrder); - } - - saveOrderBathResult = saveBatch(orderList); - } - - // 修改Excel状态 - Integer status = saveOrderBathResult ? ExcelStatusEnum.SUCCESS.value() : ExcelStatusEnum.FAILE.value(); - CtExcelImportInfo updateCtExcelImportInfo = new CtExcelImportInfo(); - updateCtExcelImportInfo.setId(ctExcelImportInfo.getId()); - updateCtExcelImportInfo.setStatus(status); - ctExcelImportInfoService.updateById(updateCtExcelImportInfo); - - return true; - } - - @Override - public void toPay() { - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.eq("status", ExcelStatusEnum.TOBE.value()); - List ctOrderList = list(queryWrapper); - - for (CtOrder ctOrder:ctOrderList) { - payOrderApi(ctOrder); - } - } - - @Override - public Boolean payOrderApi(CtOrder ctOrder) { - - // TODO 参数检验验证 - - Map params = new HashMap<>(); - // 统一请求参数 - params.put("timestamp", System.currentTimeMillis()); - params.put("v", DhApiProperties.PAY_ORDER_V); - params.put("access_token", ctOrder.getBuyAccessToken()); - params.put("method", DhApiProperties.PAY_ORDER_METHOD); - - // boby - params.put("orderNo", ctOrder.getOrderNo()); - - String responseStr = HttpClientUtil.doPostHttp(DhApiProperties.PAY_ORDER_URL, params); - PayOrderVO payOrderVO = JSONUtil.toBean(responseStr, PayOrderVO.class); - Boolean requestBoolean = false; - // 成功 修改订单状态 以及填充接口响应信息 - if (ObjectUtil.isNotEmpty(payOrderVO) && PublicConstant.RESPONSE_SUCCESS.equals(payOrderVO.getResult()) && PublicConstant.DH_REQUEST_SUCCESS_STATUS_CODE.equals(payOrderVO.getStatus().getCode())) { - requestBoolean = true; - } - - Integer status = requestBoolean ? ExcelStatusEnum.SUCCESS.value() : ExcelStatusEnum.FAILE.value(); - CtOrder updateCtOrder = new CtOrder(); - updateCtOrder.setId(ctOrder.getId()); - updateCtOrder.setPayResponseStatus(JSONUtil.toJsonStr(payOrderVO)); - updateCtOrder.setStatus(status); - return updateById(updateCtOrder); - } -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtPlatformServiceImpl.java b/wjcy-common/src/main/java/me/zhengjie/service/impl/CtPlatformServiceImpl.java deleted file mode 100644 index b399b7b..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtPlatformServiceImpl.java +++ /dev/null @@ -1,37 +0,0 @@ -package me.zhengjie.service.impl; - -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import me.zhengjie.dao.CtPlatformDao; -import me.zhengjie.entity.CtPlatform; -import me.zhengjie.service.CtPlatformService; -import org.springframework.stereotype.Service; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * 平台信息(CtPlatform)表服务实现类 - * - * @author makejava - * @since 2022-06-23 10:37:44 - */ -@Service -public class CtPlatformServiceImpl extends ServiceImpl implements CtPlatformService { - - @Override - public Map getNameList(List platNameList) { - Map ctPlatformMap = new HashMap<>(16); - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.in("name", platNameList).select("id", "name"); - List ctPlatformList = list(queryWrapper); - if (ObjectUtil.isNotEmpty(ctPlatformList)) { - ctPlatformMap = ctPlatformList.stream().collect(Collectors.toMap(CtPlatform::getId, CtPlatform::getName)); - } - return ctPlatformMap; - } -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtRebotServiceImpl.java b/wjcy-common/src/main/java/me/zhengjie/service/impl/CtRebotServiceImpl.java deleted file mode 100644 index 93120c8..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtRebotServiceImpl.java +++ /dev/null @@ -1,127 +0,0 @@ -package me.zhengjie.service.impl; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.lang.Snowflake; -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import me.zhengjie.config.PropertiesConfig; -import me.zhengjie.config.SystemConfig; -import me.zhengjie.constant.PublicConstant; -import me.zhengjie.dao.CtRebotDao; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.CtRebot; -import me.zhengjie.entity.CtRebotExport; -import me.zhengjie.entity.CtRebotImport; -import me.zhengjie.service.CtRebotService; -import me.zhengjie.service.vo.CtRebotListVO; -import me.zhengjie.utils.PageUtils; -import me.zhengjie.utils.excel.ExcelUtils; -import org.springframework.stereotype.Service; -import org.springframework.web.multipart.MultipartFile; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletResponse; -import java.util.ArrayList; -import java.util.List; - -/** - * 影刀设备-机器人信息(CtRebot)表服务实现类 - * - * @author rch - * @since 2022-07-23 - */ -@Service -public class CtRebotServiceImpl extends ServiceImpl implements CtRebotService { - - @Resource - private CtRebotDao ctRebotDao; - @Resource - private PropertiesConfig propertiesConfig; - @Resource - private Snowflake snowflake; - - @Override - public CtRebot getByAccountNameLock(String accountName) { - return ctRebotDao.getByAccountNameLock(accountName); - } - - @Override - public PageUtils searchPageList(IPage page, Wrapper ew) { - ctRebotDao.searchRebotList(page,ew); - return new PageUtils<>(page.getTotal(),page.getRecords()); - } - - @Override - public Dto importRebot(MultipartFile file, HttpServletResponse response)throws Exception { - List ctRebotImportList = ExcelUtils.readMultipartFile(file,CtRebotImport.class); - if(ObjectUtil.isEmpty(ctRebotImportList)){ - return Dto.returnResult(false); - } - - List addCtRebotList = new ArrayList<>(); - List ctRebotExportList = new ArrayList<>(); - List rebotNameList = getAccountNameList(); - List rebotUuidList = getClientUuidList(); - - for(CtRebotImport ctRebotImport : ctRebotImportList){ - CtRebotExport ctRebotExport = new CtRebotExport(); - BeanUtil.copyProperties(ctRebotImport,ctRebotExport); - - StringBuffer errorBuffer = new StringBuffer(); - String rowTips = ctRebotImport.getRowTips(); - if(ObjectUtil.isNotEmpty(rowTips)){ - errorBuffer.append(rowTips); - errorBuffer.append(";"); - } - if(rebotNameList.contains(ctRebotImport.getAccountName())){ - errorBuffer.append("已存在该名称对应的机器人信息"); - errorBuffer.append(";"); - } - if(rebotUuidList.contains(ctRebotImport.getRobotClientUuid())){ - errorBuffer.append("已存在该Uuid对应的机器人信息"); - errorBuffer.append(";"); - } - if(ObjectUtil.isNotEmpty(errorBuffer)){ - ctRebotExport.setError(errorBuffer.toString()); - ctRebotExportList.add(ctRebotExport); - }else{ - CtRebot ctRebot = new CtRebot(); - BeanUtil.copyProperties(ctRebotImport,ctRebot); - addCtRebotList.add(ctRebot); - } - } - - String returnDataStr = null; - String filePath = propertiesConfig.getUploadImgPath().get(PublicConstant.EXPORT_EXCEL_FILE_TYPE); - String fileName = "机器人导入异常信息表-" + snowflake.nextIdStr(); - if(ObjectUtil.isNotEmpty(ctRebotExportList)){ - ExcelUtils.exportFile(SystemConfig.IMG_PATH + filePath, fileName, ctRebotExportList); - returnDataStr = SystemConfig.FILE_VISIT_ADDR + filePath + fileName + ".xlsx"; - //returnDataStr = "http://localhost:8008/file" + filePath + fileName + ".xlsx"; - } - - if(ObjectUtil.isNotEmpty(addCtRebotList)){ - saveBatch(addCtRebotList); - } - - return Dto.returnResult(ObjectUtil.isEmpty(returnDataStr) ? true : returnDataStr); - } - - @Override - public List getAccountNameList() { - return ctRebotDao.getAccountNameList(); - } - - @Override - public List getClientUuidList() { - return ctRebotDao.getClientUuidList(); - } - - @Override - public Boolean updateNewStatusByOldStatus(Long id, Integer newStatus, Integer oldStatus) { - return ctRebotDao.updateNewStatusByOldStatus(id, newStatus, oldStatus); - } -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtResponseOrderAddressServiceImpl.java b/wjcy-common/src/main/java/me/zhengjie/service/impl/CtResponseOrderAddressServiceImpl.java deleted file mode 100644 index 96ee9e6..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtResponseOrderAddressServiceImpl.java +++ /dev/null @@ -1,19 +0,0 @@ -package me.zhengjie.service.impl; - -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import me.zhengjie.dao.CtResponseOrderAddressDao; -import me.zhengjie.entity.CtResponseOrderAddress; -import me.zhengjie.service.CtResponseOrderAddressService; -import org.springframework.stereotype.Service; - -/** - * 下注成功订单响应收货地址信息(CtResponseOrderAddress)表服务实现类 - * - * @author rch - * @since 2022-07-01 - */ -@Service -public class CtResponseOrderAddressServiceImpl extends ServiceImpl implements CtResponseOrderAddressService { - -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtResponseOrderProductServiceImpl.java b/wjcy-common/src/main/java/me/zhengjie/service/impl/CtResponseOrderProductServiceImpl.java deleted file mode 100644 index 9045753..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtResponseOrderProductServiceImpl.java +++ /dev/null @@ -1,19 +0,0 @@ -package me.zhengjie.service.impl; - -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import me.zhengjie.dao.CtResponseOrderProductDao; -import me.zhengjie.entity.CtResponseOrderProduct; -import me.zhengjie.service.CtResponseOrderProductService; -import org.springframework.stereotype.Service; - -/** - * 下单订单响应产品信息(CtResponseOrderProduct)表服务实现类 - * - * @author rch - * @since 2022-07-01 - */ -@Service -public class CtResponseOrderProductServiceImpl extends ServiceImpl implements CtResponseOrderProductService { - -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtResponseOrderServiceImpl.java b/wjcy-common/src/main/java/me/zhengjie/service/impl/CtResponseOrderServiceImpl.java deleted file mode 100644 index 1aab77d..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtResponseOrderServiceImpl.java +++ /dev/null @@ -1,19 +0,0 @@ -package me.zhengjie.service.impl; - -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import me.zhengjie.dao.CtResponseOrderDao; -import me.zhengjie.entity.CtResponseOrder; -import me.zhengjie.service.CtResponseOrderService; -import org.springframework.stereotype.Service; - -/** - * 下单成功响应订单商品信息(CtResponseOrder)表服务实现类 - * - * @author rch - * @since 2022-07-01 - */ -@Service -public class CtResponseOrderServiceImpl extends ServiceImpl implements CtResponseOrderService { - -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtVpnServiceImpl.java b/wjcy-common/src/main/java/me/zhengjie/service/impl/CtVpnServiceImpl.java deleted file mode 100644 index db2730a..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/impl/CtVpnServiceImpl.java +++ /dev/null @@ -1,31 +0,0 @@ -package me.zhengjie.service.impl; - -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import me.zhengjie.dao.CtVpnDao; -import me.zhengjie.entity.CtVpn; -import me.zhengjie.entity.CtVpnInfo; -import me.zhengjie.service.CtVpnService; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; - -/** - * VPN信息表(CtVpn)表服务实现类 - * - * @author rch - * @since 2022-07-07 - */ -@Service -public class CtVpnServiceImpl extends ServiceImpl implements CtVpnService { - - @Resource - private CtVpnDao ctVpnDao; - - @Override - public List getIpList() { return ctVpnDao.getIpList(); } - - @Override - public List getVpnInfoByIp(List ipAddress){ return ctVpnDao.getVpnInfoByIp(ipAddress);} -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/impl/DhAddCarOrderServiceImpl.java b/wjcy-common/src/main/java/me/zhengjie/service/impl/DhAddCarOrderServiceImpl.java deleted file mode 100644 index 3d9143b..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/impl/DhAddCarOrderServiceImpl.java +++ /dev/null @@ -1,98 +0,0 @@ -package me.zhengjie.service.impl; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import me.zhengjie.dao.DhAddCarOrderDao; -import me.zhengjie.dao.DhCarGoodsDao; -import me.zhengjie.entity.DhAddCarOrder; -import me.zhengjie.entity.DhCarGoods; -import me.zhengjie.enums.ParamsTypeEnum; -import me.zhengjie.service.DhAddCarOrderService; -import me.zhengjie.service.vo.dhaddcar.DhAddCarVO; -import me.zhengjie.service.vo.dhcargood.DhCarGoodKeyVO; -import me.zhengjie.service.vo.dhcargood.DhCarGoodLinkVO; -import me.zhengjie.service.vo.dhcarorder.DhAddCarOrderListVO; -import me.zhengjie.service.vo.dhcarorder.DhCarOrderParamsVO; -import me.zhengjie.utils.PageUtils; -import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * 敦煌-加购物车-订单(DhAddCarOrder)表服务实现类 - * - * @author rch - * @since 2022-11-17 09:12:00 - */ -@Service -public class DhAddCarOrderServiceImpl extends ServiceImpl implements DhAddCarOrderService { - - @Resource - private DhAddCarOrderDao dhAddCarOrderDao; - - @Resource - private DhCarGoodsDao dhCarGoodsDao; - - @Override - public DhAddCarOrder getByIdLock(Long id) { - return dhAddCarOrderDao.getByIdLock(id); - } - - @Override - public PageUtils searchPageList(IPage page, Wrapper ew) { - dhAddCarOrderDao.searchPageList(page, ew); - return new PageUtils(page.getTotal(), page.getRecords()); - } - - @Override - public DhCarOrderParamsVO getYdParams(Long id) { - DhCarOrderParamsVO dhCarOrderParamsVO = dhAddCarOrderDao.getYdParams(id); - if (ObjectUtil.isEmpty(dhCarOrderParamsVO)) { - return dhCarOrderParamsVO; - } - - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.eq("params_type", dhCarOrderParamsVO.getParamsType()); - queryWrapper.in("id", Arrays.asList(dhCarOrderParamsVO.getCarGoodIds().split(","))); - List DhCarGoods = dhCarGoodsDao.selectList(queryWrapper); - if (ObjectUtil.isEmpty(DhCarGoods)) { - return dhCarOrderParamsVO; - } - - List carGoodKeyList = new ArrayList<>(); - List carGoodLinkList = new ArrayList<>(); - for (DhCarGoods dhCarGoods:DhCarGoods) { - if (ParamsTypeEnum.KEY_WORD.eqValue(dhCarOrderParamsVO.getParamsType())) { - - DhCarGoodKeyVO dhCarGoodKeyVO = new DhCarGoodKeyVO(); - BeanUtil.copyProperties(dhCarGoods, dhCarGoodKeyVO); - carGoodKeyList.add(dhCarGoodKeyVO); - } else if (ParamsTypeEnum.LINK.eqValue(dhCarOrderParamsVO.getParamsType())) { - - DhCarGoodLinkVO dhCarGoodLinkVO = new DhCarGoodLinkVO(); - BeanUtil.copyProperties(dhCarGoods, dhCarGoodLinkVO); - carGoodLinkList.add(dhCarGoodLinkVO); - } else { - continue; - } - } - - if (ObjectUtil.isNotEmpty(carGoodKeyList)) { - dhCarOrderParamsVO.setCarGoodKeys(carGoodKeyList); - } - - if (ObjectUtil.isNotEmpty(carGoodLinkList)) { - dhCarOrderParamsVO.setCarGoodLinks(carGoodLinkList); - } - return dhCarOrderParamsVO; - } -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/impl/DhAddCarServiceImpl.java b/wjcy-common/src/main/java/me/zhengjie/service/impl/DhAddCarServiceImpl.java deleted file mode 100644 index 9b45a16..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/impl/DhAddCarServiceImpl.java +++ /dev/null @@ -1,108 +0,0 @@ -package me.zhengjie.service.impl; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import me.zhengjie.dao.DhAddCarDao; -import me.zhengjie.entity.DhAddCar; -import me.zhengjie.entity.DhCarGoods; -import me.zhengjie.enums.ParamsTypeEnum; -import me.zhengjie.service.DhAddCarService; -import me.zhengjie.service.DhCarGoodsService; -import me.zhengjie.service.vo.dhaddcar.DhAddCarListVO; -import me.zhengjie.service.vo.dhaddcar.DhAddCarVO; -import me.zhengjie.service.vo.dhaddcar.DhAddCarYdParamsVO; -import me.zhengjie.service.vo.dhcargood.DhCarGoodKeyVO; -import me.zhengjie.service.vo.dhcargood.DhCarGoodLinkVO; -import me.zhengjie.utils.PageUtils; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * 敦煌加入购物车(DhAddCar)表服务实现类 - * - * @author rch - * @since 2022-11-17 09:11:56 - */ -@Service -public class DhAddCarServiceImpl extends ServiceImpl implements DhAddCarService { - - @Resource - private DhAddCarDao dhAddCarDao; - @Resource - private DhCarGoodsService dhCarGoodsService; - - @Override - public PageUtils searchPageList(IPage page, Wrapper ew) { - dhAddCarDao.searchPageList(page, ew); - return new PageUtils(page.getTotal(), page.getRecords()); - } - - @Override - public DhAddCarVO getDetailById(Long id) { - DhAddCarVO dhAddCarVO = dhAddCarDao.getDetailById(id); - if (ObjectUtil.isEmpty(dhAddCarVO)) { - return dhAddCarVO; - } - - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.eq("params_type", dhAddCarVO.getParamsType()); - queryWrapper.in("id", Arrays.asList(dhAddCarVO.getCarGoodIds().split(","))); - List DhCarGoods = dhCarGoodsService.list(queryWrapper); - if (ObjectUtil.isEmpty(DhCarGoods)) { - return dhAddCarVO; - } - - List carGoodKeyList = new ArrayList<>(); - List carGoodLinkList = new ArrayList<>(); - for (DhCarGoods dhCarGoods:DhCarGoods) { - if (ParamsTypeEnum.KEY_WORD.eqValue(dhAddCarVO.getParamsType())) { - - DhCarGoodKeyVO dhCarGoodKeyVO = new DhCarGoodKeyVO(); - BeanUtil.copyProperties(dhCarGoods, dhCarGoodKeyVO); - carGoodKeyList.add(dhCarGoodKeyVO); - } else if (ParamsTypeEnum.LINK.eqValue(dhAddCarVO.getParamsType())) { - - DhCarGoodLinkVO dhCarGoodLinkVO = new DhCarGoodLinkVO(); - BeanUtil.copyProperties(dhCarGoods, dhCarGoodLinkVO); - carGoodLinkList.add(dhCarGoodLinkVO); - } else { - continue; - } - } - - if (ObjectUtil.isNotEmpty(carGoodKeyList)) { - dhAddCarVO.setCarGoodKeys(carGoodKeyList); - } - - if (ObjectUtil.isNotEmpty(carGoodLinkList)) { - dhAddCarVO.setCarGoodLinks(carGoodLinkList); - } - return dhAddCarVO; - } - - @Override - public DhAddCar getByIdLock(Long id) { - return dhAddCarDao.getByIdLock(id); - } - - @Override - public DhAddCarYdParamsVO getAddCarYdParams(Long id) { - DhAddCarYdParamsVO dhAddCarYdParamsVO = new DhAddCarYdParamsVO(); - DhAddCarVO dhAddCarVO = getDetailById(id); - if (ObjectUtil.isEmpty(dhAddCarVO)) { - return dhAddCarYdParamsVO; - } - - BeanUtil.copyProperties(dhAddCarVO, dhAddCarYdParamsVO); - return dhAddCarYdParamsVO; - } -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/impl/DhCarGoodsServiceImpl.java b/wjcy-common/src/main/java/me/zhengjie/service/impl/DhCarGoodsServiceImpl.java deleted file mode 100644 index f18256a..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/impl/DhCarGoodsServiceImpl.java +++ /dev/null @@ -1,19 +0,0 @@ -package me.zhengjie.service.impl; - -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import me.zhengjie.dao.DhCarGoodsDao; -import me.zhengjie.entity.DhCarGoods; -import me.zhengjie.service.DhCarGoodsService; -import org.springframework.stereotype.Service; - -/** - * 敦煌-加入购物车商品信息(DhCarGoods)表服务实现类 - * - * @author makejava - * @since 2022-11-17 09:12:04 - */ -@Service -public class DhCarGoodsServiceImpl extends ServiceImpl implements DhCarGoodsService { - -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/impl/FileUploadServiceImpl.java b/wjcy-common/src/main/java/me/zhengjie/service/impl/FileUploadServiceImpl.java deleted file mode 100644 index 37d22fa..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/impl/FileUploadServiceImpl.java +++ /dev/null @@ -1,130 +0,0 @@ -package me.zhengjie.service.impl; - - -import cn.hutool.core.convert.Convert; -import cn.hutool.core.lang.Snowflake; -import cn.hutool.core.map.MapUtil; -import cn.hutool.core.util.ObjectUtil; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.config.PropertiesConfig; -import me.zhengjie.config.SystemConfig; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.service.FileUploadService; -import org.springframework.stereotype.Service; -import org.springframework.util.FileCopyUtils; -import org.springframework.web.multipart.MultipartFile; -import org.springframework.web.multipart.MultipartHttpServletRequest; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.File; -import java.io.IOException; -import java.time.LocalDate; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import static me.zhengjie.error.ErrorCodeEnum.UPLOAD_IMG_FORMAT_ERROR; -/** - *

- * 图片上传服务 - *

- * - * @Author xx - * @Date 2021/7/26 - **/ -@Slf4j -@Service -public class FileUploadServiceImpl implements FileUploadService { - - @Resource - private Snowflake snowflake; - @Resource - private PropertiesConfig config; - - @Override - public List uploadify(HttpServletRequest request, HttpServletResponse response) throws IOException { - response.setCharacterEncoding("utf-8"); - response.setContentType("application/json;charset=utf-8"); - response.setHeader("Cache-Control", "no-cache"); - Integer type = Convert.toInt(request.getParameter("type")); - - MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; - Map fileMap = multipartRequest.getFileMap(); - // 如果有传文件路径,则为替换文件, - String fileUrl = request.getParameter("fileUrl"); - - List returnStr = new ArrayList(); - if (ObjectUtil.isNotEmpty(fileUrl)) { - for (String key : fileMap.keySet()) { - MultipartFile multipartFile = fileMap.get(key); - isTrue(multipartFile,type); - // 文件覆盖 - File uploadFile = new File(SystemConfig.IMG_PATH + "/" + fileUrl); - - FileCopyUtils.copy(multipartFile.getBytes(), uploadFile); - returnStr.add(MapUtil.of("path", fileUrl)); - break; - } - }else { - for (String key : fileMap.keySet()) { - MultipartFile mf = fileMap.get(key); - isTrue(mf,type); - // 文件保存路径 - String filePath = config.getUploadImgPath().get(type); - filePath = filePath + LocalDate.now().toString().replaceAll("-","")+"/"; - - File file = new File(SystemConfig.IMG_PATH + filePath); - if (!file.exists()) { - file.mkdirs(); - } - // 文件名 - String fileEnd = mf.getOriginalFilename(); - fileEnd = fileEnd.substring(fileEnd.lastIndexOf(".")); - String newfileName = snowflake.nextIdStr() + fileEnd; - // 文件保存到本地 - File uploadFile = new File(file.getAbsolutePath() + "/" + newfileName); - FileCopyUtils.copy(mf.getBytes(), uploadFile); - String path = filePath + newfileName; - returnStr.add(MapUtil.of("path", path)); - } - } - - return returnStr; - } - - - /** - * 上传文件验证,如果验证不通过将抛出异常 - * - * @author: zeng - */ - private void isTrue(MultipartFile mf,Integer type) { - int maxFileSize = SystemConfig.MAX_FILE_SIZE; - if (type.equals(8)){ - maxFileSize = SystemConfig.VIDEO_MAX_FILE_SIZE; - } - if (mf.getSize()>(maxFileSize*1024*1024)){ - throw new BadRequestException(2005, "文件大小不超过于" + maxFileSize + "M"); - } - String fileEnd = mf.getOriginalFilename(); - fileEnd = fileEnd.substring(fileEnd.lastIndexOf(".")); - // 文件格式验证 - if (!imgFormat(fileEnd.substring(1))){ - UPLOAD_IMG_FORMAT_ERROR.setDesc(fileEnd+" 上传图片格式错误"); - throw new BadRequestException(UPLOAD_IMG_FORMAT_ERROR); - } - } - - - private boolean imgFormat(String fileEnd) { - for (String s : config.getSustainImgFormat()) { - if (s.equalsIgnoreCase(fileEnd)) { - return true; - } - } - return false; - } - -} diff --git a/wjcy-common/src/main/java/me/zhengjie/service/impl/LoginIpServiceImpl.java b/wjcy-common/src/main/java/me/zhengjie/service/impl/LoginIpServiceImpl.java deleted file mode 100644 index bf9256f..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/impl/LoginIpServiceImpl.java +++ /dev/null @@ -1,121 +0,0 @@ -package me.zhengjie.service.impl; - -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import lombok.RequiredArgsConstructor; -import me.zhengjie.dao.LoginIpDao; -import me.zhengjie.entity.LoginIp; -import me.zhengjie.service.LoginIpService; -import me.zhengjie.service.vo.LoginIpVO; -import me.zhengjie.utils.DateUtil; -import me.zhengjie.utils.LoginIpUtil; -import me.zhengjie.utils.PageUtils; -import me.zhengjie.utils.RedisUtils; -import org.springframework.stereotype.Service; - -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; - -/** - * (LoginIp)表服务实现类 - * - * @author zeng - * @since 2022-03-21 14:07:01 - */ -@Service -@RequiredArgsConstructor -public class LoginIpServiceImpl extends ServiceImpl implements LoginIpService { - - final RedisUtils redisUtils; - - @Override - public PageUtils getList(IPage iPage) { - LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); - lqw.orderByDesc(LoginIp::getId); - page(iPage, lqw); - ArrayList arrayList = new ArrayList(); - for (LoginIp record : iPage.getRecords()) { - LoginIpVO loginIpVO = new LoginIpVO(record); - arrayList.add(loginIpVO); - } - return new PageUtils(iPage.getTotal(), arrayList); - } - - @Override - public boolean addIp(LoginIp ip) { - if (save(ip)) { - redisUtils.lPush(LoginIpService.LOGIN_IP_LIST, ip); - return true; - } - return false; - } - - @Override - public List getAll() { - List list = redisUtils.lGet(LoginIpService.LOGIN_IP_LIST, 0, -1); - if (ObjectUtil.isEmpty(list)) { - LambdaQueryWrapper lqw = new LambdaQueryWrapper<>(); - lqw.ge(LoginIp::getVaildTime, DateUtil.getCurrentTime()).or(q->q.eq(LoginIp::getVaildTime,"")); - return list(lqw); - } - return list; - } - - @Override - public boolean updateIp(LoginIp ip) { - if (updateById(ip)) { - List list = getAll(); - for (LoginIp loginIp : list) { - if (loginIp.getId().equals(ip.getId())) { - redisUtils.lRemove(LoginIpService.LOGIN_IP_LIST, 1, loginIp); - break; - } - } - redisUtils.lPush(LoginIpService.LOGIN_IP_LIST, ip); - return true; - } - return false; - } - - @Override - public boolean deleteIp(Integer id) { - if (removeById(id)) { - List list = getAll(); - for (LoginIp loginIp : list) { - if (loginIp.getId().equals(id)) { - redisUtils.lRemove(LoginIpService.LOGIN_IP_LIST, 1, loginIp); - } - } - } - return false; - } - - @Override - public boolean whiteListFlag(String ip) { - List ipList = getAll(); - if (ObjectUtil.isNotEmpty(ipList)) { - boolean flag = false; - for (LoginIp loginIp : ipList) { - if (ObjectUtil.isNotEmpty(loginIp.getVaildTime())) { - LocalDateTime localDateTime = DateUtil.parseLocalDateTimeFormatyMdHms(loginIp.getVaildTime()); - if (localDateTime.isBefore(LocalDateTime.now())) { - // 失效 - redisUtils.lRemove(LoginIpService.LOGIN_IP_LIST, 1, loginIp); - continue; - } - } - if (LoginIpUtil.ipExistsInRange(ip, loginIp.getIpStart(), loginIp.getIpEnd())) { - return true; - } - } - return false; - } - return true; - } - - -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/impl/SettingSiteServiceImpl.java b/wjcy-common/src/main/java/me/zhengjie/service/impl/SettingSiteServiceImpl.java deleted file mode 100644 index 56538f3..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/impl/SettingSiteServiceImpl.java +++ /dev/null @@ -1,75 +0,0 @@ -package me.zhengjie.service.impl; - -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.dao.SettingSiteDao; -import me.zhengjie.entity.CtSettingSite; -import me.zhengjie.service.SettingSiteService; -import me.zhengjie.utils.RedisUtils; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; - -import static me.zhengjie.constant.PublicConstant.CACHE_OVER_TIME; -import static me.zhengjie.constant.PublicConstant.SETTING_SITE_PREFIX; - -/** - * 站点配置(CtSettingSite)表服务实现类 - * - * @author makejava - * @since 2021-11-17 17:02:11 - */ -@Service -@Slf4j -public class SettingSiteServiceImpl extends ServiceImpl implements SettingSiteService { - @Resource - private RedisUtils redisUtils; - @Resource - private SettingSiteDao settingSiteDao; - - @Override - public String getValue(String key) { - String prefix = String.format(SETTING_SITE_PREFIX, key); - Object value = redisUtils.get(prefix); - - if (ObjectUtil.isNotEmpty(value)) { - return value.toString(); - } - String valueByKey = settingSiteDao.getValueByKey(key); - redisUtils.set(prefix, valueByKey, CACHE_OVER_TIME); - return valueByKey; - } - - @Override - public boolean saveOrUpdateByKey(String key, String value) { - LambdaQueryWrapper lqw = new LambdaQueryWrapper(); - lqw.eq(CtSettingSite::getSettingKey, key); - boolean boo; - if (count(lqw) > 0) { - LambdaUpdateWrapper luw = new LambdaUpdateWrapper(); - luw.eq(CtSettingSite::getSettingKey, key); - luw.set(CtSettingSite::getSettingValue, value); - boo = update(luw); - }else { - CtSettingSite site = new CtSettingSite(); - site.setContent(""); - site.setSettingKey(key); - site.setSettingValue(value); - boo = save(site); - } - if (boo) { - String prefix = String.format(SETTING_SITE_PREFIX, key); - redisUtils.set(prefix, value, CACHE_OVER_TIME); - } - return boo; - } - - @Override - public Boolean getGooleAuthSwitch() { - return "1".equals(settingSiteDao.getValueByKey("googleAuth")) ? true : false; - } -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/impl/SysQuartzJobServiceImpl.java b/wjcy-common/src/main/java/me/zhengjie/service/impl/SysQuartzJobServiceImpl.java deleted file mode 100644 index 1975f7c..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/impl/SysQuartzJobServiceImpl.java +++ /dev/null @@ -1,63 +0,0 @@ -//package me.zhengjie.service.impl; -// -//import cn.hutool.core.bean.BeanUtil; -//import com.baomidou.mybatisplus.core.conditions.Wrapper; -//import com.baomidou.mybatisplus.core.metadata.IPage; -//import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -//import lombok.RequiredArgsConstructor; -//import me.zhengjie.dao.SysQuartzJobDao; -//import me.zhengjie.entity.SysQuartzJob; -//import me.zhengjie.enums.TaskTypeEnum; -//import me.zhengjie.service.SysQuartzJobService; -//import me.zhengjie.service.vo.SysQuartzJobListVO; -//import me.zhengjie.utils.PageUtils; -//import me.zhengjie.utils.RedisUtils; -//import org.apache.logging.log4j.core.layout.SyslogLayout; -//import org.springframework.stereotype.Service; -// -//import javax.annotation.Resource; -// -///** -// * 定时任务(SysQuartzJob)表服务实现类 -// * -// * @author rch -// * @since 2022-07-20 -// */ -//@Service -//@RequiredArgsConstructor -//public class SysQuartzJobServiceImpl extends ServiceImpl implements SysQuartzJobService { -// -// @Resource -// private SysQuartzJobService sysQuartzJobService; -// @Resource -// private SysQuartzJobDao sysQuartzJobDao; -// -// private final QuartzJobRepository quartzJobRepository; -// private final QuartzLogRepository quartzLogRepository; -// private final QuartzManage quartzManage; -// private final RedisUtils redisUtils; -// -// @Override -// public PageUtils searchPageList(IPage page, Wrapper wrapper) { -// sysQuartzJobDao.searchPageList(page,wrapper); -// return new PageUtils(page.getTotal(),page.getRecords()); -// } -// -// @Override -// public boolean modifyJobStatus(Long jobId) { -// SysQuartzJob sysQuartzJobIsExist = sysQuartzJobService.getById(jobId); -// if(sysQuartzJobIsExist == null){ -// return false; -// }else{ -// SysQuartzJob sysQuartzJob = new SysQuartzJob(); -// BeanUtil.copyProperties(sysQuartzJobIsExist,sysQuartzJob); -// if(sysQuartzJob.getIsPause() == 0){ -// sysQuartzJob.setIsPause(1); -// }else{ -// sysQuartzJob.setIsPause(0); -// } -// return sysQuartzJobService.updateById(sysQuartzJob); -// } -// } -//} -// diff --git a/wjcy-common/src/main/java/me/zhengjie/service/impl/SysQuartzLogServiceImpl.java b/wjcy-common/src/main/java/me/zhengjie/service/impl/SysQuartzLogServiceImpl.java deleted file mode 100644 index aac7886..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/impl/SysQuartzLogServiceImpl.java +++ /dev/null @@ -1,35 +0,0 @@ -package me.zhengjie.service.impl; - -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import me.zhengjie.dao.SysQuartzJobDao; -import me.zhengjie.dao.SysQuartzLogDao; -import me.zhengjie.entity.SysQuartzJob; -import me.zhengjie.entity.SysQuartzLog; -import me.zhengjie.service.SysQuartzLogService; -import me.zhengjie.service.vo.SysQuartzLogListVO; -import me.zhengjie.utils.PageUtils; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; - -/** - * 定时任务(SysQuartzJob)表服务实现类 - * - * @author rch - * @since 2022-07-20 - */ -@Service -public class SysQuartzLogServiceImpl extends ServiceImpl implements SysQuartzLogService { - - @Resource - private SysQuartzLogDao sysQuartzLogDao; - - @Override - public PageUtils searchPageList(IPage page, Wrapper wrapper) { - sysQuartzLogDao.searchPageList(page, wrapper); - return new PageUtils(page.getTotal(), page.getRecords()); - } -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/impl/YdQuartzServiceImpl.java b/wjcy-common/src/main/java/me/zhengjie/service/impl/YdQuartzServiceImpl.java deleted file mode 100644 index d0b54b9..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/impl/YdQuartzServiceImpl.java +++ /dev/null @@ -1,464 +0,0 @@ -package me.zhengjie.service.impl; - -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.json.JSONUtil; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.config.BeanFactory; -import me.zhengjie.constant.Constants; -import me.zhengjie.entity.*; -import me.zhengjie.entity.quartz.*; -import me.zhengjie.enums.*; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.service.*; -import me.zhengjie.service.redission.LockCallBack; -import me.zhengjie.utils.HttpClientUtil; -import me.zhengjie.utils.RedissonUtil; -import org.redisson.api.RLock; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import javax.annotation.Resource; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -/** - * 影刀定时任务Service 实现类 - * - * @author rch - * @create 2022-08-01 - */ -@Service -@Slf4j -public class YdQuartzServiceImpl implements YdQuartzService { - - @Resource - private CtRebotService ctRebotService; - @Resource - private CtApplyService ctApplyService; - @Resource - private RedissonUtil redissonUtil; - @Resource - private CtClickFarmingService ctClickFarmingService; - @Resource - private CtBuyerService ctBuyerService; - @Resource - private CtClickOrderService ctClickOrderService; - @Resource - private DhAddCarOrderService dhAddCarOrderService; - @Resource - private DhAddCarService dhAddCarService; - @Resource - private CtBrowseService ctBrowseService; - - @Override - public Object executeOnLock(String lockKey, long time, long timeout, LockCallBack callBack) throws Exception { - RLock lock = redissonUtil.getRLock(lockKey); - String currentTime = me.zhengjie.utils.DateUtil.getCurrentTime(); - try { - log.info(currentTime + " 获取锁============= {}",lockKey); - if (lock.tryLock(time, timeout, TimeUnit.SECONDS)) { - System.out.println("run111 ====== lock success "); - return callBack.execute(true); - } else { - System.out.println("run111 ====== lock fail "); - throw new BadRequestException(" lock fail "); - } - } catch (Exception e) { - throw e; - } finally { - lock.unlock(); - log.info(currentTime+" 释放锁============= {}",lockKey); - } - } - - @Override - @Transactional(rollbackFor = Exception.class) - public String exec(String str) throws Exception { - Boss boss = JSONUtil.toBean(str, Boss.class); - // 1.根据设备id获取设备信息 for update - CtRebot ctRebot = ctRebotService.getByAccountNameLock(boss.getAccountName()); - System.out.println(JSONUtil.toJsonStr(ctRebot)); - if (ObjectUtil.isEmpty(ctRebot) || !YesOrNoEnum.NO.eqValue(ctRebot.getStatus())) { - // 有问题 不执行 - log.info("机器人设备信息不存在,或者机器人状态不可用!"); - throw new BadRequestException("机器人设备信息不存在,或者机器人状态不可用!"); - } - - // TODO 这里需要根据应用获取 appKey appSecret信息 - CtApply ctApply = ctApplyService.getById(boss.getApplyId()); - if (ObjectUtil.isEmpty(ctApply) - || ObjectUtil.isEmpty(ctApply.getRobotUuid()) - || ObjectUtil.isEmpty(ctApply.getAccessKeyId()) - || ObjectUtil.isEmpty(ctApply.getAccessKeySecret())) { - log.info("影刀应用信息不存在,或者影刀应用信息异常!"); - throw new BadRequestException("影刀应用信息不存在,或者影刀应用信息异常!"); - } - - // 判断买家是否占用 - List paramList = boss.getParams().stream().filter(n->n.getName().equals("account")).collect(Collectors.toList()); - if (ObjectUtil.isEmpty(paramList)) { - throw new BadRequestException("买家信息不存在!"); - } - String buyerName = paramList.get(0).getValue(); - CtBuyer ctBuyer = ctBuyerService.getBuyerOccupyStatusLock(buyerName); - if (ObjectUtil.isEmpty(ctBuyer) || BuyerOccupyStatusEnum.OCCUPIED.value().equals(ctBuyer.getOccupyStatus())) { - throw new BadRequestException("买家信息不存在,或者已占用状态!"); - } - - boss.setRobotUuid(ctApply.getRobotUuid()); - // token - Map params = new HashMap<>(16); - params.put("accessKeyId", ctApply.getAccessKeyId()); - params.put("accessKeySecret", ctApply.getAccessKeySecret()); - SecreInfo secreInfo = JSONUtil.toBean(HttpClientUtil.getHttp(Constants.GET_SECRET, params), SecreInfo.class); - if (!secreInfo.getSuccess()) { - log.info("=========鉴权异常=========="); - throw new BadRequestException("请求影刀鉴权异常!"); - } - String token = secreInfo.getData().getAccessToken(); - System.out.println("====token===="); - Map headers = new HashMap<>(16); - headers.put("Accept", "application/json"); - headers.put("Content-Type", "application/json;charset=utf-8"); - headers.put("authorization", "Bearer " + token); - - // 判断是否在线 - RebotStatu rebotStatu = new RebotStatu(ctRebot.getRobotClientUuid(), ctRebot.getAccountName()); - String returnStr = HttpClientUtil.postJson(Constants.REBOT_STATU, headers, JSONUtil.toJsonStr(rebotStatu), "utf-8"); - RebotStatuReturn rebotStatuReturn = JSONUtil.toBean(returnStr, RebotStatuReturn.class); - // 状态 connected:已连接 idle:空闲 running:运行中 allocated:已分配 abnormal:异常 offline:离线 - if (RobotStatusEnum.OFFLINE.value().equals(rebotStatuReturn.getData().getStatus())) { - log.info("=======设备不在线====="); - throw new BadRequestException("设备不在线!"); - } else if (RobotStatusEnum.RUNNING.value().equals(rebotStatuReturn.getData().getStatus())) { - log.info("=======设备运行中====="); - throw new BadRequestException("设备运行中!"); - } else if (RobotStatusEnum.ALLOCATED.value().equals(rebotStatuReturn.getData().getStatus())) { - log.info("=======设备已分配====="); - throw new BadRequestException("设备已分配!"); - } else if (RobotStatusEnum.ABNORMAL.value().equals(rebotStatuReturn.getData().getStatus())) { - log.info("=======设备异常====="); - throw new BadRequestException("设备异常!"); - } - // 启动Job - String returnJobStr = null; - CtRebot updateCtRebot = new CtRebot(); - updateCtRebot.setId(ctRebot.getId()); - updateCtRebot.setStatus(YesOrNoEnum.YES.value()); - CtRebotService ctRebotService = BeanFactory.getBean(CtRebotService.class); - Boolean resultBoolean = ctRebotService.updateById(updateCtRebot); - if (resultBoolean) { - // 修改买家信息占用状态 - ctBuyer.setOccupyStatus(BuyerOccupyStatusEnum.OCCUPIED.value()); - if (ctBuyerService.updateById(ctBuyer)) { - returnJobStr = HttpClientUtil.postJson(Constants.STAT_JOB_URL, headers, JSONUtil.toJsonStr(boss), "utf-8"); - StartYdReturnInfo startYdReturnInfo = JSONUtil.toBean(returnJobStr, StartYdReturnInfo.class); - if (startYdReturnInfo.getSuccess()) { - log.info("run111 执行成功,返回结果为: {}" + returnJobStr); - } else { - throw new BadRequestException(startYdReturnInfo.getMsg()); - } - } else { - log.info("run111 执行成功。 但是修改设备状态失败----- 此处该预警"); - throw new BadRequestException("修改设备状态失败!"); - } - } else { - log.info("run111 执行成功。 但是修改设备状态失败----- 此处该预警"); - throw new BadRequestException("修改设备状态失败!"); - } - return returnJobStr; - } - - @Override - @Transactional(rollbackFor = Exception.class) - public Boolean clickFarmExec(String str) throws Exception { - System.out.println("================================ClickFarmTask=========================4"); - // 只有真正发起了执行 状态才修改为执行中 回调后修改成功 或者失败 - // TODO 这里根据响应结果 修改平台状态 类型,根据boss里面的 执行中 别的任务如果想再执行这个刷单信息, 不允许执行。 执行前加锁查询, 带执行状态才可以往下走 - // 修改状态为 执行中。 - - Boss boss = JSONUtil.toBean(str, Boss.class); - List paramList = boss.getParams(); - // 获取ID - String id = paramList.stream().filter(p->p.getName().equals("id")).collect(Collectors.toList()).get(0).getValue(); - CtClickFarming ctClickFarming = ctClickFarmingService.getByIdLock(Long.valueOf(id)); - if (ClickFarmingStatusEnum.IN_EXECUTION.value().equals(ctClickFarming.getStatus())) { - throw new BadRequestException("该定时任务对应的刷单信息已经执行中状态,请检查后重试!"); - } - - if (ClickFarmingStatusEnum.EXECUTION_SUCCESS.value().equals(ctClickFarming.getStatus())) { - throw new BadRequestException("该定时任务对应的刷单信息已执行成功,请检查后重试!"); - } - - String returnStartJobStr = exec(str); - if (ObjectUtil.isEmpty(returnStartJobStr)) { - throw new BadRequestException("调用影刀启动任务失败! response:" + returnStartJobStr); - } - - YdStartReturn ydStartReturn = JSONUtil.toBean(returnStartJobStr, YdStartReturn.class); - if (!ydStartReturn.getSuccess()) { - throw new BadRequestException("调用影刀启动任务失败! response:" + returnStartJobStr); - } - - // 修改状态 带执行 - 》 执行中 - CtClickFarming updateCtClickFarming = new CtClickFarming(); - updateCtClickFarming.setId(ctClickFarming.getId()); - updateCtClickFarming.setStatus(ClickFarmingStatusEnum.IN_EXECUTION.value()); - return ctClickFarmingService.updateById(updateCtClickFarming); - } - - - @Override - @Transactional(rollbackFor = Exception.class) - public Boolean addCarExec(String str) throws Exception { - System.out.println("================================ClickFarmTask=========================4"); - // 只有真正发起了执行 状态才修改为执行中 回调后修改成功 或者失败 - // TODO 这里根据响应结果 修改平台状态 类型,根据boss里面的 执行中 别的任务如果想再执行这个刷单信息, 不允许执行。 执行前加锁查询, 带执行状态才可以往下走 - // 修改状态为 执行中。 - - Boss boss = JSONUtil.toBean(str, Boss.class); - List paramList = boss.getParams(); - // 获取ID - String id = paramList.stream().filter(p->p.getName().equals("id")).collect(Collectors.toList()).get(0).getValue(); - DhAddCar dhAddCar = dhAddCarService.getByIdLock(Long.valueOf(id)); - if (!DhAddCarStatusEnum.TOBE_EXECUTION.value().equals(dhAddCar.getStatus()) && !DhAddCarStatusEnum.ADD_CARD_FAILE.value().equals(dhAddCar.getStatus())) { - throw new BadRequestException("该定时任务对应的敦煌加购必须带执行或执行失败,请检查后重试!"); - } - - if (DhAddCarStatusEnum.Add_CARD_SUCCESS.value().equals(dhAddCar.getStatus())) { - throw new BadRequestException("该定时任务对应的敦煌加购已执行成功,请检查后重试!"); - } - - String returnStartJobStr = exec(str); - if (ObjectUtil.isEmpty(returnStartJobStr)) { - throw new BadRequestException("调用影刀启动任务失败! response:" + returnStartJobStr); - } - - YdStartReturn ydStartReturn = JSONUtil.toBean(returnStartJobStr, YdStartReturn.class); - if (!ydStartReturn.getSuccess()) { - throw new BadRequestException("调用影刀启动任务失败! response:" + returnStartJobStr); - } - - // 修改状态 带执行 - 》 执行中 - DhAddCar updateDhAddCar = new DhAddCar(); - updateDhAddCar.setId(dhAddCar.getId()); - updateDhAddCar.setStatus(ClickFarmingStatusEnum.IN_EXECUTION.value()); - return dhAddCarService.updateById(updateDhAddCar); - } - - - @Override - @Transactional(rollbackFor = Exception.class) - public Boolean catchOrderExec(String str) throws Exception { - System.out.println("================================catchOrderExec=========================4"); - // 只有真正发起了执行 状态才修改为执行中 回调后修改成功 或者失败 - // TODO 这里根据响应结果 修改平台状态 类型,根据boss里面的 执行中 别的任务如果想再执行这个刷单信息, 不允许执行。 执行前加锁查询, 带执行状态才可以往下走 - // 修改状态为 执行中。 - - Boss boss = JSONUtil.toBean(str, Boss.class); - List paramList = boss.getParams(); - // 获取ID - String id = paramList.stream().filter(p->p.getName().equals("id")).collect(Collectors.toList()).get(0).getValue(); - DhAddCar dhAddCar = dhAddCarService.getByIdLock(Long.valueOf(id)); - if (!DhAddCarStatusEnum.TO_BE_CATCH_ORDER.value().equals(dhAddCar.getStatus()) && !DhAddCarStatusEnum.CATCH_ORDER_FAILE.value().equals(dhAddCar.getStatus())) { - throw new BadRequestException("该定时任务对应的敦煌加购抓单必须是待抓单或者抓单失败状态!"); - } - - String returnStartJobStr = exec(str); - if (ObjectUtil.isEmpty(returnStartJobStr)) { - throw new BadRequestException("调用影刀启动任务失败! response:" + returnStartJobStr); - } - - YdStartReturn ydStartReturn = JSONUtil.toBean(returnStartJobStr, YdStartReturn.class); - if (!ydStartReturn.getSuccess()) { - throw new BadRequestException("调用影刀启动任务失败! response:" + returnStartJobStr); - } - - // 修改状态 带抓单/抓单失败 - 》 抓单中 - DhAddCar updateDhAddCar = new DhAddCar(); - updateDhAddCar.setId(dhAddCar.getId()); - updateDhAddCar.setStatus(DhAddCarStatusEnum.CATCH_ORDER_ING.value()); - return dhAddCarService.updateById(updateDhAddCar); - } - - - // TODO 这里查询任务结果然后返回, 在回调哪里 调用这个方法,然后解析参数, 入参 出参 和执行结果状态等。 - @Override - @Transactional(rollbackFor = Exception.class) - public JobQueryByUuidReturn queryJobUuid(String uuid, String accessKeyId, String accessKeySecret) { - // token - Map params = new HashMap<>(16); - params.put("accessKeyId", accessKeyId); - params.put("accessKeySecret", accessKeySecret); - String response = HttpClientUtil.getHttp(Constants.GET_SECRET, params); - log.error("鉴权请求结果:" +response); - SecreInfo secreInfo = JSONUtil.toBean(response, SecreInfo.class); - if (ObjectUtil.isEmpty(secreInfo) || !secreInfo.getSuccess()) { - log.info("=========鉴权异常=========="); - throw new BadRequestException("请求影刀鉴权异常!"); - } - String token = secreInfo.getData().getAccessToken(); - Map headers = new HashMap<>(16); - headers.put("Accept", "application/json"); - headers.put("Content-Type", "application/json;charset=utf-8"); - headers.put("authorization", "Bearer " + token); - - // 判断是否在线 - JobQueryByUuid jobQueryByUuid = new JobQueryByUuid(); - jobQueryByUuid.setJobUuid(uuid); - String returnStr = HttpClientUtil.postJson(Constants.QUERY_JOB_URL, headers, JSONUtil.toJsonStr(jobQueryByUuid), "utf-8"); - log.info("====returnStr====" + returnStr); - JobQueryByUuidReturn jobQueryByUuidReturn = JSONUtil.toBean(returnStr, JobQueryByUuidReturn.class); - - return jobQueryByUuidReturn; - } - - @Override - @Transactional(rollbackFor = Exception.class) - public Boolean clickFarmSuppleMentExec(String str) throws Exception { - System.out.println("================================ClickFarmSuppleMentTask=========================4"); - // 只有真正发起了执行 状态才修改为执行中 回调后修改成功 或者失败 - // TODO 这里根据响应结果 修改平台状态 类型,根据boss里面的 执行中 别的任务如果想再执行这个刷单信息, 不允许执行。 执行前加锁查询, 带执行状态才可以往下走 - // 修改状态为 执行中。 - - Boss boss = JSONUtil.toBean(str, Boss.class); - List paramList = boss.getParams(); - // 获取ID - String id = paramList.stream().filter(p->p.getName().equals("id")).collect(Collectors.toList()).get(0).getValue(); - CtClickFarming ctClickFarming = ctClickFarmingService.getByIdLock(Long.valueOf(id)); - if (!ClickFarmingStatusEnum.AWAITING_PAYMENT.value().equals(ctClickFarming.getStatus())) { - throw new BadRequestException("仅待支付状态才允许补录,请检查后重试!"); - } - - String returnStartJobStr = exec(str); - if (ObjectUtil.isEmpty(returnStartJobStr)) { - throw new BadRequestException("调用影刀启动任务失败! response:" + returnStartJobStr); - } - - YdStartReturn ydStartReturn = JSONUtil.toBean(returnStartJobStr, YdStartReturn.class); - if (!ydStartReturn.getSuccess()) { - throw new BadRequestException("调用影刀启动任务失败! response:" + returnStartJobStr); - } - - // 修改状态 带执行 - 》 执行中 - CtClickFarming updateCtClickFarming = new CtClickFarming(); - updateCtClickFarming.setId(ctClickFarming.getId()); - updateCtClickFarming.setStatus(ClickFarmingStatusEnum.IN_EXECUTION.value()); - return ctClickFarmingService.updateById(updateCtClickFarming); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public Object dhWellReceivedExec(String str) throws Exception { - System.out.println("================================WellReceivedExec=========================4"); - // 只有真正发起了执行 状态才修改为执行中 回调后修改成功 或者失败 - // 修改状态为 执行中。 - - Boss boss = JSONUtil.toBean(str, Boss.class); - List paramList = boss.getParams(); - // 获取ID - String id = paramList.stream().filter(p->p.getName().equals("id")).collect(Collectors.toList()).get(0).getValue(); - DhAddCarOrder dhAddCarOrder = dhAddCarOrderService.getByIdLock(Long.valueOf(id)); - if (ClickOrderStatusEnum.IN_EXECUTION.value().equals(dhAddCarOrder.getStatus())) { - throw new BadRequestException("该定时任务对应的敦煌加购好评信息已经执行中状态,请检查后重试!"); - } - - if (ClickFarmingStatusEnum.EXECUTION_SUCCESS.value().equals(dhAddCarOrder.getStatus())) { - throw new BadRequestException("该定时任务对应的敦煌加购好评信息已执行成功,请检查后重试!"); - } - - String returnStartJobStr = exec(str); - if (ObjectUtil.isEmpty(returnStartJobStr)) { - throw new BadRequestException("调用影刀启动任务失败! response:" + returnStartJobStr); - } - - YdStartReturn ydStartReturn = JSONUtil.toBean(returnStartJobStr, YdStartReturn.class); - if (!ydStartReturn.getSuccess()) { - throw new BadRequestException("调用影刀启动任务失败! response:" + returnStartJobStr); - } - - // 修改状态 带执行 - 》 执行中 - DhAddCarOrder updateDhAddCarOrder = new DhAddCarOrder(); - updateDhAddCarOrder.setId(dhAddCarOrder.getId()); - updateDhAddCarOrder.setStatus(ClickOrderStatusEnum.IN_EXECUTION.value()); - return dhAddCarOrderService.updateById(updateDhAddCarOrder); - } - - - @Override - @Transactional(rollbackFor = Exception.class) - public Object wellReceivedExec(String str) throws Exception { - System.out.println("================================WellReceivedExec=========================4"); - // 只有真正发起了执行 状态才修改为执行中 回调后修改成功 或者失败 - // 修改状态为 执行中。 - - Boss boss = JSONUtil.toBean(str, Boss.class); - List paramList = boss.getParams(); - // 获取ID - String id = paramList.stream().filter(p->p.getName().equals("id")).collect(Collectors.toList()).get(0).getValue(); - CtClickOrder ctClickOrder = ctClickOrderService.getByIdLock(Long.valueOf(id)); - if (ClickOrderStatusEnum.IN_EXECUTION.value().equals(ctClickOrder.getStatus())) { - throw new BadRequestException("该定时任务对应的敦煌加购好评信息已经执行中状态,请检查后重试!"); - } - - if (ClickFarmingStatusEnum.EXECUTION_SUCCESS.value().equals(ctClickOrder.getStatus())) { - throw new BadRequestException("该定时任务对应的敦煌加购好评信息已执行成功,请检查后重试!"); - } - - String returnStartJobStr = exec(str); - if (ObjectUtil.isEmpty(returnStartJobStr)) { - throw new BadRequestException("调用影刀启动任务失败! response:" + returnStartJobStr); - } - - YdStartReturn ydStartReturn = JSONUtil.toBean(returnStartJobStr, YdStartReturn.class); - if (!ydStartReturn.getSuccess()) { - throw new BadRequestException("调用影刀启动任务失败! response:" + returnStartJobStr); - } - - // 修改状态 带执行 - 》 执行中 - CtClickOrder updateCtClickOrder = new CtClickOrder(); - updateCtClickOrder.setId(ctClickOrder.getId()); - updateCtClickOrder.setStatus(ClickOrderStatusEnum.IN_EXECUTION.value()); - return ctClickOrderService.updateById(updateCtClickOrder); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public Object browseTaskExec(String str) throws Exception { - System.out.println("================================browseTaskExec=========================4"); - // 只有真正发起了执行 状态才修改为执行中 回调后修改成功 或者失败 - // 修改状态为 执行中。 - - Boss boss = JSONUtil.toBean(str, Boss.class); - List paramList = boss.getParams(); - // 获取ID - String id = paramList.stream().filter(p->p.getName().equals("id")).collect(Collectors.toList()).get(0).getValue(); - CtBrowse ctBrowse = ctBrowseService.getByIdLock(Long.valueOf(id)); - if (ClickOrderStatusEnum.IN_EXECUTION.value().equals(ctBrowse.getStatus())) { - throw new BadRequestException("该定时任务对应的订单信息已经执行中状态,请检查后重试!"); - } - - if (ClickFarmingStatusEnum.EXECUTION_SUCCESS.value().equals(ctBrowse.getStatus())) { - throw new BadRequestException("该定时任务对应的订单信息已执行成功,请检查后重试!"); - } - - String returnStartJobStr = exec(str); - if (ObjectUtil.isEmpty(returnStartJobStr)) { - throw new BadRequestException("调用影刀启动任务失败! response:" + returnStartJobStr); - } - - YdStartReturn ydStartReturn = JSONUtil.toBean(returnStartJobStr, YdStartReturn.class); - if (!ydStartReturn.getSuccess()) { - throw new BadRequestException("调用影刀启动任务失败! response:" + returnStartJobStr); - } - - // 修改状态 带执行 - 》 执行中 - CtBrowse updateCtBrowse = new CtBrowse(); - updateCtBrowse.setId(ctBrowse.getId()); - updateCtBrowse.setStatus(ClickOrderStatusEnum.IN_EXECUTION.value()); - return ctBrowseService.updateById(updateCtBrowse); - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/service/redission/LockCallBack.java b/wjcy-common/src/main/java/me/zhengjie/service/redission/LockCallBack.java deleted file mode 100644 index 8d8b5ff..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/redission/LockCallBack.java +++ /dev/null @@ -1,8 +0,0 @@ -package me.zhengjie.service.redission; - -@FunctionalInterface -public interface LockCallBack { - - Object execute(T t); - -} diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/AdminGoogleAuthInfoVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/AdminGoogleAuthInfoVO.java deleted file mode 100644 index 4e5973e..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/AdminGoogleAuthInfoVO.java +++ /dev/null @@ -1,31 +0,0 @@ -package me.zhengjie.service.vo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - *

- * Admin 秘钥信息 - *

- * - * @author: rch - * @since: 2020-08-26 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class AdminGoogleAuthInfoVO { - - /** Google 总开关 */ - private Boolean gogoleAuthSwitch; - - /** 用户信息 */ - private String userName; - - /** 二维码url 信息 */ - private String qrBarCodeUrl; - - /** 明文秘钥 */ - private String secret; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/BuyOrderResponseAddressVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/BuyOrderResponseAddressVO.java deleted file mode 100644 index 2364b02..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/BuyOrderResponseAddressVO.java +++ /dev/null @@ -1,39 +0,0 @@ -package me.zhengjie.service.vo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 下注成功订单响应收货地址信息(CtResponseOrderAddress)表实体类 - * - * @author rch - * @since 2022-06-23 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class BuyOrderResponseAddressVO { - - /** 地址1 */ - private String addressline1; - /** 国家 */ - private String country; - /** 州 */ - private String state; - /** 电话 */ - private String tel; - /** lastname */ - private String lastname; - /** 税号 */ - private String vatNumber; - /** 城市 */ - private String city; - /** 地址2 */ - private String addressline2; - /** firstname */ - private String firstname; - /** 邮政编码 */ - private String postalcode; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/BuyOrderResponseOrderVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/BuyOrderResponseOrderVO.java deleted file mode 100644 index be0997d..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/BuyOrderResponseOrderVO.java +++ /dev/null @@ -1,54 +0,0 @@ -package me.zhengjie.service.vo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.Date; - -/** - * 下单成功响应订单商品信息(CtResponseOrder)表实体类 - * - * @author rch - * @since 2022-06-23 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class BuyOrderResponseOrderVO { - - private Long id; - /** 运费 */ - private Double shipCost; - /** 产品总价 */ - private Double totalPriceOfProduct; - /** 备货期 */ - private Double leadingTime; - /** 订单总价 */ - private Double orderTotal; - /** 卖家Id */ - private String supplierId; - /** 卖家店铺coupon */ - private Double couponOfSeller; - /** 运输方式 */ - private String shipType; - /** 订单优惠 */ - private Double orderSave; - /** 税费手续费 */ - private Double taxCharge; - /** 买家Id */ - private String buyerId; - /** 税费 */ - private Double tax; - /** 促销折扣 */ - private Double promoDiscount; - /** 订单号--这个要特殊处理这个是对应响应的id字段 */ - private Long orderId; - /** DHcoupon */ - private Double couponDiscount; - /** 下单站点 */ - private String siteId; - /** 创建时间 */ - private Date createTime; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/BuyOrderResponseProductVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/BuyOrderResponseProductVO.java deleted file mode 100644 index 5f603a5..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/BuyOrderResponseProductVO.java +++ /dev/null @@ -1,81 +0,0 @@ -package me.zhengjie.service.vo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.math.BigDecimal; -import java.util.Date; - -/** - * 下单订单响应产品信息(CtResponseOrderProduct)表实体类 - * - * @author rch - * @since 2022-06-23 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class BuyOrderResponseProductVO { - - /** 秒杀类型 */ - private String flashDeals; - /** 卖家设置价格 */ - private Double prodPriceOrg; - /** 产品skuId */ - private String skuId; - /** 购买数量 */ - private Integer cateDispId; - /** 商品总金额 */ - private Double amount; - /** 发布类目id */ - private String catePubId; - /** 促销折扣 */ - private Double promDis; - /** 产品单位名称 */ - private String measureName; - /** 短描 */ - private String shortDescription; - /** 卖家承诺运达天数 */ - private Integer promiseDays; - /** 备货国家 */ - private String stockin; - /** 产品图片(小图) */ - private String thumbnailImage; - /** 是否为样品 */ - private String isSample; - /** 最终运费 */ - private Double shipCost; - /** 卖家Id */ - private String supplierId; - /** 跨店满减金额 */ - private BigDecimal crossReduceAmount; - /** 产品itemcode */ - private Integer itemcode; - /** buyer选择的运输方式 */ - private String shipType; - /** 销售价格 */ - private Double originPrice; - /** 产品长描地址 */ - private String htmlUrl; - /** 产品图片(大图) */ - private String imageUrl; - /** 最终价格 */ - private Double price; - /** 产品URL */ - private String productUrl; - /** 备注 */ - private String remark; - /** lots */ - private Integer lots; - /** 产品名称 */ - private String productName; - /** 产品Id */ - private String productId; - /** 产品skumd5 */ - private String skuMd5; - /** 创建时间 */ - private Date createTime; - /** 产品单位Id */ - private String measureId; -} \ No newline at end of file diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/BuyOrderVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/BuyOrderVO.java deleted file mode 100644 index 37dd881..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/BuyOrderVO.java +++ /dev/null @@ -1,24 +0,0 @@ -package me.zhengjie.service.vo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.List; - -/** - * 订单下单API响应对象 - * - * @author rch - * @create 2022-06-27 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class BuyOrderVO { - - /** 接口响应状态 响应码 响应内容等信息*/ - private OrderResponStatusVO status; - /** 接口响应订单信息 */ - private List orderList; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtApplyInfoVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/CtApplyInfoVO.java deleted file mode 100644 index e1c57a1..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtApplyInfoVO.java +++ /dev/null @@ -1,19 +0,0 @@ -package me.zhengjie.service.vo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 应用信息(ct_apply) VO - * @Author zhw - * @Date 2022-08-01 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtApplyInfoVO { - - private Long id; - private String name; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtApplyListVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/CtApplyListVO.java deleted file mode 100644 index 04270b8..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtApplyListVO.java +++ /dev/null @@ -1,68 +0,0 @@ -package me.zhengjie.service.vo; - - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 应用信息表(CtApply)表实体类 分页查询VO - * @author zhw - * @Data 2022-07-23 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("应用信息表") -public class CtApplyListVO { - - @ApiModelProperty(value = "id") - private Long id; - - @ApiModelProperty(value = "平台Id") - private Long platformId; - - @ApiModelProperty(value = "创建时间") - private String createdAt; - - @ApiModelProperty(value = "修改时间") - private String updatedAt; - - /** 操作人账号 */ - @ApiModelProperty(value = "操作人账号") - private String gmName; - - /** 应用名称 */ - @ApiModelProperty(value = "应用名称") - private String name; - - /** 任务名称 */ - @ApiModelProperty(value = "任务名称") - private String taskName; - - /** 方法名称 */ - @ApiModelProperty(value = "方法名称") - private String methodName; - - /** accessKeyID */ - @ApiModelProperty(value = "accessKeyID") - private String accessKeyId; - - /** accessKeySecret */ - @ApiModelProperty(value = "accessKeySecret") - private String accessKeySecret; - - /** 应用id */ - @ApiModelProperty(value = "应用id") - private String robotUuid; - - /** 备注 */ - @ApiModelProperty(value = "备注") - private String remark; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtBrowseDetailVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/CtBrowseDetailVO.java deleted file mode 100644 index 0a4b4ff..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtBrowseDetailVO.java +++ /dev/null @@ -1,73 +0,0 @@ -package me.zhengjie.service.vo; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.math.BigDecimal; -import java.util.Date; - -/** - * 收藏浏览信息表(CtCard)表实体类 详情Detail - * - * @author rch - * @since 2022-07-09 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("收藏浏览详情") -public class CtBrowseDetailVO { - - @ApiModelProperty(value = "id") - private Long id; - - @ApiModelProperty(value = "创建时间") - private String createdAt; - - @ApiModelProperty(value = "修改时间") - private String updatedAt; - - /** 操作人账号*/ - @ApiModelProperty(value = "操作人账号") - private String gmName; - - /** 买家ID */ - @ApiModelProperty(value = "买家ID") - private Long buyerId; - - /** 国家 */ - @ApiModelProperty(value = "国家") - private String country; - - /** 账号 */ - @ApiModelProperty(value = "账号") - private String account; - - /** 密码 */ - @ApiModelProperty(value = "密码") - private String pwd; - - /** vpn分享链接 */ - @ApiModelProperty(value = "vpn分享链接") - private String vpnShare; - - /** 收藏链接 */ - @ApiModelProperty(value = "收藏链接") - private String linkUrl; - - /** 状态描述 */ - @ApiModelProperty(value = "状态描述") - private String paymentResults; - - /** 状态 1.待执行 2.执行中 3.执行成功 4.执行失败 */ - @ApiModelProperty(value = "状态 1.待执行 2.执行中 3.执行成功 4.执行失败") - private Integer status; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtBrowseListVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/CtBrowseListVO.java deleted file mode 100644 index 02d75fa..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtBrowseListVO.java +++ /dev/null @@ -1,63 +0,0 @@ -package me.zhengjie.service.vo; - -import com.baomidou.mybatisplus.extension.activerecord.Model; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.Date; - -/** - * 浏览收藏(CtBrowse)表实体类 VO - * - * @author rch - * @since 2022-11-04 09:45:31 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("浏览收藏VO") -public class CtBrowseListVO extends Model { - /** 主键ID */ - @ApiModelProperty(value = "主键ID") - private Long id; - - /** 买家ID */ - @ApiModelProperty(value = "买家ID") - private Long buyerId; - - /** 国家 */ - @ApiModelProperty(value = "国家") - private String country; - - /** 账号 */ - @ApiModelProperty(value = "账号") - private String account; - - /** 收藏链接 */ - @ApiModelProperty(value = "收藏链接") - private String linkUrl; - - /** 创建时间 */ - @ApiModelProperty(value = "创建时间") - private Date createdAt; - - /** 修改时间 */ - @ApiModelProperty(value = "修改时间") - private Date updatedAt; - - /** 状态描述 */ - @ApiModelProperty(value = "状态描述") - private String paymentResults; - - /** 状态 1.待执行 2.执行中 3.执行成功 4.执行失败 */ - @ApiModelProperty(value = "状态 1.待执行 2.执行中 3.执行成功 4.执行失败") - private Integer status; - - /** 操作人账号 */ - @ApiModelProperty(value = "操作人账号") - private String gmName; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtBuyerClickFarmVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/CtBuyerClickFarmVO.java deleted file mode 100644 index 21ff831..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtBuyerClickFarmVO.java +++ /dev/null @@ -1,103 +0,0 @@ -package me.zhengjie.service.vo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.math.BigDecimal; - -/** - * 买家信息表(CtBuyer)表实体类 详情Detail -刷单信息模块使用 - * - * @author rch - * @since 2022-09-20 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtBuyerClickFarmVO { - - private Long id; - - /** 创建时间 */ - private String createdAt; - - /** 修改时间 */ - private String updatedAt; - - /** 昵称*/ - private String nickName; - - /** 账号*/ - private String account; - - /** 密码*/ - private String pwd; - - /** 平台名称 */ - private Integer platformId; - - /** 平台名称 */ - private String platformName; - - /** 平台名称 */ - private Integer companyId; - - /** 公司名称 */ - private String companyName; - - /** 操作人账号*/ - private String gmName; - - ////////////////////////////////////// 新增字段 - /** 国家 */ - private String contntryShort; - /** VPN_ID(导入excel里包含) */ - private Long vpnId; - private String ipAddress; - private String link; - - /** 信用卡ID */ - private Long cardId; - private String number; - private String pinNumber; - private String holderSurname; - private String holderName; - - /** 用户等级(导入默认内部账号) 1.普通 2.精品 3.压力 4.内部账号 */ - private Integer level; - /** 占用状态 1.已占用 2.未占用 */ - private Integer occupyStatus; - /** 占用账户 */ - private String occupyAccount; - /** 账户余额 */ - private BigDecimal balance; - /** 账户购买总金额 */ - private BigDecimal buyTotalMoney; - - /** 状态(导入默认正常) 1.待注册 2待验证 3.待完善 4.正常 5.异常 6.可用但已用 7.删除 */ - private Integer status; - - // ==================地址信息相关========================================begin - /** 地址1 */ - private String addressline1; - /** 国家 */ - private String country; - /** 州 */ - private String state; - /** 电话 */ - private String tel; - /** lastname */ - private String lastname; - /** 税号 */ - private String vatNumber; - /** 城市 */ - private String city; - /** 地址2 */ - private String addressline2; - /** firstname */ - private String firstname; - /** 邮政编码 */ - private String postalcode; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtBuyerDetailVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/CtBuyerDetailVO.java deleted file mode 100644 index 12f1baf..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtBuyerDetailVO.java +++ /dev/null @@ -1,162 +0,0 @@ -package me.zhengjie.service.vo; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.math.BigDecimal; - -/** - * 买家信息表(CtBuyer)表实体类 详情Detail - * - * @author rch - * @since 2022-07-07 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("买家详情") -public class CtBuyerDetailVO { - - @ApiModelProperty(value = "id") - private Long id; - - /** 创建时间 */ - @ApiModelProperty(value = "创建时间") - private String createdAt; - - /** 修改时间 */ - @ApiModelProperty(value = "修改时间") - private String updatedAt; - - /** 昵称 */ - @ApiModelProperty(value = "昵称") - private String nickName; - - /** 账号 */ - @ApiModelProperty(value = "账号") - private String account; - - /** 密码 */ - @ApiModelProperty(value = "密码") - private String pwd; - - /** 平台ID */ - @ApiModelProperty(value = "平台ID") - private Integer platformId; - - /** 平台名称 */ - @ApiModelProperty(value = "平台名称") - private String platformName; - - /** 公司ID */ - @ApiModelProperty(value = "公司ID") - private Integer companyId; - - /** 公司名称 */ - @ApiModelProperty(value = "公司名称") - private String companyName; - - /** 操作人账号*/ - @ApiModelProperty(value = "操作人账号") - private String gmName; - - ////////////////////////////////////// 新增字段 - /** 国家 */ - @ApiModelProperty(value = "国家") - private String contntryShort; - - /** VPN_ID(导入excel里包含) */ - @ApiModelProperty(value = "VPN_ID") - private Long vpnId; - - @ApiModelProperty(value = "Vpn-Ip") - private String ipAddress; - - @ApiModelProperty(value = "vpn分享链接") - private String vpn; - - /** 信用卡ID */ - @ApiModelProperty(value = "信用卡ID") - private Long cardId; - - @ApiModelProperty(value = "信用卡卡号") - private String number; - - @ApiModelProperty(value = "信用卡密码") - private String cardPwd; - - @ApiModelProperty(value = "信用卡姓氏") - private String holderSurname; - - @ApiModelProperty(value = "信用卡名称") - private String holderName; - - /** 用户等级(导入默认内部账号) 1.普通 2.精品 3.压力 4.内部账号 */ - @ApiModelProperty(value = "用户等级(导入默认内部账号) 1.普通 2.精品 3.压力 4.内部账号") - private Integer level; - - /** 占用状态 1.已占用 2.未占用 */ - @ApiModelProperty(value = "占用状态 1.已占用 2.未占用") - private Integer occupyStatus; - - /** 占用账户 */ - @ApiModelProperty(value = "占用账户") - private String occupyAccount; - - /** 账户余额 */ - @ApiModelProperty(value = "账户余额") - private BigDecimal balance; - - /** 账户购买总金额 */ - @ApiModelProperty(value = "账户购买总金额") - private BigDecimal buyTotalMoney; - - /** 状态(导入默认正常) 1.待注册 2待验证 3.待完善 4.正常 5.异常 6.可用但已用 7.删除 */ - @ApiModelProperty(value = "状态(导入默认正常) 1.待注册 2待验证 3.待完善 4.正常 5.异常 6.可用但已用 7.删除") - private Integer status; - - // ==================地址信息相关========================================begin - /** 地址1 */ - @ApiModelProperty(value = "地址1") - private String addressline1; - - /** 国家 */ - @ApiModelProperty(value = "国家") - private String country; - - /** 州 */ - @ApiModelProperty(value = "州") - private String state; - - /** 电话 */ - @ApiModelProperty(value = "电话") - private String tel; - - /** lastname */ - @ApiModelProperty(value = "lastname") - private String lastname; - - /** 税号 */ - @ApiModelProperty(value = "税号") - private String vatNumber; - - /** 城市 */ - @ApiModelProperty(value = "城市") - private String city; - - /** 地址2 */ - @ApiModelProperty(value = "地址2") - private String addressline2; - - /** firstname */ - @ApiModelProperty(value = "firstname") - private String firstname; - - /** 邮政编码 */ - @ApiModelProperty(value = "邮政编码") - private String postalcode; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtBuyerListVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/CtBuyerListVO.java deleted file mode 100644 index b6a7f57..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtBuyerListVO.java +++ /dev/null @@ -1,111 +0,0 @@ -package me.zhengjie.service.vo; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 买家信息表(CtBuyer)表实体类 分页查询Detail - * - * @author rch - * @since 2022-07-07 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel -public class CtBuyerListVO { - - @ApiModelProperty(value = "Id") - private Long id; - - /** 创建时间 */ - @ApiModelProperty(value = "创建时间") - private String createdAt; - - /** 修改时间 */ - @ApiModelProperty(value = "修改时间") - private String updatedAt; - - /** 昵称 */ - @ApiModelProperty(value = "昵称") - private String nickName; - - /** 账号 */ - @ApiModelProperty(value = "账号") - private String account; - - /** 密码 */ - @ApiModelProperty(value = "密码") - private String pwd; - - /** 平台id */ - @ApiModelProperty(value = "平台id") - private Integer platformId; - - /** 平台名称 */ - @ApiModelProperty(value = "平台名称") - private String platformName; - - /** 公司id */ - @ApiModelProperty(value = "公司id") - private Long companyId; - - /** 公司名称 */ - @ApiModelProperty(value = "公司名称") - private String companyName; - - /** 操作人账号*/ - @ApiModelProperty(value = "操作人账号") - private String gmName; - - ////////////////////////////////////// 新增字段 - /** 国家 */ - @ApiModelProperty(value = "国家") - private String contntryShort; - - /** VPN_ID(导入excel里包含) */ - @ApiModelProperty(value = "VPN_ID") - private Long vpnId; - - @ApiModelProperty(value = "Vpn-Ip") - private String ipAddress; - - @ApiModelProperty(value = "vpn分享链接") - private String vpn; - - /** 信用卡ID */ - @ApiModelProperty(value = "信用卡ID") - private Long cardId; - - @ApiModelProperty(value = "信用卡卡号") - private String number; - - @ApiModelProperty(value = "信用卡密码") - private String cardPwd; - - @ApiModelProperty(value = "信用卡姓氏") - private String holderSurname; - - @ApiModelProperty(value = "信用卡名称") - private String holderName; - - /** 状态(导入默认正常) 1.待注册 2待验证 3.待完善 4.正常 5.异常 6.可用但已用 7.删除 */ - @ApiModelProperty(value = "状态(导入默认正常) 1.待注册 2待验证 3.待完善 4.正常 5.异常 6.可用但已用 7.删除") - private Integer status; - - /** 地址1 */ - @ApiModelProperty(value = "地址1") - private String addressline1; - - /** 国家 */ - @ApiModelProperty(value = "国家") - private String country; - - /** 州 */ - @ApiModelProperty(value = "州") - private String state; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtBuyerVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/CtBuyerVO.java deleted file mode 100644 index efa7e74..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtBuyerVO.java +++ /dev/null @@ -1,47 +0,0 @@ -package me.zhengjie.service.vo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 买家信息表(CtBuyer)表实体类 - * - * @author rch - * @since 2022-06-22 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtBuyerVO { - - private Long id; - - /** 创建时间 */ - private String createdAt; - - /** 修改时间 */ - private String updatedAt; - - /** 昵称*/ - private String nickName; - - /** 账号*/ - private String account; - - /** 密码*/ - private String pwd; - - /** 平台id */ - private Integer platformId; - - /** 平台名称 */ - private String platformName; - - /** 公司id */ - private Long companyId; - - /** 操作人账号*/ - private String gmName; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtCardDetailVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/CtCardDetailVO.java deleted file mode 100644 index 270a99b..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtCardDetailVO.java +++ /dev/null @@ -1,125 +0,0 @@ -package me.zhengjie.service.vo; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.math.BigDecimal; -import java.util.Date; - -/** - * 信用卡信息表(CtCard)表实体类 详情Detail - * - * @author rch - * @since 2022-07-09 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("信用卡详情") -public class CtCardDetailVO { - - @ApiModelProperty(value = "Id") - private Long id; - - @ApiModelProperty(value = "创建时间") - private String createdAt; - - @ApiModelProperty(value = "修改时间") - private String updatedAt; - - /** 操作人账号*/ - @ApiModelProperty(value = "操作人账号") - private String gmName; - - /** 父ID */ - @ApiModelProperty(value = "父ID") - private Long parentId; - - /** 卡号 */ - @ApiModelProperty(value = "卡号") - private String number; - -// /** PIN码 */ -// @ApiModelProperty(value = "PIN码") -// private String pinNumber; - - /** 持卡人姓氏 */ - @ApiModelProperty(value = "持卡人姓氏") - private String holderSurname; - - /** 持卡人名称 */ - @ApiModelProperty(value = "持卡人名称") - private String holderName; - - /** 有效期 */ - @ApiModelProperty(value = "有效期") - private Date termOfValidity; - - /** 余额 */ - @ApiModelProperty(value = "余额") - private BigDecimal balance; - - /** 累计消费 */ - @ApiModelProperty(value = "累计消费") - private BigDecimal sumConsume; - - /** 开卡日期 */ - @ApiModelProperty(value = "开卡日期") - private Date openDate; - - /** 所属国家 */ - @ApiModelProperty(value = "所属国家") - private String contntryShort; - - /** 信用卡类型 1.Payoneer 2.万事达虚拟卡 3.Visa信用卡 */ - @ApiModelProperty(value = "信用卡类型 1.Payoneer 2.万事达虚拟卡 3.Visa信用卡") - private Integer type; - - /** 所属厂商:1.AmzKeys 2.Airwallex */ - @ApiModelProperty(value = "所属厂商:1.AmzKeys 2.Airwallex") - private Integer cardDealer; - - /** 身份证号 */ - @ApiModelProperty(value = "身份证号") - private String idNumber; - - /** 省份 */ - @ApiModelProperty(value = "省份") - private String province; - - /** 城市 */ - @ApiModelProperty(value = "城市") - private String country; - - /** 地址 */ - @ApiModelProperty(value = "地址") - private String address; - - /** 手机号 */ - @ApiModelProperty(value = "手机号") - private String phone; - - /** 邮箱 */ - @ApiModelProperty(value = "邮箱") - private String email; - - /** 登陆账号 */ - @ApiModelProperty(value = "登陆账号") - private String account; - - /** 密码 */ - @ApiModelProperty(value = "密码") - private String pwd; - - /** 状态:1.正常、2.异常、3.已删除 */ - @ApiModelProperty(value = "状态:1.正常、2.异常、3.已删除") - private Integer status; - - /** 备注 */ - @ApiModelProperty(value = "备注") - private String remarks; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtCardListVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/CtCardListVO.java deleted file mode 100644 index fd2225f..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtCardListVO.java +++ /dev/null @@ -1,72 +0,0 @@ -package me.zhengjie.service.vo; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.math.BigDecimal; - -/** - * 买家信息表(CtCard)表实体类 分页查询Detail - * - * @author rch - * @since 2022-07-09 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel -public class CtCardListVO { - - @ApiModelProperty(value = "Id") - private Long id; - - @ApiModelProperty(value = "创建时间") - private String createdAt; - - @ApiModelProperty(value = "修改时间") - private String updatedAt; - - /** 操作人账号*/ - @ApiModelProperty(value = "操作人账号") - private String gmName; - - /** 卡号 */ - @ApiModelProperty(value = "卡号") - private String number; - - /** PIN码 */ - @ApiModelProperty(value = "PIN码") - private String pinNumber; - - /** 持卡人姓氏 */ - @ApiModelProperty(value = "持卡人姓氏") - private String holderSurname; - - /** 持卡人名称 */ - @ApiModelProperty(value = "持卡人名称") - private String holderName; - - /** 余额 */ - @ApiModelProperty(value = "余额") - private BigDecimal balance; - - /** 累计消费 */ - @ApiModelProperty(value = "累计消费") - private BigDecimal sumConsume; - - /** 信用卡类型 1.Payoneer 2.万事达虚拟卡 3.Visa信用卡 */ - @ApiModelProperty(value = "信用卡类型 1.Payoneer 2.万事达虚拟卡 3.Visa信用卡") - private Integer type; - - /** 所属厂商:1.AmzKeys 2.Airwallex */ - @ApiModelProperty(value = "所属厂商:1.AmzKeys 2.Airwallex") - private Integer cardDealer; - - /** 状态:1.正常、2.异常、3.已删除 */ - @ApiModelProperty(value = "状态:1.正常、2.异常、3.已删除") - private Integer status; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtClickFarmEditDetailVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/CtClickFarmEditDetailVO.java deleted file mode 100644 index c789a85..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtClickFarmEditDetailVO.java +++ /dev/null @@ -1,63 +0,0 @@ -package me.zhengjie.service.vo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.Date; - -/** - * 刷单Excel信息(CtClickFarming)表实体类 - 修改详情 - * - * @author rch - * @since 2022-08-16 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtClickFarmEditDetailVO { - - private Long id; - /** 关联刷单订单ID */ - private Long ctClickOrderId; - /** 买家id */ - private Long buyerId; - /** 买家名称 */ - private String buyerName; - /** 刷单类型 */ - private Integer type; - /** 刷单类型 */ - private Integer paramsType; - /** 店铺名称 */ - private String shopName; - /** 关键词 */ - private String keyWord; - /** 标题 */ - private String title; - /** 链接 */ - private String link; - /** 数量 */ - private Integer number; - /** 规格 */ - private String specification; - /** 颜色 */ - private String color; - /** item */ - private String item; - private String exchange; - /** 执行结果 */ - private String response; - /** 支付订单ID */ - private String payOrderId; - /** 状态 1.待执行 2.执行中 3.执行成功 4.执行失败 */ - private Integer status; - /** 留言 */ - private String amessage; - /** 创建时间 */ - private Date createdAt; - /** 修改时间 */ - private Date updatedAt; - /** 操作人账号 */ - private String gmName; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtClickFarmingDetailVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/CtClickFarmingDetailVO.java deleted file mode 100644 index eacd156..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtClickFarmingDetailVO.java +++ /dev/null @@ -1,98 +0,0 @@ -package me.zhengjie.service.vo; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import java.util.Date; - -/** - * 刷单Excel信息(CtClickFarming)表实体类 - * - * @author rch - * @since 2022-08-16 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("刷单详情") -public class CtClickFarmingDetailVO { - - @ApiModelProperty(value = "id") - private Long id; - - @ApiModelProperty(value = "买家名称") - private String buyerName; - - /** 商品属性类型 */ - @ApiModelProperty(value = "商品属性类型:1.关键词 2.链接", required = true, allowableValues = "1,2") - private Integer paramsType; - - /** 店铺名称 */ - @ApiModelProperty(value = "店铺名称") - private String shopName; - - /** 关键词 */ - @ApiModelProperty(value = "关键词") - private String keyWord; - - /** 标题 */ - @ApiModelProperty(value = "标题") - private String title; - - /** 链接 */ - @ApiModelProperty(value = "链接") - private String link; - - /** 数量 */ - @ApiModelProperty(value = "数量") - private Integer number; - - /** 规格 */ - @ApiModelProperty(value = "规格") - private String specification; - - /** 颜色 */ - @ApiModelProperty(value = "颜色") - private String color; - - /** item */ - @ApiModelProperty(value = "item") - private String item; - - @ApiModelProperty(value = "优惠劵") - private String exchange; - - /** 执行结果 */ - @ApiModelProperty(value = "执行结果") - private String response; - - /** 支付订单ID */ - @ApiModelProperty(value = "支付订单ID") - private String payOrderId; - - /** 状态 1.待执行 2.执行中 3.执行成功 4.执行失败 5.代付款 6.支付成功后失败 */ - @ApiModelProperty(value = "状态 1.待执行 2.执行中 3.执行成功 4.执行失败 5.代付款 6.支付成功后失败", allowableValues = "1,2,3,4,5,6") - private Integer status; - - /** 留言 */ - @ApiModelProperty(value = "留言") - private String amessage; - - /** 创建时间 */ - @ApiModelProperty(value = "创建时间") - private Date createdAt; - - /** 修改时间 */ - @ApiModelProperty(value = "修改时间") - private Date updatedAt; - - /** 操作人账号 */ - @ApiModelProperty(value = "操作人账号") - private String gmName; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtClickFarmingVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/CtClickFarmingVO.java deleted file mode 100644 index 44a409e..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtClickFarmingVO.java +++ /dev/null @@ -1,59 +0,0 @@ -package me.zhengjie.service.vo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.Date; - -/** - * 刷单Excel信息(CtClickFarming)表实体类 - * - * @author rch - * @since 2022-08-16 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtClickFarmingVO { - - private Long id; - /** 关联刷单订单ID */ - private Long ctClickOrderId; - /** 刷单类型 */ - private Integer paramsType; - /** 国家 */ - private String country; - /** 账号 */ - private String account; - /** 店铺名称 */ - private String shopName; - /** 关键词 */ - private String keyWord; - /** 标题 */ - private String title; - /** 链接 */ - private String link; - /** 数量 */ - private Integer number; - /** 规格 */ - private String specification; - /** 颜色 */ - private String color; - /** item */ - private String item; - private String exchange; - /** 执行结果 */ - private String response; - /** 支付订单ID */ - private String payOrderId; - /** 状态 1.待执行 2.执行中 3.执行成功 4.执行失败 */ - private Integer status; - /** 创建时间 */ - private Date createdAt; - /** 修改时间 */ - private Date updatedAt; - /** 操作人账号 */ - private String gmName; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtClickOrderDetailVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/CtClickOrderDetailVO.java deleted file mode 100644 index 1fbf249..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtClickOrderDetailVO.java +++ /dev/null @@ -1,48 +0,0 @@ -package me.zhengjie.service.vo; - -import com.baomidou.mybatisplus.extension.activerecord.Model; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.utils.excel.ExcelExport; - -/** - * 刷单-订单信息(CtClickOrder)表实体类 - * - * @author rch - * @since 2022-09-14 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtClickOrderDetailVO extends Model { - private Long id; - private String createdAt; - private String updatedAt; - /** 操作人账号*/ - private String gmName; - /** 公司ID */ - private Long companyId; - /** 状态描述 */ - private String paymentResults; - /** 购买数量 */ - private String pricesNumber; - /** 总金额 */ - private String amount; - /** 店铺名称 */ - private String shop; - /** 订单id */ - private String orderId; - /** 商品名称 */ - private String shopName; - /** 时间 */ - private String orderDate; - /** 评论 */ - private String comment; - /** 图片路径 */ - private String paths; - /** 状态 1.待执行 2.执行中 3.执行成功 4.执行失败 */ - private Integer status; - /** 执行结果 */ - private String response; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtClickOrderListVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/CtClickOrderListVO.java deleted file mode 100644 index f99a5b8..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtClickOrderListVO.java +++ /dev/null @@ -1,45 +0,0 @@ -package me.zhengjie.service.vo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.utils.excel.ExcelExport; - -/** - * 实体类 分页查询Detail - * - * @author rch - * @since 2022-09-27 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtClickOrderListVO { - - private Long id; - private String createdAt; - private String updatedAt; - /** 公司ID */ - private Long companyId; - /** 类型 1.刷单 2.导入 */ - private Integer type; - /** 公司Name */ - private String companyName; - /** 账号 */ - private String account; - /** 密码 */ - private String pwd; - /** 总金额 */ - private String amount; - /** 店铺名称 */ - private String shop; - /** 订单id */ - private String orderId; - /** 评论 */ - private String comment; - /** 状态 1.待执行 2.执行中 3.执行成功 4.执行失败 */ - private Integer status; - /** 执行结果 */ - private String response; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtCompanyInfoVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/CtCompanyInfoVO.java deleted file mode 100644 index 6f1db4b..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtCompanyInfoVO.java +++ /dev/null @@ -1,23 +0,0 @@ -package me.zhengjie.service.vo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 公司信息(CtPlatform)表实体类 VO - * - * @author rch - * @since 2022-07-07 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtCompanyInfoVO { - - private Long id; - - /** 名称 */ - private String name; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtCompanyVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/CtCompanyVO.java deleted file mode 100644 index c13e35d..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtCompanyVO.java +++ /dev/null @@ -1,35 +0,0 @@ -package me.zhengjie.service.vo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 公司信息(CtCompany)表实体类 VO - * - * @author rch - * @since 2022-06-28 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtCompanyVO { - - private Long id; - private String createdAt; - private String updatedAt; - /** 名称 */ - private String name; - /** 地址 */ - private String address; - /** 电话 */ - private String phone; - /** 商户码(公司调用api公司唯一标识) */ - private String number; - /** 商户token(公司调用api公司token身份标识) */ - private String token; - - /** 操作人账号*/ - private String gmName; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtDhPayDetailVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/CtDhPayDetailVO.java deleted file mode 100644 index d6f4e98..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtDhPayDetailVO.java +++ /dev/null @@ -1,40 +0,0 @@ -package me.zhengjie.service.vo; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.math.BigDecimal; -import java.util.Date; - -/** - * 买家信息表(CtDhPay)表实体类 详情Detail - * - * @author rch - * @since 2022-07-28 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtDhPayDetailVO { - - private Long id; - private String createdAt; - private String updatedAt; - /** 操作人账号*/ - private String gmName; - - /** 买家名称 */ - private String buyerName; - /** 支付订单ID(敦煌的) */ - private String orderId; - /** 请求响应详情 */ - private String response; - /** 状态 0.待处理 1.支付成功 2.支付失败 */ - private Integer status; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtDhPayListVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/CtDhPayListVO.java deleted file mode 100644 index 778ea07..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtDhPayListVO.java +++ /dev/null @@ -1,36 +0,0 @@ -package me.zhengjie.service.vo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.Date; - -/** - * 买家信息表(CtDhPay)表实体类 分页查询Detail - * - * @author rch - * @since 2022-07-07 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtDhPayListVO { - - private Long id; - /** 买家名称 */ - private String buyerName; - /** 支付订单ID(敦煌的) */ - private String orderId; - /** 请求响应详情 */ - private String response; - /** 状态 0.待处理 1.支付成功 2.支付失败 */ - private Integer status; - /** 创建时间 */ - private Date createdAt; - /** 修改时间 */ - private Date updatedAt; - /** 操作人账号 */ - private String gmName; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtExcelImportInfoVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/CtExcelImportInfoVO.java deleted file mode 100644 index c20eda1..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtExcelImportInfoVO.java +++ /dev/null @@ -1,42 +0,0 @@ -package me.zhengjie.service.vo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * ExcelImportInfo 导入信息(CtExcel)表实体类 VO - * - * @author rch - * @since 2022-06-27 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtExcelImportInfoVO { - - private Long id; - private String createdAt; - private String updatedAt; - - /** 公司主键 */ - private Long companyId; - - /** 鉴权枚举 */ - private Integer tokenEnum; - - /** 订单来源 */ - private String fromDetailInfo; - - /** 状态 状态 1.待处理 2.处理成功 3.处理失败 */ - private Integer status; - - /** 产品信息-JSON */ - private String cartList; - - /** 订单收货地址-JSON */ - private String contactInfo; - - /** 操作人账号*/ - private String gmName; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtExcelVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/CtExcelVO.java deleted file mode 100644 index 802664b..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtExcelVO.java +++ /dev/null @@ -1,31 +0,0 @@ -package me.zhengjie.service.vo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * Excel 导入信息(CtExcel)表实体类 VO - * - * @author rch - * @since 2022-06-23 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtExcelVO { - - private Long id; - private String createdAt; - private String updatedAt; - /** 备注 */ - private String remarks; - /** excel路径 */ - private String path; - private String errorPath; - /** 状态1.待处理 2.已处理 */ - private Integer status; - - /** 操作人账号*/ - private String gmName; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtOrderVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/CtOrderVO.java deleted file mode 100644 index 2fe99ae..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtOrderVO.java +++ /dev/null @@ -1,44 +0,0 @@ -package me.zhengjie.service.vo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * (CtOrder)表实体类 VO - * - * @author rch - * @since 2022-07-01 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtOrderVO { - - private Long id; - private String createdAt; - private String updatedAt; - /** 公司Id */ - private Long companyId; - /** ExcelId 信息 */ - private Long excelInfoId; - /** 买家buy_access_token */ - private String buyAccessToken; - /** 我们平台订单编号 */ - private String ctOrderNo; - /** 订单号,下单成功响应的订单号(冗余字段 下单成功响应订单信息里有) */ - private Long orderNo; - /** 下单成功响应的产品id( a,b,c 格式) (响应字段很多,先少些几个) */ - private Long responseProductId; - /** 下单成功响应的订单地址id(响应字段很多,先少些几个) */ - private Long responseOrderAddressId; - /** 下单成功响应的订单信息 (响应字段很多,先少些几个) */ - private Long responseOrderId; - /** 响应码信息 */ - private OrderResponStatusVO orderResponseStatus; - /** 响应码信息 */ - private PayOrderVO payOrderVO; - /** 状态 1.待支付(下单成功) 2.支付成功 3.支付失败*/ - private Integer status; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtPlatformInfoVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/CtPlatformInfoVO.java deleted file mode 100644 index 6086629..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtPlatformInfoVO.java +++ /dev/null @@ -1,23 +0,0 @@ -package me.zhengjie.service.vo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 平台信息(CtPlatform)表实体类 VO - * - * @author rch - * @since 2022-06-23 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtPlatformInfoVO { - - private Long id; - - /** 名称 */ - private String name; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtPlatformVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/CtPlatformVO.java deleted file mode 100644 index 6562b7b..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtPlatformVO.java +++ /dev/null @@ -1,29 +0,0 @@ -package me.zhengjie.service.vo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 平台信息(CtPlatform)表实体类 VO - * - * @author rch - * @since 2022-06-23 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtPlatformVO { - - private Long id; - private String createdAt; - private String updatedAt; - /** 名称 */ - private String name; - /** 地址 */ - private String address; - /** 电话 */ - private String phone; - private String gmName; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtRebotListVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/CtRebotListVO.java deleted file mode 100644 index 02edb77..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtRebotListVO.java +++ /dev/null @@ -1,37 +0,0 @@ -package me.zhengjie.service.vo; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 影刀机器人 分页查询VO - * - * @Author zhw - * @Date 2022-07-23 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtRebotListVO { - - - private Long id; - - private String createdAt; - - private String updatedAt; - /** 操作人账号*/ - private String gmName; - - /** 机器人账号 */ - private String accountName; - /** 机器人Uuid信息 */ - private String robotClientUuid; - /** 状态 0.未占用 1.已占用 */ - private Integer status; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtVpnInfoVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/CtVpnInfoVO.java deleted file mode 100644 index 3241d22..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtVpnInfoVO.java +++ /dev/null @@ -1,16 +0,0 @@ -package me.zhengjie.service.vo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtVpnInfoVO { - - private Long id; - - /** 名称 */ - private String name; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtVpnVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/CtVpnVO.java deleted file mode 100644 index a95a195..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/CtVpnVO.java +++ /dev/null @@ -1,42 +0,0 @@ -package me.zhengjie.service.vo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtVpnVO { - - private Long id; - /** 创建时间*/ - private String createdAt; - /** 修改时间*/ - private String updatedAt; - /** 操作人账号*/ - private String gmName; - - /** 所属国家简称 */ - private String contntryShort; - /** IP地址 */ - private String ipAddress; - /** 父ip地址 */ - private String parentIpAddress; - /** 端口 */ - private Integer port; - /** 名称 */ - private String name; - /** 密码 */ - private String pwd; - /** VPS类型 1.传统 */ - private Integer vpsType; - /** 经销商 1.V2 */ - private Integer dealer; - /** mac地址 */ - private String mac; - /** 链接 */ - private String link; - /** 经销商 1.可用 2.禁用 */ - private Integer status; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/GoogleAuthInfoVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/GoogleAuthInfoVO.java deleted file mode 100644 index e99241f..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/GoogleAuthInfoVO.java +++ /dev/null @@ -1,27 +0,0 @@ -package me.zhengjie.service.vo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - *

- * 秘钥信息 - *

- * - * @author: rch - * @since: 2020-08-26 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class GoogleAuthInfoVO { - /** 用户信息 */ - private String userName; - - /** 二维码url 信息 */ - private String qrBarCodeUrl; - - /** 明文秘钥 */ - private String secret; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/LoginIpVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/LoginIpVO.java deleted file mode 100644 index 80b4c10..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/LoginIpVO.java +++ /dev/null @@ -1,57 +0,0 @@ -package me.zhengjie.service.vo; - -import cn.hutool.core.util.ObjectUtil; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.entity.LoginIp; -import me.zhengjie.utils.DateUtil; - -import java.time.LocalDateTime; - -/* - * - * @Description - * @Date 2022/3/21 - * @Author zeng - */ -@Data -@NoArgsConstructor -public class LoginIpVO extends LoginIp { - - // 状态 1:正常 0:失效 - private Integer status; - - - public String getIp() { - StringBuffer sbf = new StringBuffer(getIpStart()); - if (sbf.length() > 0) { - sbf.append("~"); - } - sbf.append(getIpEnd()); - return sbf.toString(); - } - - public Integer getStatus() { - if (ObjectUtil.isNotEmpty(getVaildTime())) { - LocalDateTime localDateTime = DateUtil.parseLocalDateTimeFormatyMdHms(getVaildTime()); - if (localDateTime.isBefore(LocalDateTime.now())) { - return 0; - } - return 1; - } - return 1; - } - - public LoginIpVO(LoginIp loginIp) { - setId(loginIp.getId()); - setIpStart(loginIp.getIpStart()); - setIpEnd(loginIp.getIpEnd()); - setCreatedAt(loginIp.getCreatedAt()); - setUpdatedAt(loginIp.getUpdatedAt()); - setGmName(loginIp.getGmName()); - setRemark(loginIp.getRemark()); - setVaildTime(loginIp.getVaildTime()); - } - - -} diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/OrderResponStatusVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/OrderResponStatusVO.java deleted file mode 100644 index 73ed2c5..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/OrderResponStatusVO.java +++ /dev/null @@ -1,21 +0,0 @@ -package me.zhengjie.service.vo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 订单下单模块响应Status对象VO - * - * @author rch - * @create 2022-06-27 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class OrderResponStatusVO { - private String code; - private String message; - private String solution; - private OrderResponSubErrorVO subErrors; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/OrderResponSubErrorVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/OrderResponSubErrorVO.java deleted file mode 100644 index fcf8b58..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/OrderResponSubErrorVO.java +++ /dev/null @@ -1,19 +0,0 @@ -package me.zhengjie.service.vo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 敦煌接口响应SubError - * - * @author rch - * @create 2022-06-27 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class OrderResponSubErrorVO { - private String code; - private String message; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/OrderResponseVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/OrderResponseVO.java deleted file mode 100644 index 7c69e07..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/OrderResponseVO.java +++ /dev/null @@ -1,28 +0,0 @@ -package me.zhengjie.service.vo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.List; - -/** - * 敦煌订单下单响应订单信息 - * - * @author rch - * @create 2022-06-27 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class OrderResponseVO { - - /** 接口响应订单信息 订单信息 */ - private BuyOrderResponseOrderVO orderInfo; - - /** 接口响应订单信息 订单产品信息 */ - private List cartList; - - /** 接口响应订单信息 订单收件地址信息 */ - private BuyOrderResponseAddressVO orderContactInfo; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/PayOrderVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/PayOrderVO.java deleted file mode 100644 index d623fdc..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/PayOrderVO.java +++ /dev/null @@ -1,23 +0,0 @@ -package me.zhengjie.service.vo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 支付下单API响应对象 - * - * @author rch - * @create 2022-06-27 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class PayOrderVO { - - /** 接口响应状态 响应码 响应内容等信息*/ - private OrderResponStatusVO status; - /** 接口响应订单信息 */ - private String result; - private String message; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/SettingSiteVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/SettingSiteVO.java deleted file mode 100644 index afa4d11..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/SettingSiteVO.java +++ /dev/null @@ -1,31 +0,0 @@ -package me.zhengjie.service.vo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 站点配置(SettingSiteVO)表 响应类 - * - * @author zeng - * @since 2020-07-13 10:07:39 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class SettingSiteVO { - - private Long id; - - /** 设置KEY */ - private String settingKey; - - /** 设置value */ - private String settingValue; - - /** 中文描述 */ - private String content; - - /** 单位 */ - private String unit; -} \ No newline at end of file diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/SysQuartzJobListVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/SysQuartzJobListVO.java deleted file mode 100644 index 282b4a6..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/SysQuartzJobListVO.java +++ /dev/null @@ -1,40 +0,0 @@ -package me.zhengjie.service.vo; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 影刀任务表(sys_quartz_job)表实体类 分页查询VO - * @author zhw - * @since 2022-07-21 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class SysQuartzJobListVO { - - /** 任务ID */ - private Long jobId; - /** 任务名称 */ - private String jobName; - /** Spring Bean名称 */ - private String beanName; - /** 方法名称 */ - private String methodName; - /** 参数 */ - private String params; - /** cron 表达式 */ - private String cronExpression; - /** 状态:1暂停、0启用 */ - private Integer isPause; - /** 备注 */ - private String description; - /** 创建时间 */ - private String createTime; - -} diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/SysQuartzLogListVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/SysQuartzLogListVO.java deleted file mode 100644 index 8b79777..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/SysQuartzLogListVO.java +++ /dev/null @@ -1,47 +0,0 @@ -package me.zhengjie.service.vo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.math.BigDecimal; -import java.sql.Timestamp; - -/** - * 买家信息表(sys_quartz_log)表实体类 分页查询Detail - * - * @author rch - * @since 2022-07-09 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class SysQuartzLogListVO { - - private Long logId; - /** bean名称 */ - private String beanName; - /** 任务名称 */ - private String jobName; - /** 方法名称 */ - private String methodName; - - /** 参数 */ - private String params; - - /** cron表达式 */ - private String cronExpression; - - /** 状态 */ - private Integer isSuccess; - - /** 异常详情 */ - private String exceptionDetail; - - /** 执行耗时 */ - private Long time; - - /** 创建时间 */ - private Timestamp createTime; -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/dhaddcar/DhAddCarListVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/dhaddcar/DhAddCarListVO.java deleted file mode 100644 index b8ea1ec..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/dhaddcar/DhAddCarListVO.java +++ /dev/null @@ -1,80 +0,0 @@ -package me.zhengjie.service.vo.dhaddcar; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotNull; -import java.util.Date; - -/** - * 敦煌加购信息 DTO - * - * @author rch - * @create 2022-11-17 - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("敦煌加购信息") -public class DhAddCarListVO { - - /** ID */ - @ApiModelProperty(value = "ID", required = true) - private Long id; - - /** 商品属性类型:1.关键词 2.链接 */ - @ApiModelProperty(value = "商品属性类型:1.关键词 2.链接", required = true, allowableValues = "1,2") - private Integer paramsType; - - /** 买家ID */ - @ApiModelProperty(value = "买家ID", required = true) - private Integer buyerId; - - /** 账号 */ - @ApiModelProperty(value = "账号") - private String account; - - /** 公司名称 */ - @ApiModelProperty(value = "公司名称") - private String companyName; - - /** 国家 */ - @ApiModelProperty(value = "国家") - private String country; - - /** 加购物车商品ids */ - @ApiModelProperty(value = "加购物车商品ids") - private String carGoodIds; - - /** 执行结果 */ - @ApiModelProperty(value = "执行结果") - private String response; - - /** 状态 1.待执行 2.执行中 3.加购成功 4.加购失败 5.下单成功 6.支付成功 7.抓单成功 8.抓单失败 */ - @ApiModelProperty(value = "状态 1.待执行 2.执行中 3.加购成功 4.加购失败 5.下单成功 6.支付成功 7.抓单成功 8.抓单失败") - private Integer status; - - /** 创建时间 */ - @ApiModelProperty(value = "创建时间") - private Date createdAt; - - /** 修改时间 */ - @ApiModelProperty(value = "修改时间") - private Date updatedAt; - - /** 操作人账号 */ - @ApiModelProperty(value = "操作人账号") - private String gmName; - -// /** 加购物车商品ids */ -// @ApiModelProperty(value = "加购物车商品ids") -// private List carGoodKeys; -// -// /** 加购物车商品ids */ -// @ApiModelProperty(value = "加购物车商品ids") -// private List carGoodLinks; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/dhaddcar/DhAddCarVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/dhaddcar/DhAddCarVO.java deleted file mode 100644 index 1db1917..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/dhaddcar/DhAddCarVO.java +++ /dev/null @@ -1,65 +0,0 @@ -package me.zhengjie.service.vo.dhaddcar; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.service.vo.dhcargood.DhCarGoodKeyVO; -import me.zhengjie.service.vo.dhcargood.DhCarGoodLinkVO; - -import java.util.List; - -/** - * 敦煌加购Exit信息 DTO - * - * @author rch - * @create 2022-07-09 - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("修改敦煌加购信息回显") -public class DhAddCarVO { - - /** ID */ - @ApiModelProperty(value = "ID", required = true) - private Long id; - - /** 商品属性类型:1.关键词 2.链接 */ - @ApiModelProperty(value = "商品属性类型:1.关键词 2.链接") - private Integer paramsType; - @ApiModelProperty(value = "公司名称", required = true) - private String companyName; - /** 买家ID */ - @ApiModelProperty(value = "买家ID", required = true) - private Integer buyerId; - /** 买家账号 */ - @ApiModelProperty(value = "买家账号", required = true) - private String account; - /** 国家 */ - @ApiModelProperty(value = "国家", required = true) - private String country; - /** 密码 */ - @ApiModelProperty(value = "密码", required = true) - private String pwd; - /** vpn分享链接 */ - private String vpnShare; - - /** 加购物车商品ids */ - @ApiModelProperty(value = "加购物车商品ids") - private String carGoodIds; - - /** 加购物车商品ids */ - @ApiModelProperty(value = "加购物车商品ids") - private List carGoodKeys; - - /** 加购物车商品ids */ - @ApiModelProperty(value = "加购物车商品ids") - private List carGoodLinks; - - /** 状态 1.待执行 2.执行中 3.加购成功 4.加购失败 5.下单成功 6.支付成功 7.抓单成功 8.抓单失败 */ - @ApiModelProperty(value = "状态 1.待执行 2.执行中 3.加购成功 4.加购失败 5.下单成功 6.支付成功 7.抓单成功 8.抓单失败") - private Integer status; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/dhaddcar/DhAddCarYdParamsVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/dhaddcar/DhAddCarYdParamsVO.java deleted file mode 100644 index acd8943..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/dhaddcar/DhAddCarYdParamsVO.java +++ /dev/null @@ -1,56 +0,0 @@ -package me.zhengjie.service.vo.dhaddcar; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.service.vo.dhcargood.DhCarGoodKeyVO; -import me.zhengjie.service.vo.dhcargood.DhCarGoodLinkVO; - -import java.util.List; - -/** - * 敦煌加购 影刀参数信息 DTO - * - * @author rch - * @create 2022-07-09 - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("修改敦煌加购信息回显") -public class DhAddCarYdParamsVO { - - /** ID */ - @ApiModelProperty(value = "ID", required = true) - private Long id; - - /** 商品属性类型:1.关键词 2.链接 */ - @ApiModelProperty(value = "商品属性类型:1.关键词 2.链接") - private Integer paramsType; - - /** 买家账号 */ - @ApiModelProperty(value = "买家账号", required = true) - private String account; - - /** 国家 */ - @ApiModelProperty(value = "国家", required = true) - private String country; - - /** 密码 */ - @ApiModelProperty(value = "密码", required = true) - private String pwd; - - /** vpn分享链接 */ - private String vpnShare; - - /** 加购物车商品ids */ - @ApiModelProperty(value = "加购物车商品ids") - private List carGoodKeys; - - /** 加购物车商品ids */ - @ApiModelProperty(value = "加购物车商品ids") - private List carGoodLinks; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/dhcargood/DhCarGoodKeyVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/dhcargood/DhCarGoodKeyVO.java deleted file mode 100644 index 3c8a789..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/dhcargood/DhCarGoodKeyVO.java +++ /dev/null @@ -1,76 +0,0 @@ -package me.zhengjie.service.vo.dhcargood; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Null; - -/** - * 敦煌-加购商品(根据关键词) VO - * - * @author rch - * @create 2022-07-09 - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("敦煌-加购商品(根据关键词)") -public class DhCarGoodKeyVO { - - /** ID */ - @ApiModelProperty(value = "ID", required = true) - private Long id; - - /** 商品属性类型:1.关键词 2.链接 */ - @ApiModelProperty(value = "商品属性类型:1.关键词 2.链接", required = true, allowableValues = "1,2") - private Integer paramsType; - - /** 店铺名称 */ - @ApiModelProperty(value = "NotBlank", required = true) - private String shopName; - - /** 关键词 */ - @ApiModelProperty(value = "关键词", required = true) - private String keyWord; - - /** 标题 */ - @ApiModelProperty(value = "标题", required = true) - private String title; - - /** 数量 */ - @ApiModelProperty(value = "数量", required = true) - private Integer number; - - /** 规格 */ - @ApiModelProperty(value = "规格") - private String specification; - - /** 颜色 */ - @ApiModelProperty(value = "颜色") - private String color; - - /** item */ - @ApiModelProperty(value = "item", required = true) - private String item; - - /** 最小价格区间 */ - @ApiModelProperty(value = "最小价格区间") - private String sectionMin; - - /** 最大价格区间 */ - @ApiModelProperty(value = "最大价格区间") - private String sectionMax; - - /** 评论 */ - @ApiModelProperty(value = "评论") - private String comment; - - /** 图片url */ - @ApiModelProperty(value = "图片url") - private String paths; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/dhcargood/DhCarGoodLinkVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/dhcargood/DhCarGoodLinkVO.java deleted file mode 100644 index 0a6005e..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/dhcargood/DhCarGoodLinkVO.java +++ /dev/null @@ -1,56 +0,0 @@ -package me.zhengjie.service.vo.dhcargood; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Null; - -/** - * 敦煌-加购商品(根据链接) VO - * - * @author rch - * @create 2022-07-09 - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("敦煌-加购商品(根据链接)") -public class DhCarGoodLinkVO { - - /** ID */ - @ApiModelProperty(value = "ID", required = true) - private Long id; - - /** 商品属性类型:1.关键词 2.链接 */ - @ApiModelProperty(value = "商品属性类型:1.关键词 2.链接", required = true, allowableValues = "1,2") - private Integer paramsType; - - /** 链接 */ - @ApiModelProperty(value = "链接", required = true) - private String link; - - /** 数量 */ - @ApiModelProperty(value = "数量", required = true) - private Integer number; - - /** 规格 */ - @ApiModelProperty(value = "规格", required = true) - private String specification; - - /** 颜色 */ - @ApiModelProperty(value = "颜色", required = true) - private String color; - - /** 评论 */ - @ApiModelProperty(value = "评论") - private String comment; - - /** 图片url */ - @ApiModelProperty(value = "图片url") - private String paths; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/dhcarorder/DhAddCarOrderListVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/dhcarorder/DhAddCarOrderListVO.java deleted file mode 100644 index c8920e4..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/dhcarorder/DhAddCarOrderListVO.java +++ /dev/null @@ -1,62 +0,0 @@ -package me.zhengjie.service.vo.dhcarorder; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.Date; - -/** - * 敦煌加购订单信息 DTO - * - * @author rch - * @create 2022-12-01 - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("敦煌加购信息") -public class DhAddCarOrderListVO { - - @ApiModelProperty(value = "ID") - private Long id; - @ApiModelProperty(value = "创建时间") - private String createdAt; - @ApiModelProperty(value = "修改时间") - private String updatedAt; - /** 操作人账号*/ - @ApiModelProperty(value = "操作人") - private String gmName; - - /** 1.导入 2.刷单 */ - @ApiModelProperty(value = "类型 1.导入 2.刷单") - private Integer type; - /** 关联敦煌加购的id */ - @ApiModelProperty(value = "关联敦煌加购的id") - private Long addCarId; - /** 总金额 */ - @ApiModelProperty(value = "总金额") - private String amount; - /** 状态描述 */ - @ApiModelProperty(value = "状态描述") - private String paymentResults; - /** 店铺名称 */ - @ApiModelProperty(value = "店铺名称") - private String shop; - /** 订单id */ - @ApiModelProperty(value = "订单id") - private String orderId; - /** 时间 */ - @ApiModelProperty(value = "订单时间") - private String orderDate; - /** 状态 1.待执行 2.执行中 3.执行成功 4.执行失败 */ - @ApiModelProperty(value = "状态 1.待执行 2.执行中 3.执行成功 4.执行失败") - private Integer status; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/service/vo/dhcarorder/DhCarOrderParamsVO.java b/wjcy-common/src/main/java/me/zhengjie/service/vo/dhcarorder/DhCarOrderParamsVO.java deleted file mode 100644 index ad98173..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/service/vo/dhcarorder/DhCarOrderParamsVO.java +++ /dev/null @@ -1,59 +0,0 @@ -package me.zhengjie.service.vo.dhcarorder; - -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.service.vo.dhcargood.DhCarGoodKeyVO; -import me.zhengjie.service.vo.dhcargood.DhCarGoodLinkVO; - -import java.util.List; - -/** - * 敦煌加购好评-影刀参数 - * - * @author rch - * @create 2022-12-01 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class DhCarOrderParamsVO { - /** ID */ - @ApiModelProperty(value = "ID", required = true) - private Long id; - - /** 商品属性类型:1.关键词 2.链接 */ - @ApiModelProperty(value = "商品属性类型:1.关键词 2.链接") - private Integer paramsType; - - /** 买家账号 */ - @ApiModelProperty(value = "买家账号", required = true) - private String account; - - /** 国家 */ - @ApiModelProperty(value = "国家", required = true) - private String country; - - /** 密码 */ - @ApiModelProperty(value = "密码", required = true) - private String pwd; - - /** vpn分享链接 */ - private String vpnShare; - - /** 订单ID */ - private String orderId; - - /** 加购物车商品ids */ - @ApiModelProperty(value = "加购物车商品ids") - private String carGoodIds; - - /** 加购物车商品ids */ - @ApiModelProperty(value = "加购物车商品ids") - private List carGoodKeys; - - /** 加购物车商品ids */ - @ApiModelProperty(value = "加购物车商品ids") - private List carGoodLinks; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/CacheKey.java b/wjcy-common/src/main/java/me/zhengjie/utils/CacheKey.java deleted file mode 100644 index 7485713..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/CacheKey.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2019-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.utils; - -/** - * @author: liaojinlong - * @date: 2020/6/11 15:49 - * @apiNote: 关于缓存的Key集合 - */ -public interface CacheKey { - - /** - * 用户 - */ - String USER_ID = "user::id:"; - /** - * 数据 - */ - String DATA_USER = "data::user:"; - /** - * 菜单 - */ - String MENU_ID = "menu::id:"; - String MENU_USER = "menu::user:"; - /** - * 角色授权 - */ - String ROLE_AUTH = "role::auth:"; - /** - * 角色信息 - */ - String ROLE_ID = "role::id:"; - /** - * 部门 - */ - String DEPT_ID = "dept::id:"; - /** - * 岗位 - */ - String JOB_ID = "job::id:"; - /** - * 数据字典 - */ - String DICT_NAME = "dict::name:"; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/CallBack.java b/wjcy-common/src/main/java/me/zhengjie/utils/CallBack.java deleted file mode 100644 index 9b10812..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/CallBack.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2019-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package me.zhengjie.utils; - -/** - * @author: liaojinlong - * @date: 2020/6/9 17:02 - * @since: 1.0 - * @see {@link SpringContextHolder} - * 针对某些初始化方法,在SpringContextHolder 初始化前时,
- * 可提交一个 提交回调任务。
- * 在SpringContextHolder 初始化后,进行回调使用 - */ - -public interface CallBack { - /** - * 回调执行方法 - */ - void executor(); - - /** - * 本回调任务名称 - * @return / - */ - default String getCallBackName() { - return Thread.currentThread().getId() + ":" + this.getClass().getName(); - } -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/CheckPwdValidator.java b/wjcy-common/src/main/java/me/zhengjie/utils/CheckPwdValidator.java deleted file mode 100644 index 2f10dca..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/CheckPwdValidator.java +++ /dev/null @@ -1,35 +0,0 @@ -package me.zhengjie.utils; - -import cn.hutool.core.util.ObjectUtil; -import me.zhengjie.annotation.CheckPwd; - -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; -import java.util.regex.Pattern; - -/* - * - * @Description - * @Date 2022/3/21 - * @Author zeng - */ -public class CheckPwdValidator implements ConstraintValidator { - - private CheckPwd checkPwd; - - public static final String p = "^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[~@#$%\\*-\\+=:,\\\\?\\[\\]\\{}]).{16,64}$"; - - - @Override - public void initialize(CheckPwd constraintAnnotation) { - this.checkPwd = constraintAnnotation; - } - - @Override - public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) { - if (ObjectUtil.isEmpty(value)) { - return true; - } - return Pattern.matches(p, value); - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/CloseUtil.java b/wjcy-common/src/main/java/me/zhengjie/utils/CloseUtil.java deleted file mode 100644 index 98d375b..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/CloseUtil.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.utils; - -import java.io.Closeable; - -/** - * @author Zheng Jie - * @website https://el-admin.vip - * @description 用于关闭各种连接,缺啥补啥 - * @date 2021-03-05 - **/ -public class CloseUtil { - - public static void close(Closeable closeable) { - if (null != closeable) { - try { - closeable.close(); - } catch (Exception e) { - // 静默关闭 - } - } - } - - public static void close(AutoCloseable closeable) { - if (null != closeable) { - try { - closeable.close(); - } catch (Exception e) { - // 静默关闭 - } - } - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/CronUtils.java b/wjcy-common/src/main/java/me/zhengjie/utils/CronUtils.java deleted file mode 100644 index 14728f8..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/CronUtils.java +++ /dev/null @@ -1,49 +0,0 @@ -package me.zhengjie.utils; - -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; - -/** - * 时间日期转cron工具类 - * Spring Task是Quartz的弱版,Quartz支持年份,而Spring Task不支持。Spring Task是6位, - * Quartz可以7位,本代码是基于hutool工具的表达式,是可以支持Quartz。 - * @author rch - * @create 2022-10-06 - */ -public class CronUtils { - - - /** - * 仅一次 - * @param dateStr - * @return - */ - public static String onlyOnce(String dateStr) { - LocalDateTime time = LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); - String cronStr = time.format(DateTimeFormatter.ofPattern("ss mm HH dd MM ? yyyy")); - return cronStr; - } - - /** - * 每天 - * @param timeStr - * @return - */ - public static String everyDay(String timeStr) { - LocalDateTime time = LocalDateTime.parse(timeStr, DateTimeFormatter.ofPattern("HH:mm:ss")); - String cronStr = time.format(DateTimeFormatter.ofPattern("ss mm HH dd * * ?")); - return cronStr; - } - - - /** - * 每周 - * @param timeStr - * @return - */ - public static String everyWeek(String timeStr, String week) { - LocalDateTime time = LocalDateTime.parse(timeStr, DateTimeFormatter.ofPattern("HH:mm:ss")); - String cronStr = time.format(DateTimeFormatter.ofPattern("ss mm HH ? * " + week)); - return cronStr; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/DateTimeValidator.java b/wjcy-common/src/main/java/me/zhengjie/utils/DateTimeValidator.java deleted file mode 100644 index 1d22b75..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/DateTimeValidator.java +++ /dev/null @@ -1,46 +0,0 @@ -package me.zhengjie.utils; - - -import cn.hutool.core.util.ObjectUtil; -import me.zhengjie.annotation.DateTime; - -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; -import java.text.SimpleDateFormat; -/** - *

- * 日期格式效验 - *

- * - * @Author xx - * @Date 2021/7/27 - **/ -public class DateTimeValidator implements ConstraintValidator { - private DateTime dateTime; - - @Override - public void initialize(DateTime dateTime) { - this.dateTime = dateTime; - } - - @Override - public boolean isValid(String value, ConstraintValidatorContext context) { - if (ObjectUtil.isEmpty(value)) { - return true; - } - String format = dateTime.format(); - - if (value.length() != format.length()) { - return false; - } - - SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format); - - try { - simpleDateFormat.parse(value); - } catch (Exception e) { - return false; - } - return true; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/DateUtil.java b/wjcy-common/src/main/java/me/zhengjie/utils/DateUtil.java deleted file mode 100644 index 3df2210..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/DateUtil.java +++ /dev/null @@ -1,555 +0,0 @@ -/* - * Copyright 2019-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package me.zhengjie.utils; - -import cn.hutool.core.util.ObjectUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.time.*; -import java.time.format.DateTimeFormatter; -import java.util.*; - -/** - * @author: liaojinlong - * @date: 2020/6/11 16:28 - * @apiNote: JDK 8 新日期类 格式化与字符串转换 工具类 - */ -public class DateUtil { - - private static final Logger LOGGER = LoggerFactory.getLogger(DateUtil.class); - - public static final DateTimeFormatter DFY_MD_HMS = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - public static final DateTimeFormatter DFY_MD = DateTimeFormatter.ofPattern("yyyy-MM-dd"); - - - /** - * - * 判断某个时间是否在某个时间段内 - * @ xxs - * @param date 待比较的时间 - * @param format 时间格式,eg("HH:mm") - * @param startTimeStr 时间范围的开始时间,eg("06:00") - * @param endTimeStr 时间范围的结束时间,eg("22:00") - * - * */ - public static Boolean isBelong(Date date, String format, String startTimeStr, String endTimeStr){ - //设置日期格式 - SimpleDateFormat df = new SimpleDateFormat(format); - Date beginTime = null; - Date endTime = null; - try { - date = df.parse(df.format(date)); - beginTime = df.parse(startTimeStr); - endTime = df.parse(endTimeStr); - } catch (Exception e) { - e.printStackTrace(); - } - - return belongCalendar(date, beginTime, endTime); - } - - - - /** - * 判断时间是否在时间段内 - * @xxs - * @param nowTime - * @param beginTime - * @param endTime - * @return - */ - public static boolean belongCalendar(Date nowTime, Date beginTime, Date endTime) { - Calendar date = Calendar.getInstance(); - date.setTime(nowTime); - - Calendar begin = Calendar.getInstance(); - begin.setTime(beginTime); - - Calendar end = Calendar.getInstance(); - end.setTime(endTime); - - if (date.after(begin) && date.before(end)) { - return true; - } else { - return false; - } - } - - /** - * 比较两日期格式大小(最新的时间靠前) - * 1: time1time2 - * 0: time1=time2 - * null time1 or time2 日期格式错误 - * - * @param time1 yyyy-MM-dd HH:mm:ss - * @param time2 yyyy-MM-dd HH:mm:ss - * @return - */ - public static Integer compareDate(String time1, String time2) { - try { - LocalDateTime t1 = parseLocalDateTimeFormatyMdHms(time1); - LocalDateTime t2 = parseLocalDateTimeFormatyMdHms(time2); - Long timeStamp1 = getTimeStamp(t1); - Long timeStamp2 = getTimeStamp(t2); - if (timeStamp1 < timeStamp2) { - return 1; - } - if (timeStamp1 > timeStamp2) { - return -1; - } - if (timeStamp1.equals(timeStamp2)) { - return 0; - } - } catch (Exception e) {} - return null; - } - - /** - * 获得指定日期的前一天 - * - * @param specifiedDay - * @return - * @throws Exception - */ - public static String getSpecifiedDayBefore(String specifiedDay) { - Calendar c = Calendar.getInstance(); - Date date = null; - try { - date = new SimpleDateFormat("yy-MM-dd").parse(specifiedDay); - } catch (ParseException e) { - e.printStackTrace(); - } - c.setTime(date); - int day = c.get(Calendar.DATE); - c.set(Calendar.DATE, day - 1); - - String dayBefore = new SimpleDateFormat("yyyy-MM-dd").format(c.getTime()); - return dayBefore; - } - - /** - * 获取今日查询时间 - * - * @return - */ - public static Map getTodayDate(String time) { - Map map = new HashMap(16); - map.put("stime", time + " 00:00:00"); - map.put("etime", time + " 23:59:59"); - return map; - } - - - /** - * 根据发送时间获取有效截止时间 - * - * @param sendTime yyyy-MM-dd HH:mm:ss - * @param days 有效天数 - * @return - */ - public static LocalDate getExpiryDate(String sendTime, Integer days) { - if (ObjectUtil.isEmpty(sendTime)) { - sendTime = getCurrentTime(); - } - return LocalDate.parse(sendTime, DFY_MD_HMS) - .plusDays(days); - } - - /** - * 将年月日时分秒的各种转为cron表达式 - * - * @param time - * @return - */ - public static String toCronString(String time) { - LocalDateTime dateTime = LocalDateTime.parse(time, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); - return dateTime.getSecond() + " " + dateTime.getMinute() + " " + dateTime.getHour() + " " - + dateTime.getDayOfMonth() + " " + dateTime.getMonthValue() + " ? " + dateTime.getYear(); - } - - /** - * 获取当时时间 yyyy-MM-dd HH:mm:ss格式 - * - * @return - */ - public static String getCurrentTime() { - return localDateTimeFormatyMdHms(LocalDateTime.now()); - } - - /** - * 获取系统当前时间 - * - * @return 系统当前时间(年月日) - */ - public static String getCurrentDateHalf() { - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); - String date = simpleDateFormat.format(new Date()); - return date; - } - /** - * 获取系统未来某天的日期 - * - * @return 系统昨天时间(年月日) - */ - public static String getFutrueDateHalf(Integer day) { - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); - String date = simpleDateFormat.format(new Date()); - Calendar calendar = new GregorianCalendar(); - calendar.setTime(new Date()); - calendar.add(Calendar.DATE, day); - return simpleDateFormat.format(calendar.getTime()); - } - /** - * 获取系统前12小时时间 - * - * @return 系统前12小时时间(年月日) - */ - public static String getCurrentTimeBeforeTwHour() { - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - String date = simpleDateFormat.format(new Date()); - Calendar calendar = new GregorianCalendar(); - calendar.setTime(new Date()); - calendar.add(Calendar.HOUR, -12); - return simpleDateFormat.format(calendar.getTime()); - } - /** - * 获取系统昨天时间 - * - * @return 系统昨天时间(年月日) - */ - public static String getYesterDateHalf() { - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); - String date = simpleDateFormat.format(new Date()); - Calendar calendar = new GregorianCalendar(); - calendar.setTime(new Date()); - calendar.add(Calendar.DATE, -1); - return simpleDateFormat.format(calendar.getTime()); - } - /** - * 获取系统昨天时间 - * - * @return 系统昨天时间(年月日) - */ - public static String getAgoDateHalf(int i) { - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); - String date = simpleDateFormat.format(new Date()); - Calendar calendar = new GregorianCalendar(); - calendar.setTime(new Date()); - calendar.add(Calendar.DATE, -i); - return simpleDateFormat.format(calendar.getTime()); - } - /** - * 获取系统昨天时间 - * - * @return 系统昨天时间(年月日) - */ - public static String getWeekAgoDateHalf() { - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); - String date = simpleDateFormat.format(new Date()); - Calendar calendar = new GregorianCalendar(); - calendar.setTime(new Date()); - calendar.add(Calendar.DATE, -7); - return simpleDateFormat.format(calendar.getTime()); - } - /** - * 获取当时时间+10min yyyy-MM-dd HH:mm:ss格式 - * - * @return - */ - public static String getCurrentTimeAddTenMin() { - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - String date = simpleDateFormat.format(new Date()); - Calendar calendar = new GregorianCalendar(); - calendar.setTime(new Date()); - calendar.add(Calendar.MINUTE, 10); - return simpleDateFormat.format(calendar.getTime()); - } - - /**获取后两分钟 - * @param startTime - * @return - */ - public static String getLaterTimeAddTwoMin(String startTime){ - - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - Calendar calendar = new GregorianCalendar(); - try { - - calendar.setTime(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse(startTime)); - calendar.add(Calendar.MINUTE, 2); - } catch (Exception exception) { - LOGGER.error(exception.getMessage()); - } - return simpleDateFormat.format(calendar.getTime()); - } - /**获取前一天 - * @param startTime - * @return - */ - public static String getAgoTimeAddDay(String startTime){ - - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - Calendar calendar = new GregorianCalendar(); - try { - - calendar.setTime(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse(startTime)); - calendar.add(Calendar.HOUR, -24); - } catch (Exception exception) { - LOGGER.error(exception.getMessage()); - } - return simpleDateFormat.format(calendar.getTime()); - } - /**获取后一天 - * @param startTime - * @return - */ - public static String getLaterTimeAddDay(String startTime){ - - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - Calendar calendar = new GregorianCalendar(); - try { - - calendar.setTime(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse(startTime)); - calendar.add(Calendar.HOUR, 24); - } catch (Exception exception) { - LOGGER.error(exception.getMessage()); - } - return simpleDateFormat.format(calendar.getTime()); - } - /** 获取前十分钟 时间 - * @param startTime - * @return - */ - public static String getEarlyTimeAddTenMin(String startTime){ - - SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - Calendar calendar = new GregorianCalendar(); - try { - - calendar.setTime(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse(startTime)); - calendar.add(Calendar.MINUTE, -10); - } catch (Exception exception) { - LOGGER.error(exception.getMessage()); - } - return simpleDateFormat.format(calendar.getTime()); - } - - /** - * LocalDateTime 转时间戳 - * - * @param localDateTime / - * @return / - */ - public static Long getTimeStamp(LocalDateTime localDateTime) { - return localDateTime.atZone(ZoneId.systemDefault()).toEpochSecond(); - } - - /** - * 时间戳转LocalDateTime - * - * @param timeStamp / - * @return / - */ - public static LocalDateTime fromTimeStamp(Long timeStamp) { - return LocalDateTime.ofEpochSecond(timeStamp, 0, OffsetDateTime.now().getOffset()); - } - - /** - * LocalDateTime 转 Date - * Jdk8 后 不推荐使用 {@link Date} Date - * - * @param localDateTime / - * @return / - */ - public static Date toDate(LocalDateTime localDateTime) { - return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); - } - - /** - * LocalDate 转 Date - * Jdk8 后 不推荐使用 {@link Date} Date - * - * @param localDate / - * @return / - */ - public static Date toDate(LocalDate localDate) { - return toDate(localDate.atTime(LocalTime.now(ZoneId.systemDefault()))); - } - - - /** - * Date转 LocalDateTime - * Jdk8 后 不推荐使用 {@link Date} Date - * - * @param date / - * @return / - */ - public static LocalDateTime toLocalDateTime(Date date) { - return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()); - } - - /** - * 日期 格式化 - * - * @param localDateTime / - * @param patten / - * @return / - */ - public static String localDateTimeFormat(LocalDateTime localDateTime, String patten) { - DateTimeFormatter df = DateTimeFormatter.ofPattern(patten); - return df.format(localDateTime); - } - - /** - * 日期 格式化 - * - * @param localDateTime / - * @param df / - * @return / - */ - public static String localDateTimeFormat(LocalDateTime localDateTime, DateTimeFormatter df) { - return df.format(localDateTime); - } - - /** - * 日期格式化 yyyy-MM-dd HH:mm:ss - * - * @param localDateTime / - * @return / - */ - public static String localDateTimeFormatyMdHms(LocalDateTime localDateTime) { - return DFY_MD_HMS.format(localDateTime); - } - - /** - * 日期格式化 yyyy-MM-dd - * - * @param localDateTime / - * @return / - */ - public String localDateTimeFormatyMd(LocalDateTime localDateTime) { - return DFY_MD.format(localDateTime); - } - - /** - * 字符串转 LocalDateTime ,字符串格式 yyyy-MM-dd - * - * @param localDateTime / - * @return / - */ - public static LocalDateTime parseLocalDateTimeFormat(String localDateTime, String pattern) { - DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern); - return LocalDateTime.from(dateTimeFormatter.parse(localDateTime)); - } - - /** - * 字符串转 LocalDateTime ,字符串格式 yyyy-MM-dd - * - * @param localDateTime / - * @return / - */ - public static LocalDateTime parseLocalDateTimeFormat(String localDateTime, DateTimeFormatter dateTimeFormatter) { - return LocalDateTime.from(dateTimeFormatter.parse(localDateTime)); - } - - /** - * 字符串转 LocalDateTime ,字符串格式 yyyy-MM-dd HH:mm:ss - * - * @param localDateTime / - * @return / - */ - public static LocalDateTime parseLocalDateTimeFormatyMdHms(String localDateTime) { - return LocalDateTime.from(DFY_MD_HMS.parse(localDateTime)); - } - - /** - * 字符串转 LocalDate ,字符串格式 yyyy-MM-dd - * @param localDate - * @return - */ - public static LocalDate parseLocalDateFormatyMd(String localDate) { - return LocalDate.from(DFY_MD.parse(localDate)); - } - - /** - * 生成指定时间之前相聚 指定秒的一个时间并返回 - * 时间格式默认常规 年月日 时分秒: 2020-12-07 10:18:25 - * @param endTime - * @param min 相聚多少秒 - * @param max - * @return - */ - public static String getRandmo(String endTime, Integer min, Integer max) { - - if (min > max) { - return null; - } - - try { - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); - Date endTimeDate = format.parse(endTime); - Random random = new Random(); - long time = random.nextInt(max - min + 1) + min; - Date newDate = new Date(endTimeDate .getTime() - time * 1000); - return format.format(newDate); - }catch (Exception exception) { - return null; - } - } - - /** - * @Description: 获取当天日期再查询日期区间的第几个位置,起始位置从0开始算 - * @Author: zeng - * @param stime - * @param etime - * @return: java.lang.Integer - */ - public static Long getDifferenceDayCount(String stime,String etime) { - if (!ObjectUtil.isAllNotEmpty(stime, etime)) { - return null; - } - LocalDate sLocalDate = parseLocalDateTimeFormatyMdHms(stime).toLocalDate(); - LocalDate eLocalDate = parseLocalDateTimeFormatyMdHms(etime).toLocalDate(); - - return Math.abs(eLocalDate.toEpochDay() - sLocalDate.toEpochDay())+1; - } - - - public static String getHour(long dt) { - //秒数 -// Integer dt = Integer.parseInt(date) ; - if (dt < 3600) { - return Math.round(dt / 60) + "分钟"; - } - int hour = Math.round(dt / 3600); - int minute = Math.round((dt - (hour * 3600)) / 60); - long s = dt - (hour == 0 ? 0 : hour * 3600) - (minute == 0 ? 0 : minute * 60); - return hour == 0 ? "" : hour + "小时" + (minute == 0 ? "" : minute + "分钟") + (s == 0 ? "" : s + "秒"); - - //分钟 -// Integer dt = Integer.parseInt(date) ; -// if (dt < 60) return dt + "分钟"; -// int hour = Math.round(dt / 60); -// int minute = Math.round(dt - (hour * 60)); -// return hour + "小时" + (minute == 0 ? "" : minute + "分钟"); - } - -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/ElAdminConstant.java b/wjcy-common/src/main/java/me/zhengjie/utils/ElAdminConstant.java deleted file mode 100644 index 08f9c3c..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/ElAdminConstant.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.utils; - -/** - * 常用静态常量 - * - * @author Zheng Jie - * @date 2018-12-26 - */ -public class ElAdminConstant { - - /** - * 用于IP定位转换 - */ - public static final String REGION = "内网IP|内网IP"; - /** - * win 系统 - */ - public static final String WIN = "win"; - - /** - * mac 系统 - */ - public static final String MAC = "mac"; - - /** - * 常用接口 - */ - public static class Url { - // IP归属地查询 - public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp?ip=%s&json=true"; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/EmptyAttributeFiler.java b/wjcy-common/src/main/java/me/zhengjie/utils/EmptyAttributeFiler.java deleted file mode 100644 index c7fdd93..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/EmptyAttributeFiler.java +++ /dev/null @@ -1,76 +0,0 @@ -package me.zhengjie.utils; - - -import cn.hutool.core.util.ObjectUtil; -import lombok.extern.slf4j.Slf4j; - -import java.lang.reflect.Field; -import java.util.List; -/** - *

- * 将数据为空或空字符串的过滤为null(MyBatis 会将空字符串的值也持久化到数据库中) - *

- * - * @Author xx - * @Date 2021/7/19 - **/ -@Slf4j -public class EmptyAttributeFiler { - - /** - * 判断list的所有元素是否都为null - * @param list - * @return - */ - public static boolean isEmpty(List list) { - if (ObjectUtil.isEmpty(list)) { - return true; - } - for (Object o : list) { - if (ObjectUtil.isNotEmpty(o)) { - return false; - } - } - return true; - } - - public static T emptyAttributeFiler(T obj) { - Class clazz = obj.getClass(); - Field[] fields = clazz.getDeclaredFields(); - try { - for (Field field : fields) { - field.setAccessible(true); - if (ObjectUtil.isEmpty(field.get(obj))) { - field.set(obj, null); - } - } - } catch (Exception e) { - log.error("过滤值为空属性失败:" + e.getMessage(), e); - } - return obj; - } - - public static String emptyAttributeFilerToString(Object obj) { - Class clazz = obj.getClass(); - Field[] fields = clazz.getDeclaredFields(); - StringBuffer sbf = new StringBuffer("{"); - try { - int i = 0; - for (Field field : fields) { - field.setAccessible(true); - if (ObjectUtil.isNotEmpty(field.get(obj))) { - if (i != 0) { - sbf.append(","+field.getName() + ":" + field.get(obj)); - continue; - } - sbf.append(field.getName() + ":" + field.get(obj)); - i++; - } - } - } catch (Exception e) { - log.error("过滤值为空属性失败:" + e.getMessage(), e); - } - sbf.append("}"); - return sbf.toString().length()==2?"":sbf.toString(); - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/EncryptUtils.java b/wjcy-common/src/main/java/me/zhengjie/utils/EncryptUtils.java deleted file mode 100644 index 4f334aa..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/EncryptUtils.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.utils; - -import javax.crypto.Cipher; -import javax.crypto.SecretKey; -import javax.crypto.SecretKeyFactory; -import javax.crypto.spec.DESKeySpec; -import javax.crypto.spec.IvParameterSpec; -import java.nio.charset.StandardCharsets; - -/** - * 加密 - * @author Zheng Jie - * @date 2018-11-23 - */ - -public class EncryptUtils { - - private static final String STR_PARAM = "Passw0rd"; - - private static Cipher cipher; - - private static final IvParameterSpec IV = new IvParameterSpec(STR_PARAM.getBytes(StandardCharsets.UTF_8)); - - private static DESKeySpec getDesKeySpec(String source) throws Exception { - if (source == null || source.length() == 0){ - return null; - } - cipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); - String strKey = "Passw0rd"; - return new DESKeySpec(strKey.getBytes(StandardCharsets.UTF_8)); - } - - /** - * 对称加密 - */ - public static String desEncrypt(String source) throws Exception { - DESKeySpec desKeySpec = getDesKeySpec(source); - SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); - SecretKey secretKey = keyFactory.generateSecret(desKeySpec); - cipher.init(Cipher.ENCRYPT_MODE, secretKey, IV); - return byte2hex( - cipher.doFinal(source.getBytes(StandardCharsets.UTF_8))).toUpperCase(); - } - - /** - * 对称解密 - */ - public static String desDecrypt(String source) throws Exception { - byte[] src = hex2byte(source.getBytes(StandardCharsets.UTF_8)); - DESKeySpec desKeySpec = getDesKeySpec(source); - SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); - SecretKey secretKey = keyFactory.generateSecret(desKeySpec); - cipher.init(Cipher.DECRYPT_MODE, secretKey, IV); - byte[] retByte = cipher.doFinal(src); - return new String(retByte); - } - - private static String byte2hex(byte[] inStr) { - String stmp; - StringBuilder out = new StringBuilder(inStr.length * 2); - for (byte b : inStr) { - stmp = Integer.toHexString(b & 0xFF); - if (stmp.length() == 1) { - // 如果是0至F的单位字符串,则添加0 - out.append("0").append(stmp); - } else { - out.append(stmp); - } - } - return out.toString(); - } - - private static byte[] hex2byte(byte[] b) { - int size = 2; - if ((b.length % size) != 0){ - throw new IllegalArgumentException("长度不是偶数"); - } - byte[] b2 = new byte[b.length / 2]; - for (int n = 0; n < b.length; n += size) { - String item = new String(b, n, 2); - b2[n / 2] = (byte) Integer.parseInt(item, 16); - } - return b2; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/FileUtil.java b/wjcy-common/src/main/java/me/zhengjie/utils/FileUtil.java deleted file mode 100644 index e8577d0..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/FileUtil.java +++ /dev/null @@ -1,351 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.utils; - -import cn.hutool.core.io.IoUtil; -import cn.hutool.core.util.IdUtil; -import cn.hutool.poi.excel.BigExcelWriter; -import cn.hutool.poi.excel.ExcelUtil; -import me.zhengjie.exception.BadRequestException; -import org.apache.poi.util.IOUtils; -import org.apache.poi.xssf.streaming.SXSSFSheet; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.web.multipart.MultipartFile; -import javax.servlet.ServletOutputStream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.*; -import java.security.MessageDigest; -import java.text.DecimalFormat; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.List; -import java.util.Map; - -/** - * File工具类,扩展 hutool 工具包 - * - * @author Zheng Jie - * @date 2018-12-27 - */ -public class FileUtil extends cn.hutool.core.io.FileUtil { - - private static final Logger log = LoggerFactory.getLogger(FileUtil.class); - - /** - * 系统临时目录 - *
- * windows 包含路径分割符,但Linux 不包含, - * 在windows \\==\ 前提下, - * 为安全起见 同意拼装 路径分割符, - *
-     *       java.io.tmpdir
-     *       windows : C:\Users/xxx\AppData\Local\Temp\
-     *       linux: /temp
-     * 
- */ - public static final String SYS_TEM_DIR = System.getProperty("java.io.tmpdir") + File.separator; - /** - * 定义GB的计算常量 - */ - private static final int GB = 1024 * 1024 * 1024; - /** - * 定义MB的计算常量 - */ - private static final int MB = 1024 * 1024; - /** - * 定义KB的计算常量 - */ - private static final int KB = 1024; - - /** - * 格式化小数 - */ - private static final DecimalFormat DF = new DecimalFormat("0.00"); - - public static final String IMAGE = "图片"; - public static final String TXT = "文档"; - public static final String MUSIC = "音乐"; - public static final String VIDEO = "视频"; - public static final String OTHER = "其他"; - - - /** - * MultipartFile转File - */ - public static File toFile(MultipartFile multipartFile) { - // 获取文件名 - String fileName = multipartFile.getOriginalFilename(); - // 获取文件后缀 - String prefix = "." + getExtensionName(fileName); - File file = null; - try { - // 用uuid作为文件名,防止生成的临时文件重复 - file = new File(SYS_TEM_DIR + IdUtil.simpleUUID() + prefix); - // MultipartFile to File - multipartFile.transferTo(file); - } catch (IOException e) { - log.error(e.getMessage(), e); - } - return file; - } - - /** - * 获取文件扩展名,不带 . - */ - public static String getExtensionName(String filename) { - if ((filename != null) && (filename.length() > 0)) { - int dot = filename.lastIndexOf('.'); - if ((dot > -1) && (dot < (filename.length() - 1))) { - return filename.substring(dot + 1); - } - } - return filename; - } - - /** - * Java文件操作 获取不带扩展名的文件名 - */ - public static String getFileNameNoEx(String filename) { - if ((filename != null) && (filename.length() > 0)) { - int dot = filename.lastIndexOf('.'); - if ((dot > -1) && (dot < (filename.length()))) { - return filename.substring(0, dot); - } - } - return filename; - } - - /** - * 文件大小转换 - */ - public static String getSize(long size) { - String resultSize; - if (size / GB >= 1) { - //如果当前Byte的值大于等于1GB - resultSize = DF.format(size / (float) GB) + "GB "; - } else if (size / MB >= 1) { - //如果当前Byte的值大于等于1MB - resultSize = DF.format(size / (float) MB) + "MB "; - } else if (size / KB >= 1) { - //如果当前Byte的值大于等于1KB - resultSize = DF.format(size / (float) KB) + "KB "; - } else { - resultSize = size + "B "; - } - return resultSize; - } - - /** - * inputStream 转 File - */ - public static File inputStreamToFile(InputStream ins, String name){ - File file = new File(SYS_TEM_DIR + name); - if (file.exists()) { - return file; - } - OutputStream os = null; - try { - os = new FileOutputStream(file); - int bytesRead; - int len = 8192; - byte[] buffer = new byte[len]; - while ((bytesRead = ins.read(buffer, 0, len)) != -1) { - os.write(buffer, 0, bytesRead); - } - } catch (Exception e) { - e.printStackTrace(); - } finally { - CloseUtil.close(os); - CloseUtil.close(ins); - } - return file; - } - - /** - * 将文件名解析成文件的上传路径 - */ - public static File upload(MultipartFile file, String filePath) { - Date date = new Date(); - SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmssS"); - String name = getFileNameNoEx(file.getOriginalFilename()); - String suffix = getExtensionName(file.getOriginalFilename()); - String nowStr = "-" + format.format(date); - try { - String fileName = name + nowStr + "." + suffix; - String path = filePath + fileName; - // getCanonicalFile 可解析正确各种路径 - File dest = new File(path).getCanonicalFile(); - // 检测是否存在目录 - if (!dest.getParentFile().exists()) { - if (!dest.getParentFile().mkdirs()) { - System.out.println("was not successful."); - } - } - // 文件写入 - file.transferTo(dest); - return dest; - } catch (Exception e) { - log.error(e.getMessage(), e); - } - return null; - } - - /** - * 导出excel - */ - public static void downloadExcel(List> list, HttpServletResponse response) throws IOException { - String tempPath = SYS_TEM_DIR + IdUtil.fastSimpleUUID() + ".xlsx"; - File file = new File(tempPath); - BigExcelWriter writer = ExcelUtil.getBigWriter(file); - // 一次性写出内容,使用默认样式,强制输出标题 - writer.write(list, true); - //response为HttpServletResponse对象 - response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8"); - //test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码 - response.setHeader("Content-Disposition", "attachment;filename=file.xlsx"); - ServletOutputStream out = response.getOutputStream(); - // 终止后删除临时文件 - file.deleteOnExit(); - writer.flush(out, true); - //此处记得关闭输出Servlet流 - IoUtil.close(out); - } - - public static String getFileType(String type) { - String documents = "txt doc pdf ppt pps xlsx xls docx"; - String music = "mp3 wav wma mpa ram ra aac aif m4a"; - String video = "avi mpg mpe mpeg asf wmv mov qt rm mp4 flv m4v webm ogv ogg"; - String image = "bmp dib pcp dif wmf gif jpg tif eps psd cdr iff tga pcd mpt png jpeg"; - if (image.contains(type)) { - return IMAGE; - } else if (documents.contains(type)) { - return TXT; - } else if (music.contains(type)) { - return MUSIC; - } else if (video.contains(type)) { - return VIDEO; - } else { - return OTHER; - } - } - - public static void checkSize(long maxSize, long size) { - // 1M - int len = 1024 * 1024; - if (size > (maxSize * len)) { - throw new BadRequestException("文件超出规定大小"); - } - } - - /** - * 判断两个文件是否相同 - */ - public static boolean check(File file1, File file2) { - String img1Md5 = getMd5(file1); - String img2Md5 = getMd5(file2); - if(img1Md5 != null){ - return img1Md5.equals(img2Md5); - } - return false; - } - - /** - * 判断两个文件是否相同 - */ - public static boolean check(String file1Md5, String file2Md5) { - return file1Md5.equals(file2Md5); - } - - private static byte[] getByte(File file) { - // 得到文件长度 - byte[] b = new byte[(int) file.length()]; - InputStream in = null; - try { - in = new FileInputStream(file); - try { - System.out.println(in.read(b)); - } catch (IOException e) { - log.error(e.getMessage(), e); - } - } catch (Exception e) { - log.error(e.getMessage(), e); - return null; - } finally { - CloseUtil.close(in); - } - return b; - } - - private static String getMd5(byte[] bytes) { - // 16进制字符 - char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; - try { - MessageDigest mdTemp = MessageDigest.getInstance("MD5"); - mdTemp.update(bytes); - byte[] md = mdTemp.digest(); - int j = md.length; - char[] str = new char[j * 2]; - int k = 0; - // 移位 输出字符串 - for (byte byte0 : md) { - str[k++] = hexDigits[byte0 >>> 4 & 0xf]; - str[k++] = hexDigits[byte0 & 0xf]; - } - return new String(str); - } catch (Exception e) { - log.error(e.getMessage(), e); - } - return null; - } - - /** - * 下载文件 - * - * @param request / - * @param response / - * @param file / - */ - public static void downloadFile(HttpServletRequest request, HttpServletResponse response, File file, boolean deleteOnExit) { - response.setCharacterEncoding(request.getCharacterEncoding()); - response.setContentType("application/octet-stream"); - FileInputStream fis = null; - try { - fis = new FileInputStream(file); - response.setHeader("Content-Disposition", "attachment; filename=" + file.getName()); - IOUtils.copy(fis, response.getOutputStream()); - response.flushBuffer(); - } catch (Exception e) { - log.error(e.getMessage(), e); - } finally { - if (fis != null) { - try { - fis.close(); - if (deleteOnExit) { - file.deleteOnExit(); - } - } catch (IOException e) { - log.error(e.getMessage(), e); - } - } - } - } - - public static String getMd5(File file) { - return getMd5(getByte(file)); - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/HexUtil.java b/wjcy-common/src/main/java/me/zhengjie/utils/HexUtil.java deleted file mode 100644 index 96cf5d5..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/HexUtil.java +++ /dev/null @@ -1,51 +0,0 @@ -package me.zhengjie.utils; - -import cn.hutool.core.util.ObjectUtil; -import static jodd.util.CharUtil.HEX_CHARS; -/** - *

- * dy登录加密校验 - *

- * - * @Author xx - * @Date 2021/7/21 - **/ -public class HexUtil { - - public static String toHexString(byte[] bArr, int i, int i2) { - if (bArr == null) { - throw new NullPointerException("bytes is null"); - } else if (i < 0 || i + i2 > bArr.length) { - throw new IndexOutOfBoundsException(); - } else { - int i3 = i2 * 2; - char[] cArr = new char[i3]; - int i4 = 0; - for (int i5 = 0; i5 < i2; i5++) { - int i6 = bArr[i5 + i] & 255; - int i7 = i4 + 1; - cArr[i4] = HEX_CHARS[i6 >> 4]; - i4 = i7 + 1; - cArr[i7] = HEX_CHARS[i6 & 15]; - } - return new String(cArr, 0, i3); - } - } - - - public static String encryptWithXor(String str) { - try { - if (ObjectUtil.isEmpty(str)) { - return null; - } - byte[] bytes = str.getBytes("UTF-8"); - for (int i = 0; i < bytes.length; i++) { - bytes[i] = (byte) (bytes[i] ^ 5); - } - return toHexString(bytes, 0, bytes.length); - } catch (Exception unused) { - return str; - } - } - -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/HttpClientUtil.java b/wjcy-common/src/main/java/me/zhengjie/utils/HttpClientUtil.java deleted file mode 100644 index 618c216..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/HttpClientUtil.java +++ /dev/null @@ -1,356 +0,0 @@ -package me.zhengjie.utils; - -import cn.hutool.core.convert.Convert; -import cn.hutool.core.map.MapUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; -import cn.hutool.json.JSONUtil; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.NameValuePair; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.message.BasicNameValuePair; -import org.apache.http.util.EntityUtils; - -import java.io.IOException; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -/** - * @author rch - * @date 2022-06-22 - */ -@Slf4j -public class HttpClientUtil { - - public static String postJson(String url, String body, String charset) { - - String result = null; - if (null == charset) { - charset = "UTF-8"; - } - CloseableHttpClient httpClient = null; - HttpPost httpPost = null; - try { - httpClient = HttpConnectionManager.getInstance().getHttpClient(); - httpPost = new HttpPost(url); - - // 设置连接超时,设置读取超时 - RequestConfig requestConfig = RequestConfig.custom() - .setConnectTimeout(3000) - .setSocketTimeout(3000) - .build(); - httpPost.setConfig(requestConfig); - - httpPost.setHeader("Accept", "application/json"); - httpPost.setHeader("Content-Type", "application/json;charset=utf-8"); - - // 设置参数 - StringEntity se = new StringEntity(body, "UTF-8"); - httpPost.setEntity(se); - HttpResponse response = httpClient.execute(httpPost); - if (response != null) { - HttpEntity resEntity = response.getEntity(); - if (resEntity != null) { - result = EntityUtils.toString(resEntity, charset); - } - } - } catch (Exception ex) { - ex.printStackTrace(); - log.error(ex.getMessage()); - } - - return result; - } - - - public static String postJson(String url, Map heards, String body, String charset) { - - String result = null; - if (null == charset) { - charset = "UTF-8"; - } - CloseableHttpClient httpClient = null; - HttpPost httpPost = null; - try { - httpClient = HttpConnectionManager.getInstance().getHttpClient(); - httpPost = new HttpPost(url); - - // 设置连接超时,设置读取超时 - RequestConfig requestConfig = RequestConfig.custom() - .setConnectTimeout(3000) - .setSocketTimeout(3000) - .build(); - httpPost.setConfig(requestConfig); - - for (Map.Entry heard:heards.entrySet()) { - httpPost.setHeader(heard.getKey(), heard.getValue().toString()); - } - - // 设置参数 - StringEntity se = new StringEntity(body, "UTF-8"); - httpPost.setEntity(se); - HttpResponse response = httpClient.execute(httpPost); - if (response != null) { - HttpEntity resEntity = response.getEntity(); - if (resEntity != null) { - result = EntityUtils.toString(resEntity, charset); - } - } - } catch (Exception ex) { - ex.printStackTrace(); - log.error(ex.getMessage()); - } - - return result; - } - - - /** - * 发送 POST 请求(HTTP),K-V形式 - * - * @param apiUrl - * API接口URL - * @param params - * 参数map - * @return - */ - public static String doPostHttp(String apiUrl, Map params) { - CloseableHttpClient httpClient = HttpClients.createDefault(); - String httpStr = null; - HttpPost httpPost = new HttpPost(apiUrl); - CloseableHttpResponse response = null; - - try { - // 设置连接超时,设置读取超时 - RequestConfig requestConfig = RequestConfig.custom() - .setConnectTimeout(10000) - .setSocketTimeout(10000) - .build(); - httpPost.setConfig(requestConfig); - httpPost.setHeader("Accept", "application/json"); - httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded"); - - List pairList = new ArrayList<>(params.size()); - for (Entry entry : params.entrySet()) { - NameValuePair pair = new BasicNameValuePair(entry.getKey(), Convert.toStr(entry.getValue())); - pairList.add(pair); - } - httpPost.setEntity(new UrlEncodedFormEntity(pairList, Charset.forName("UTF-8"))); - response = httpClient.execute(httpPost); -// System.out.println("http==response.toString():" + response.toString()); - HttpEntity entity = response.getEntity(); - httpStr = EntityUtils.toString(entity, "UTF-8"); - } catch (IOException e) { - e.printStackTrace(); - log.error(e.getMessage()); - } finally { - if (response != null) { - try { - EntityUtils.consume(response.getEntity()); - } catch (IOException e) { - e.printStackTrace(); - log.error(e.getMessage()); - } - } - } - return httpStr; - } - - /** - * 发送 GET 请求(HTTP),K-V形式 - * - * @param apiUrl - * API接口URL - * @param params - * 参数map - * @return - */ - public static String getHttp(String apiUrl,Map params){ - CloseableHttpClient httpClient = null; - CloseableHttpResponse response = null; - String result = ""; - try { - String url = apiUrl; - if(MapUtil.isNotEmpty(params)){ - String paramsStr = ""; - for (String key : params.keySet()) { - if(ObjectUtil.isNotEmpty(params.get(key))){ - if(StrUtil.isNotEmpty(paramsStr)){ - paramsStr += "&" + key + "=" + params.get(key); - }else{ - paramsStr += key + "=" + params.get(key); - } - } - } - if(StrUtil.isNotEmpty(paramsStr)){ - url += "?" + paramsStr; - } - } - httpClient = HttpClients.createDefault(); - System.out.println("url:" + url); - HttpGet httpGet = new HttpGet(url); - // 设置连接超时,设置读取超时 - RequestConfig requestConfig = RequestConfig.custom() - .setConnectTimeout(5000) - .setSocketTimeout(5000) - .build(); - httpGet.setConfig(requestConfig); - response = httpClient.execute(httpGet); - HttpEntity entity = response.getEntity(); - result = EntityUtils.toString(entity, "UTF-8"); - } catch (IOException e) { - e.printStackTrace(); - log.error(e.getMessage()); - } finally { - if (response != null) { - try { - response.close(); - } catch (IOException e) { - e.printStackTrace(); - log.error(e.getMessage()); - } - } - if (httpClient != null) { - try { - httpClient.close(); - } catch (IOException e) { - e.printStackTrace(); - log.error(e.getMessage()); - } - } - } - return result; - } - - - - /** - * 发送 GET 请求(HTTP) - * - * @param apiUrl - * API接口URL - * @return - */ - public static String getUrlHttp(String apiUrl){ - CloseableHttpClient httpClient = null; - CloseableHttpResponse response = null; - String result = ""; - try { - String url = apiUrl; - httpClient = HttpClients.createDefault(); - System.out.println("url:" + url); - HttpGet httpGet = new HttpGet(url); - // 设置连接超时,设置读取超时 - RequestConfig requestConfig = RequestConfig.custom() - .setConnectTimeout(5000) - .setSocketTimeout(5000) - .build(); - httpGet.setConfig(requestConfig); - response = httpClient.execute(httpGet); - HttpEntity entity = response.getEntity(); - result = EntityUtils.toString(entity, "UTF-8"); - } catch (IOException e) { - e.printStackTrace(); - log.error(e.getMessage()); - } finally { - if (response != null) { - try { - response.close(); - } catch (IOException e) { - e.printStackTrace(); - log.error(e.getMessage()); - } - } - if (httpClient != null) { - try { - httpClient.close(); - } catch (IOException e) { - e.printStackTrace(); - log.error(e.getMessage()); - } - } - } - return result; - } - - /** - * 发送 POST 请求(HTTP),K-V形式 - * - * @param apiUrl - * API接口URL - * @param params - * 参数map - * @return - */ - public static String postHttp(String apiUrl,Map params){ - CloseableHttpClient httpClient = null; - CloseableHttpResponse response = null; - String result = ""; - try { - String url = apiUrl; - httpClient = HttpClients.createDefault(); - HttpPost httpPost = new HttpPost(url); - // 设置连接超时,设置读取超时 - RequestConfig requestConfig = RequestConfig.custom() - .setConnectTimeout(5000) - .setSocketTimeout(5000) - .build(); - httpPost.setConfig(requestConfig); - if(MapUtil.isNotEmpty(params)){ - StringEntity se = new StringEntity(JSONUtil.toJsonStr(params), "UTF-8"); - se.setContentType("application/json"); - httpPost.setEntity(se); - } - response = httpClient.execute(httpPost); - HttpEntity entity = response.getEntity(); - result = EntityUtils.toString(entity, "UTF-8"); - } catch (IOException e) { - e.printStackTrace(); - log.error(e.getMessage()); - } finally { - if (response != null) { - try { - EntityUtils.consume(response.getEntity()); - } catch (IOException e) { - e.printStackTrace(); - log.error(e.getMessage()); - } - } - if (httpClient != null) { - try { - httpClient.close(); - } catch (IOException e) { - e.printStackTrace(); - log.error(e.getMessage()); - } - } - } - return result; - } - - - public static void main(String[] args) { - String url = "http://kjw.utest6.com/forcol/a"; - Map params = new HashMap<>(16); - params.put("page",1); - params.put("pageSize",10000); - params.put("beginTime","2022-04-01 21:00:00"); - - String result = postHttp(url,params); - System.out.println(result); - } - -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/HttpConnectionManager.java b/wjcy-common/src/main/java/me/zhengjie/utils/HttpConnectionManager.java deleted file mode 100644 index 85dc9c8..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/HttpConnectionManager.java +++ /dev/null @@ -1,57 +0,0 @@ -package me.zhengjie.utils; - - -import org.apache.http.config.Registry; -import org.apache.http.config.RegistryBuilder; -import org.apache.http.conn.socket.ConnectionSocketFactory; -import org.apache.http.conn.socket.LayeredConnectionSocketFactory; -import org.apache.http.conn.socket.PlainConnectionSocketFactory; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; -import org.springframework.stereotype.Component; - -import javax.net.ssl.SSLContext; -import java.security.NoSuchAlgorithmException; - -@Component -public class HttpConnectionManager { - - private PoolingHttpClientConnectionManager cm = null; - - private static HttpConnectionManager connectionManager; - - public static HttpConnectionManager getInstance() { - if (connectionManager == null) { - synchronized (HttpConnectionManager.class) { - if (connectionManager == null) { - connectionManager = new HttpConnectionManager(); - connectionManager.init(); - } - } - } - return connectionManager; - } - - private void init() { - LayeredConnectionSocketFactory sslsf = null; - try { - sslsf = new SSLConnectionSocketFactory(SSLContext.getDefault()); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } - - Registry socketFactoryRegistry = RegistryBuilder. create() - .register("https", sslsf).register("http", new PlainConnectionSocketFactory()).build(); - cm = new PoolingHttpClientConnectionManager(socketFactoryRegistry); - cm.setMaxTotal(200); - cm.setDefaultMaxPerRoute(20); - } - - public CloseableHttpClient getHttpClient() { - CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm).build(); - - return httpClient; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/IpUtils.java b/wjcy-common/src/main/java/me/zhengjie/utils/IpUtils.java deleted file mode 100644 index 7da2af7..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/IpUtils.java +++ /dev/null @@ -1,380 +0,0 @@ -package me.zhengjie.utils; - -import java.net.InetAddress; -import java.net.UnknownHostException; -import javax.servlet.http.HttpServletRequest; - -/** - * 获取IP方法 - * - * @author ruoyi - */ -public class IpUtils -{ - public final static String REGX_0_255 = "(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]\\d|\\d)"; - // 匹配 ip - public final static String REGX_IP = "((" + REGX_0_255 + "\\.){3}" + REGX_0_255 + ")"; - public final static String REGX_IP_WILDCARD = "(((\\*\\.){3}\\*)|(" + REGX_0_255 + "(\\.\\*){3})|(" + REGX_0_255 + "\\." + REGX_0_255 + ")(\\.\\*){2}" + "|((" + REGX_0_255 + "\\.){3}\\*))"; - // 匹配网段 - public final static String REGX_IP_SEG = "(" + REGX_IP + "\\-" + REGX_IP + ")"; - - /** - * 获取客户端IP - * - * @return IP地址 - */ - public static String getIpAddr() - { - return getIpAddr(ServletUtils.getRequest()); - } - - /** - * 获取客户端IP - * - * @param request 请求对象 - * @return IP地址 - */ - public static String getIpAddr(HttpServletRequest request) - { - if (request == null) - { - return "unknown"; - } - String ip = request.getHeader("x-forwarded-for"); - if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) - { - ip = request.getHeader("Proxy-Client-IP"); - } - if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) - { - ip = request.getHeader("X-Forwarded-For"); - } - if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) - { - ip = request.getHeader("WL-Proxy-Client-IP"); - } - if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) - { - ip = request.getHeader("X-Real-IP"); - } - - if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) - { - ip = request.getRemoteAddr(); - } - - return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : getMultistageReverseProxyIp(ip); - } - - /** - * 检查是否为内部IP地址 - * - * @param ip IP地址 - * @return 结果 - */ - public static boolean internalIp(String ip) - { - byte[] addr = textToNumericFormatV4(ip); - return internalIp(addr) || "127.0.0.1".equals(ip); - } - - /** - * 检查是否为内部IP地址 - * - * @param addr byte地址 - * @return 结果 - */ - private static boolean internalIp(byte[] addr) - { - if (NewStringUtils.isNull(addr) || addr.length < 2) - { - return true; - } - final byte b0 = addr[0]; - final byte b1 = addr[1]; - // 10.x.x.x/8 - final byte SECTION_1 = 0x0A; - // 172.16.x.x/12 - final byte SECTION_2 = (byte) 0xAC; - final byte SECTION_3 = (byte) 0x10; - final byte SECTION_4 = (byte) 0x1F; - // 192.168.x.x/16 - final byte SECTION_5 = (byte) 0xC0; - final byte SECTION_6 = (byte) 0xA8; - switch (b0) - { - case SECTION_1: - return true; - case SECTION_2: - if (b1 >= SECTION_3 && b1 <= SECTION_4) - { - return true; - } - case SECTION_5: - switch (b1) - { - case SECTION_6: - return true; - } - default: - return false; - } - } - - /** - * 将IPv4地址转换成字节 - * - * @param text IPv4地址 - * @return byte 字节 - */ - public static byte[] textToNumericFormatV4(String text) - { - if (text.length() == 0) - { - return null; - } - - byte[] bytes = new byte[4]; - String[] elements = text.split("\\.", -1); - try - { - long l; - int i; - switch (elements.length) - { - case 1: - l = Long.parseLong(elements[0]); - if ((l < 0L) || (l > 4294967295L)) - { - return null; - } - bytes[0] = (byte) (int) (l >> 24 & 0xFF); - bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF); - bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); - bytes[3] = (byte) (int) (l & 0xFF); - break; - case 2: - l = Integer.parseInt(elements[0]); - if ((l < 0L) || (l > 255L)) - { - return null; - } - bytes[0] = (byte) (int) (l & 0xFF); - l = Integer.parseInt(elements[1]); - if ((l < 0L) || (l > 16777215L)) - { - return null; - } - bytes[1] = (byte) (int) (l >> 16 & 0xFF); - bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); - bytes[3] = (byte) (int) (l & 0xFF); - break; - case 3: - for (i = 0; i < 2; ++i) - { - l = Integer.parseInt(elements[i]); - if ((l < 0L) || (l > 255L)) - { - return null; - } - bytes[i] = (byte) (int) (l & 0xFF); - } - l = Integer.parseInt(elements[2]); - if ((l < 0L) || (l > 65535L)) - { - return null; - } - bytes[2] = (byte) (int) (l >> 8 & 0xFF); - bytes[3] = (byte) (int) (l & 0xFF); - break; - case 4: - for (i = 0; i < 4; ++i) - { - l = Integer.parseInt(elements[i]); - if ((l < 0L) || (l > 255L)) - { - return null; - } - bytes[i] = (byte) (int) (l & 0xFF); - } - break; - default: - return null; - } - } - catch (NumberFormatException e) - { - return null; - } - return bytes; - } - - /** - * 获取IP地址 - * - * @return 本地IP地址 - */ - public static String getHostIp() - { - try - { - return InetAddress.getLocalHost().getHostAddress(); - } - catch (UnknownHostException e) - { - } - return "127.0.0.1"; - } - - /** - * 获取主机名 - * - * @return 本地主机名 - */ - public static String getHostName() - { - try - { - return InetAddress.getLocalHost().getHostName(); - } - catch (UnknownHostException e) - { - } - return "未知"; - } - - /** - * 从多级反向代理中获得第一个非unknown IP地址 - * - * @param ip 获得的IP地址 - * @return 第一个非unknown IP地址 - */ - public static String getMultistageReverseProxyIp(String ip) - { - // 多级反向代理检测 - if (ip != null && ip.indexOf(",") > 0) - { - final String[] ips = ip.trim().split(","); - for (String subIp : ips) - { - if (false == isUnknown(subIp)) - { - ip = subIp; - break; - } - } - } - return StringUtils.substring(ip, 0, 255); - } - - /** - * 检测给定字符串是否为未知,多用于检测HTTP请求相关 - * - * @param checkString 被检测的字符串 - * @return 是否未知 - */ - public static boolean isUnknown(String checkString) - { - return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString); - } - - /** - * 是否为IP - */ - public static boolean isIP(String ip) - { - return StringUtils.isNotBlank(ip) && ip.matches(REGX_IP); - } - - /** - * 是否为IP,或 *为间隔的通配符地址 - */ - public static boolean isIpWildCard(String ip) - { - return StringUtils.isNotBlank(ip) && ip.matches(REGX_IP_WILDCARD); - } - - /** - * 检测参数是否在ip通配符里 - */ - public static boolean ipIsInWildCardNoCheck(String ipWildCard, String ip) - { - String[] s1 = ipWildCard.split("\\."); - String[] s2 = ip.split("\\."); - boolean isMatchedSeg = true; - for (int i = 0; i < s1.length && !s1[i].equals("*"); i++) - { - if (!s1[i].equals(s2[i])) - { - isMatchedSeg = false; - break; - } - } - return isMatchedSeg; - } - - /** - * 是否为特定格式如:“10.10.10.1-10.10.10.99”的ip段字符串 - */ - public static boolean isIPSegment(String ipSeg) - { - return StringUtils.isNotBlank(ipSeg) && ipSeg.matches(REGX_IP_SEG); - } - - /** - * 判断ip是否在指定网段中 - */ - public static boolean ipIsInNetNoCheck(String iparea, String ip) - { - int idx = iparea.indexOf('-'); - String[] sips = iparea.substring(0, idx).split("\\."); - String[] sipe = iparea.substring(idx + 1).split("\\."); - String[] sipt = ip.split("\\."); - long ips = 0L, ipe = 0L, ipt = 0L; - for (int i = 0; i < 4; ++i) - { - ips = ips << 8 | Integer.parseInt(sips[i]); - ipe = ipe << 8 | Integer.parseInt(sipe[i]); - ipt = ipt << 8 | Integer.parseInt(sipt[i]); - } - if (ips > ipe) - { - long t = ips; - ips = ipe; - ipe = t; - } - return ips <= ipt && ipt <= ipe; - } - - /** - * 校验ip是否符合过滤串规则 - * - * @param filter 过滤IP列表,支持后缀'*'通配,支持网段如:`10.10.10.1-10.10.10.99` - * @param ip 校验IP地址 - * @return boolean 结果 - */ - public static boolean isMatchedIp(String filter, String ip) - { - if (StringUtils.isEmpty(filter) || StringUtils.isEmpty(ip)) - { - return false; - } - String[] ips = filter.split(";"); - for (String iStr : ips) - { - if (isIP(iStr) && iStr.equals(ip)) - { - return true; - } - else if (isIpWildCard(iStr) && ipIsInWildCardNoCheck(iStr, ip)) - { - return true; - } - else if (isIPSegment(iStr) && ipIsInNetNoCheck(iStr, ip)) - { - return true; - } - } - return false; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/JsonDealUtils.java b/wjcy-common/src/main/java/me/zhengjie/utils/JsonDealUtils.java deleted file mode 100644 index ecf2793..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/JsonDealUtils.java +++ /dev/null @@ -1,54 +0,0 @@ -package me.zhengjie.utils; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; - -import java.util.Iterator; -import java.util.Set; - -/** - * 递归去除Json字符串空值(key和value) - * - * @author rch - * @create 2022-06-27 - */ -public class JsonDealUtils { - - public static JSONObject getNoNullValue(String json) { - JSONObject objTem=JSON.parseObject(json); - JSONObject objRel=JSON.parseObject(json); - return deal(objTem,objRel); - } - - private static JSONObject deal(JSONObject objTem,JSONObject objRel) { - Set keySet = objTem.keySet(); - Iterator iterator = keySet.iterator(); - while(iterator.hasNext()) { - String temp = iterator.next(); - Object objR = objTem.get(temp); - if(temp==null||"".equals(temp)||"null".equals(temp)) { - objRel.remove(temp); - continue; - } - if(objR==null||"".equals(objR.toString())||"null".equals(objR.toString())||"[]".equals(objR.toString())||"{}".equals(objR.toString())) { - objRel.remove(temp); - continue; - } - if(objR instanceof JSONObject) { - JSONObject j=(JSONObject)objR; - JSONObject object2 = (JSONObject)objRel.get(temp); - deal(j,object2); - continue; - } - if(objR instanceof JSONArray) { - JSONArray jsonArray = objTem.getJSONArray(temp); - JSONArray jsonArray2 = objRel.getJSONArray(temp); - for(int i=0;i - * MD5工具类 - *

- * - * @author: rch - * @since: 2020-12-03 - */ - -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -public class MD5Util { - - /** * 生成16位小写md5加密字符串 * @param sourceStr * @return */ - public static String MD5ToLow16(String sourceStr) { - try { - // 获得MD5摘要算法的 MessageDigest对象 - StringBuffer buf = getMD5StringBuffer(sourceStr); - return buf.toString().substring(8, 24).toLowerCase();// 16位加密 - // return buf.toString();// 32位加密 - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - /** * 生成16位大写md5加密字符串 * @param sourceStr * @return */ - public static String MD5ToUpp16(String sourceStr) { - try { - // 获得MD5摘要算法的 MessageDigest对象 - StringBuffer buf = getMD5StringBuffer(sourceStr); - return buf.toString().substring(8, 24).toUpperCase();// 16位加密 - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - /** * 生成32位小写md5加密字符串 * @param sourceStr * @return */ - public static String MD5ToLow32(String sourceStr) { - try { - // 获得MD5摘要算法的 MessageDigest对象 - StringBuffer buf = getMD5StringBuffer(sourceStr); - return buf.toString().toLowerCase();// 32位加密 - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - /** * 生成32位大写md5加密字符串 * @param sourceStr * @return */ - public static String MD5ToUpp32(String sourceStr) { - try { - StringBuffer buf = getMD5StringBuffer(sourceStr); - - return buf.toString().toUpperCase();// 32位加密 - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - - /** * 将字符串MD5加密 * @param sourceStr * @return * @throws NoSuchAlgorithmException */ - private static StringBuffer getMD5StringBuffer(String sourceStr) throws NoSuchAlgorithmException { - // 获得MD5摘要算法的 MessageDigest对象 - MessageDigest mdInst = MessageDigest.getInstance("MD5"); - // 使用指定的字节更新摘要 - mdInst.update(sourceStr.getBytes()); - // 获得密文 - byte[] md = mdInst.digest(); - // 把密文转换成十六进制的字符串形式 - StringBuffer buf = new StringBuffer(); - for (int i = 0; i < md.length; i++) { - int tmp = md[i]; - if (tmp < 0){ - tmp += 256; - } - if (tmp < 16){ - buf.append("0"); - } - buf.append(Integer.toHexString(tmp)); - } - return buf; - } - - public static String md5(String str) { - try { - MessageDigest md5 = MessageDigest.getInstance("MD5"); - md5.update((str).getBytes("UTF-8")); - byte b[] = md5.digest(); - - int i; - StringBuffer buf = new StringBuffer(""); - - for (int offset = 0; offset < b.length; offset++) { - i = b[offset]; - if (i < 0) { - i += 256; - } - if (i < 16) { - buf.append("0"); - } - buf.append(Integer.toHexString(i)); - } - return buf.toString(); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - public static void main(String[] args) { -// String str = "1"; -// System.out.println(str); -// System.out.println(MD5ToLow16(str)); -// System.out.println(MD5ToLow32(str)); -// System.out.println(MD5ToUpp16(str)); -// System.out.println(MD5ToUpp32(str)); - String ttt = "sportsCe7vS3j1ziPHwfDDffJ3ivX34Z1cb2S1133687017471620710415600000004www.sportstatus.comzhU33255"; - System.out.println(md5(ttt)); - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/NewStringUtils.java b/wjcy-common/src/main/java/me/zhengjie/utils/NewStringUtils.java deleted file mode 100644 index 2ce685e..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/NewStringUtils.java +++ /dev/null @@ -1,646 +0,0 @@ -package me.zhengjie.utils; - -import org.springframework.util.AntPathMatcher; - -import java.util.*; - -/** - * 字符串工具类 - * - * @author ruoyi - */ -public class NewStringUtils extends org.apache.commons.lang3.StringUtils -{ - /** 空字符串 */ - private static final String NULLSTR = ""; - - /** 下划线 */ - private static final char SEPARATOR = '_'; - - /** 星号 */ - private static final char ASTERISK = '*'; - - /** - * 获取参数不为空值 - * - * @param value defaultValue 要判断的value - * @return value 返回值 - */ - public static T nvl(T value, T defaultValue) - { - return value != null ? value : defaultValue; - } - - /** - * * 判断一个Collection是否为空, 包含List,Set,Queue - * - * @param coll 要判断的Collection - * @return true:为空 false:非空 - */ - public static boolean isEmpty(Collection coll) - { - return isNull(coll) || coll.isEmpty(); - } - - /** - * * 判断一个Collection是否非空,包含List,Set,Queue - * - * @param coll 要判断的Collection - * @return true:非空 false:空 - */ - public static boolean isNotEmpty(Collection coll) - { - return !isEmpty(coll); - } - - /** - * * 判断一个对象数组是否为空 - * - * @param objects 要判断的对象数组 - ** @return true:为空 false:非空 - */ - public static boolean isEmpty(Object[] objects) - { - return isNull(objects) || (objects.length == 0); - } - - /** - * * 判断一个对象数组是否非空 - * - * @param objects 要判断的对象数组 - * @return true:非空 false:空 - */ - public static boolean isNotEmpty(Object[] objects) - { - return !isEmpty(objects); - } - - /** - * * 判断一个Map是否为空 - * - * @param map 要判断的Map - * @return true:为空 false:非空 - */ - public static boolean isEmpty(Map map) - { - return isNull(map) || map.isEmpty(); - } - - /** - * * 判断一个Map是否为空 - * - * @param map 要判断的Map - * @return true:非空 false:空 - */ - public static boolean isNotEmpty(Map map) - { - return !isEmpty(map); - } - - /** - * * 判断一个字符串是否为空串 - * - * @param str String - * @return true:为空 false:非空 - */ - public static boolean isEmpty(String str) - { - return isNull(str) || NULLSTR.equals(str.trim()); - } - - /** - * * 判断一个字符串是否为非空串 - * - * @param str String - * @return true:非空串 false:空串 - */ - public static boolean isNotEmpty(String str) - { - return !isEmpty(str); - } - - /** - * * 判断一个对象是否为空 - * - * @param object Object - * @return true:为空 false:非空 - */ - public static boolean isNull(Object object) - { - return object == null; - } - - /** - * * 判断一个对象是否非空 - * - * @param object Object - * @return true:非空 false:空 - */ - public static boolean isNotNull(Object object) - { - return !isNull(object); - } - - /** - * * 判断一个对象是否是数组类型(Java基本型别的数组) - * - * @param object 对象 - * @return true:是数组 false:不是数组 - */ - public static boolean isArray(Object object) - { - return isNotNull(object) && object.getClass().isArray(); - } - - /** - * 去空格 - */ - public static String trim(String str) - { - return (str == null ? "" : str.trim()); - } - - /** - * 替换指定字符串的指定区间内字符为"*" - * - * @param str 字符串 - * @param startInclude 开始位置(包含) - * @param endExclude 结束位置(不包含) - * @return 替换后的字符串 - */ - public static String hide(CharSequence str, int startInclude, int endExclude) - { - if (isEmpty(str)) - { - return NULLSTR; - } - final int strLength = str.length(); - if (startInclude > strLength) - { - return NULLSTR; - } - if (endExclude > strLength) - { - endExclude = strLength; - } - if (startInclude > endExclude) - { - // 如果起始位置大于结束位置,不替换 - return NULLSTR; - } - final char[] chars = new char[strLength]; - for (int i = 0; i < strLength; i++) - { - if (i >= startInclude && i < endExclude) - { - chars[i] = ASTERISK; - } - else - { - chars[i] = str.charAt(i); - } - } - return new String(chars); - } - - /** - * 截取字符串 - * - * @param str 字符串 - * @param start 开始 - * @return 结果 - */ - public static String substring(final String str, int start) - { - if (str == null) - { - return NULLSTR; - } - - if (start < 0) - { - start = str.length() + start; - } - - if (start < 0) - { - start = 0; - } - if (start > str.length()) - { - return NULLSTR; - } - - return str.substring(start); - } - - /** - * 截取字符串 - * - * @param str 字符串 - * @param start 开始 - * @param end 结束 - * @return 结果 - */ - public static String substring(final String str, int start, int end) - { - if (str == null) - { - return NULLSTR; - } - - if (end < 0) - { - end = str.length() + end; - } - if (start < 0) - { - start = str.length() + start; - } - - if (end > str.length()) - { - end = str.length(); - } - - if (start > end) - { - return NULLSTR; - } - - if (start < 0) - { - start = 0; - } - if (end < 0) - { - end = 0; - } - - return str.substring(start, end); - } - - /** - * 判断是否为空,并且不是空白字符 - * - * @param str 要判断的value - * @return 结果 - */ - public static boolean hasText(String str) - { - return (str != null && !str.isEmpty() && containsText(str)); - } - - private static boolean containsText(CharSequence str) - { - int strLen = str.length(); - for (int i = 0; i < strLen; i++) - { - if (!Character.isWhitespace(str.charAt(i))) - { - return true; - } - } - return false; - } - - - /** - * 字符串转set - * - * @param str 字符串 - * @param sep 分隔符 - * @return set集合 - */ - public static final Set str2Set(String str, String sep) - { - return new HashSet(str2List(str, sep, true, false)); - } - - /** - * 字符串转list - * - * @param str 字符串 - * @param sep 分隔符 - * @param filterBlank 过滤纯空白 - * @param trim 去掉首尾空白 - * @return list集合 - */ - public static final List str2List(String str, String sep, boolean filterBlank, boolean trim) - { - List list = new ArrayList(); - if (NewStringUtils.isEmpty(str)) - { - return list; - } - - // 过滤空白字符串 - if (filterBlank && NewStringUtils.isBlank(str)) - { - return list; - } - String[] split = str.split(sep); - for (String string : split) - { - if (filterBlank && NewStringUtils.isBlank(string)) - { - continue; - } - if (trim) - { - string = string.trim(); - } - list.add(string); - } - - return list; - } - - /** - * 判断给定的collection列表中是否包含数组array 判断给定的数组array中是否包含给定的元素value - * - * @param collection 给定的集合 - * @param array 给定的数组 - * @return boolean 结果 - */ - public static boolean containsAny(Collection collection, String... array) - { - if (isEmpty(collection) || isEmpty(array)) - { - return false; - } - else - { - for (String str : array) - { - if (collection.contains(str)) - { - return true; - } - } - return false; - } - } - - /** - * 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写 - * - * @param cs 指定字符串 - * @param searchCharSequences 需要检查的字符串数组 - * @return 是否包含任意一个字符串 - */ - public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences) - { - if (isEmpty(cs) || isEmpty(searchCharSequences)) - { - return false; - } - for (CharSequence testStr : searchCharSequences) - { - if (containsIgnoreCase(cs, testStr)) - { - return true; - } - } - return false; - } - - /** - * 驼峰转下划线命名 - */ - public static String toUnderScoreCase(String str) - { - if (str == null) - { - return null; - } - StringBuilder sb = new StringBuilder(); - // 前置字符是否大写 - boolean preCharIsUpperCase = true; - // 当前字符是否大写 - boolean curreCharIsUpperCase = true; - // 下一字符是否大写 - boolean nexteCharIsUpperCase = true; - for (int i = 0; i < str.length(); i++) - { - char c = str.charAt(i); - if (i > 0) - { - preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1)); - } - else - { - preCharIsUpperCase = false; - } - - curreCharIsUpperCase = Character.isUpperCase(c); - - if (i < (str.length() - 1)) - { - nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1)); - } - - if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase) - { - sb.append(SEPARATOR); - } - else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase) - { - sb.append(SEPARATOR); - } - sb.append(Character.toLowerCase(c)); - } - - return sb.toString(); - } - - /** - * 是否包含字符串 - * - * @param str 验证字符串 - * @param strs 字符串组 - * @return 包含返回true - */ - public static boolean inStringIgnoreCase(String str, String... strs) - { - if (str != null && strs != null) - { - for (String s : strs) - { - if (str.equalsIgnoreCase(trim(s))) - { - return true; - } - } - } - return false; - } - - /** - * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld - * - * @param name 转换前的下划线大写方式命名的字符串 - * @return 转换后的驼峰式命名的字符串 - */ - public static String convertToCamelCase(String name) - { - StringBuilder result = new StringBuilder(); - // 快速检查 - if (name == null || name.isEmpty()) - { - // 没必要转换 - return ""; - } - else if (!name.contains("_")) - { - // 不含下划线,仅将首字母大写 - return name.substring(0, 1).toUpperCase() + name.substring(1); - } - // 用下划线将原始字符串分割 - String[] camels = name.split("_"); - for (String camel : camels) - { - // 跳过原始字符串中开头、结尾的下换线或双重下划线 - if (camel.isEmpty()) - { - continue; - } - // 首字母大写 - result.append(camel.substring(0, 1).toUpperCase()); - result.append(camel.substring(1).toLowerCase()); - } - return result.toString(); - } - - /** - * 驼峰式命名法 - * 例如:user_name->userName - */ - public static String toCamelCase(String s) - { - if (s == null) - { - return null; - } - if (s.indexOf(SEPARATOR) == -1) - { - return s; - } - s = s.toLowerCase(); - StringBuilder sb = new StringBuilder(s.length()); - boolean upperCase = false; - for (int i = 0; i < s.length(); i++) - { - char c = s.charAt(i); - - if (c == SEPARATOR) - { - upperCase = true; - } - else if (upperCase) - { - sb.append(Character.toUpperCase(c)); - upperCase = false; - } - else - { - sb.append(c); - } - } - return sb.toString(); - } - - /** - * 查找指定字符串是否匹配指定字符串列表中的任意一个字符串 - * - * @param str 指定字符串 - * @param strs 需要检查的字符串数组 - * @return 是否匹配 - */ - public static boolean matches(String str, List strs) - { - if (isEmpty(str) || isEmpty(strs)) - { - return false; - } - for (String pattern : strs) - { - if (isMatch(pattern, str)) - { - return true; - } - } - return false; - } - - /** - * 判断url是否与规则配置: - * ? 表示单个字符; - * * 表示一层路径内的任意字符串,不可跨层级; - * ** 表示任意层路径; - * - * @param pattern 匹配规则 - * @param url 需要匹配的url - * @return - */ - public static boolean isMatch(String pattern, String url) - { - AntPathMatcher matcher = new AntPathMatcher(); - return matcher.match(pattern, url); - } - - @SuppressWarnings("unchecked") - public static T cast(Object obj) - { - return (T) obj; - } - - /** - * 数字左边补齐0,使之达到指定长度。注意,如果数字转换为字符串后,长度大于size,则只保留 最后size个字符。 - * - * @param num 数字对象 - * @param size 字符串指定长度 - * @return 返回数字的字符串格式,该字符串为指定长度。 - */ - public static final String padl(final Number num, final int size) - { - return padl(num.toString(), size, '0'); - } - - /** - * 字符串左补齐。如果原始字符串s长度大于size,则只保留最后size个字符。 - * - * @param s 原始字符串 - * @param size 字符串指定长度 - * @param c 用于补齐的字符 - * @return 返回指定长度的字符串,由原字符串左补齐或截取得到。 - */ - public static final String padl(final String s, final int size, final char c) - { - final StringBuilder sb = new StringBuilder(size); - if (s != null) - { - final int len = s.length(); - if (s.length() <= size) - { - for (int i = size - len; i > 0; i--) - { - sb.append(c); - } - sb.append(s); - } - else - { - return s.substring(len - size, len); - } - } - else - { - for (int i = size; i > 0; i--) - { - sb.append(c); - } - } - return sb.toString(); - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/OrderGetIndexUtil.java b/wjcy-common/src/main/java/me/zhengjie/utils/OrderGetIndexUtil.java deleted file mode 100644 index 8bce737..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/OrderGetIndexUtil.java +++ /dev/null @@ -1,63 +0,0 @@ -package me.zhengjie.utils; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicInteger; - -/** - *

- * --顺序访问 - * 第几次访问 % 钱包池中有几个排序钱包 得到 当前应该取钱包池中钱包的索引 实现顺序访问。 - *

- * - * @author: rch - * @date: 2021-09-25 - */ -public class OrderGetIndexUtil { - - private static Map concurrentHashMap = new ConcurrentHashMap<>(16); - - /** - * @param merId 商家id - * @return 指定钱包池中当前该取钱包id 下标索引 - */ - public static int getIncrement(Long merId, Integer walletType, Integer passType) { - - String keyStr = merId + "-" + walletType + "-" + passType; - AtomicInteger atomicInteger = new AtomicInteger(0); - - Integer current; - int next; - do { - current = concurrentHashMap.get(keyStr); - current = current != null ? current : 0; - atomicInteger = new AtomicInteger(current); - next = current >= 2147483647 ? 0 : current+1; - - }while (!atomicInteger.compareAndSet(current, next)); - - concurrentHashMap.put(keyStr, next); - System.out.println("------------第几次访问:次数next="+next); - return next; - } - - public static void main(String[] args) { - for (int i = 0; i < 10; i++) { - if (i % 5 == 0) { - System.out.println("0==" + getIncrement(1L, 1, 1)); - } else if (i % 5 == 1) { - System.out.println("1==" + getIncrement(1L, 2, 1)); - } else if (i % 5 == 2) { - System.out.println("2==" + getIncrement(2L, 1, 1)); - } else if (i % 5 == 3) { - System.out.println("2==" + getIncrement(2L, 2,1)); - } else if (i % 5 == 4) { - System.out.println("3==" + getIncrement(2L, 3,1)); - } else { - System.out.println("!2=" + getIncrement(11L, 3, 1)); - } - } - - System.out.println("2==" + getIncrement(2L, 1, 1)); - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/PageUtil.java b/wjcy-common/src/main/java/me/zhengjie/utils/PageUtil.java deleted file mode 100644 index 44db68d..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/PageUtil.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.utils; - -import org.springframework.data.domain.Page; -import java.util.*; - -/** - * 分页工具 - * @author Zheng Jie - * @date 2018-12-10 - */ -public class PageUtil extends cn.hutool.core.util.PageUtil { - - /** - * List 分页 - */ - public static List toPage(int page, int size , List list) { - int fromIndex = page * size; - int toIndex = page * size + size; - if(fromIndex > list.size()){ - return new ArrayList(); - } else if(toIndex >= list.size()) { - return list.subList(fromIndex,list.size()); - } else { - return list.subList(fromIndex,toIndex); - } - } - - /** - * Page 数据处理,预防redis反序列化报错 - */ - public static Map toPage(Page page) { - Map map = new LinkedHashMap<>(2); - map.put("content",page.getContent()); - map.put("totalElements",page.getTotalElements()); - return map; - } - - /** - * 自定义分页 - */ - public static Map toPage(Object object, Object totalElements) { - Map map = new LinkedHashMap<>(2); - map.put("content",object); - map.put("totalElements",totalElements); - return map; - } - -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/PageUtils.java b/wjcy-common/src/main/java/me/zhengjie/utils/PageUtils.java deleted file mode 100644 index cbf8730..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/PageUtils.java +++ /dev/null @@ -1,55 +0,0 @@ -package me.zhengjie.utils; - -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import lombok.Data; - -import java.util.Collections; -import java.util.List; -/** - *

- * 分页查询工具类 - *

- * - * @Author xx - * @Date 2021/7/19 - **/ -@Data -public class PageUtils { - /** - * 总记录数 - */ - private Long total; - /** - * 查询结果 - */ - private List list; - - public PageUtils() { - - } - - public PageUtils(Long total, List list) { - this.total = total; - this.list = list; - } - - public PageUtils(Page page) { - this.total = page.getTotal(); - this.list = page.getRecords(); - } - - public Long getTotal() { - if (ObjectUtil.isNull(total)|| EmptyAttributeFiler.isEmpty(list)) { - return 0L; - } - return total; - } - - public List getList() { - if (EmptyAttributeFiler.isEmpty(list)) { - return Collections.emptyList(); - } - return list; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/PopularizeUtil.java b/wjcy-common/src/main/java/me/zhengjie/utils/PopularizeUtil.java deleted file mode 100644 index ebb422e..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/PopularizeUtil.java +++ /dev/null @@ -1,49 +0,0 @@ -package me.zhengjie.utils; - -import cn.hutool.core.lang.UUID; - - -/** - * 推广码生成 工具类 - * - * @author: e - * @since: 2022/01/19 - */ -public class PopularizeUtil { - - public static String[] chars = new String[] { "a", "b", "c", "d", "e", "f", - "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", - "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", - "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", - "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", - "W", "X", "Y", "Z" }; - - /** - * 创建推广码 - * @return - */ - public static String createPromoCode(){ - return generateShortUuid().toUpperCase(); - //return RandomUtil.randomString(8).toUpperCase(); - } - - - public static String generateShortUuid() { - StringBuffer shortBuffer = new StringBuffer(); - String uuid = UUID.randomUUID().toString().replace("-", ""); - for (int i = 0; i < 8; i++) { - String str = uuid.substring(i * 4, i * 4 + 4); - int x = Integer.parseInt(str, 16); - shortBuffer.append(chars[x % 0x3E]); - } - return shortBuffer.toString(); - - } - - public static void main(String[] args) { - - - } - - -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/PropertiesUtil.java b/wjcy-common/src/main/java/me/zhengjie/utils/PropertiesUtil.java deleted file mode 100644 index 3dab51b..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/PropertiesUtil.java +++ /dev/null @@ -1,62 +0,0 @@ -package me.zhengjie.utils; - -import cn.hutool.core.util.ObjectUtil; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.config.SystemConfig; - -import java.io.*; -import java.util.Properties; - -/* - * - * @Description 读取多语言文本工具类 - * @Date 2021/12/16 - * @Author zeng - */ -@Slf4j -public class PropertiesUtil { - - public static String getByCode(Integer code, String language) { - FileInputStream fis = null; - InputStreamReader isr = null; - BufferedReader br = null; - try { - File file = new File(SystemConfig.LANGUAGE_PATH); - if (file.exists()) { - for (File listFile : file.listFiles()) { - if (listFile.getName().contains(language + ".properties")) { - Properties properties = new Properties(); - fis = new FileInputStream(listFile); - isr = new InputStreamReader(fis, "UTF-8"); - BufferedReader bf = new BufferedReader(isr); - properties.load(bf); - return properties.getProperty(code.toString()); - } - } - } - - } catch (FileNotFoundException e) { - log.error("文件不存在=========================="); - } catch (IOException e) { - log.error("文件读取异常=========================="); - }finally { - try { - if (ObjectUtil.isNotNull(br)) { - br.close(); - } - if (ObjectUtil.isNotNull(isr)) { - isr.close(); - } - if (ObjectUtil.isNotNull(fis)){ - fis.close(); - } - } catch (IOException e) { - e.printStackTrace(); - } - - } - log.error("=============读取多语言文本失败================== code:{} language:{}", code, language); - return null; - } - -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/QueryHelp.java b/wjcy-common/src/main/java/me/zhengjie/utils/QueryHelp.java deleted file mode 100644 index 69cb5e2..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/QueryHelp.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.utils; - -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.collection.CollectionUtil; -import cn.hutool.core.util.ObjectUtil; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.annotation.DataPermission; -import me.zhengjie.annotation.Query; -import javax.persistence.criteria.*; -import java.lang.reflect.Field; -import java.util.*; - -/** - * @author Zheng Jie - * @date 2019-6-4 14:59:48 - */ -@Slf4j -@SuppressWarnings({"unchecked","all"}) -public class QueryHelp { - - public static Predicate getPredicate(Root root, Q query, CriteriaBuilder cb) { - List list = new ArrayList<>(); - if(query == null){ - return cb.and(list.toArray(new Predicate[0])); - } - // 数据权限验证 - DataPermission permission = query.getClass().getAnnotation(DataPermission.class); - if(permission != null){ - // 获取数据权限 - List dataScopes = SecurityUtils.getCurrentUserDataScope(); - if(CollectionUtil.isNotEmpty(dataScopes)){ - if(StringUtils.isNotBlank(permission.joinName()) && StringUtils.isNotBlank(permission.fieldName())) { - Join join = root.join(permission.joinName(), JoinType.LEFT); - list.add(getExpression(permission.fieldName(),join, root).in(dataScopes)); - } else if (StringUtils.isBlank(permission.joinName()) && StringUtils.isNotBlank(permission.fieldName())) { - list.add(getExpression(permission.fieldName(),null, root).in(dataScopes)); - } - } - } - try { - List fields = getAllFields(query.getClass(), new ArrayList<>()); - for (Field field : fields) { - boolean accessible = field.isAccessible(); - // 设置对象的访问权限,保证对private的属性的访 - field.setAccessible(true); - Query q = field.getAnnotation(Query.class); - if (q != null) { - String propName = q.propName(); - String joinName = q.joinName(); - String blurry = q.blurry(); - String attributeName = isBlank(propName) ? field.getName() : propName; - Class fieldType = field.getType(); - Object val = field.get(query); - if (ObjectUtil.isNull(val) || "".equals(val)) { - continue; - } - Join join = null; - // 模糊多字段 - if (ObjectUtil.isNotEmpty(blurry)) { - String[] blurrys = blurry.split(","); - List orPredicate = new ArrayList<>(); - for (String s : blurrys) { - orPredicate.add(cb.like(root.get(s) - .as(String.class), "%" + val.toString() + "%")); - } - Predicate[] p = new Predicate[orPredicate.size()]; - list.add(cb.or(orPredicate.toArray(p))); - continue; - } - if (ObjectUtil.isNotEmpty(joinName)) { - String[] joinNames = joinName.split(">"); - for (String name : joinNames) { - switch (q.join()) { - case LEFT: - if(ObjectUtil.isNotNull(join) && ObjectUtil.isNotNull(val)){ - join = join.join(name, JoinType.LEFT); - } else { - join = root.join(name, JoinType.LEFT); - } - break; - case RIGHT: - if(ObjectUtil.isNotNull(join) && ObjectUtil.isNotNull(val)){ - join = join.join(name, JoinType.RIGHT); - } else { - join = root.join(name, JoinType.RIGHT); - } - break; - case INNER: - if(ObjectUtil.isNotNull(join) && ObjectUtil.isNotNull(val)){ - join = join.join(name, JoinType.INNER); - } else { - join = root.join(name, JoinType.INNER); - } - break; - default: break; - } - } - } - switch (q.type()) { - case EQUAL: - list.add(cb.equal(getExpression(attributeName,join,root) - .as((Class) fieldType),val)); - break; - case GREATER_THAN: - list.add(cb.greaterThanOrEqualTo(getExpression(attributeName,join,root) - .as((Class) fieldType), (Comparable) val)); - break; - case LESS_THAN: - list.add(cb.lessThanOrEqualTo(getExpression(attributeName,join,root) - .as((Class) fieldType), (Comparable) val)); - break; - case LESS_THAN_NQ: - list.add(cb.lessThan(getExpression(attributeName,join,root) - .as((Class) fieldType), (Comparable) val)); - break; - case INNER_LIKE: - list.add(cb.like(getExpression(attributeName,join,root) - .as(String.class), "%" + val.toString() + "%")); - break; - case LEFT_LIKE: - list.add(cb.like(getExpression(attributeName,join,root) - .as(String.class), "%" + val.toString())); - break; - case RIGHT_LIKE: - list.add(cb.like(getExpression(attributeName,join,root) - .as(String.class), val.toString() + "%")); - break; - case IN: - if (CollUtil.isNotEmpty((Collection)val)) { - list.add(getExpression(attributeName,join,root).in((Collection) val)); - } - break; - case NOT_IN: - if (CollUtil.isNotEmpty((Collection)val)) { - list.add(getExpression(attributeName,join,root).in((Collection) val).not()); - } - break; - case NOT_EQUAL: - list.add(cb.notEqual(getExpression(attributeName,join,root), val)); - break; - case NOT_NULL: - list.add(cb.isNotNull(getExpression(attributeName,join,root))); - break; - case IS_NULL: - list.add(cb.isNull(getExpression(attributeName,join,root))); - break; - case BETWEEN: - List between = new ArrayList<>((List)val); - list.add(cb.between(getExpression(attributeName, join, root).as((Class) between.get(0).getClass()), - (Comparable) between.get(0), (Comparable) between.get(1))); - break; - default: break; - } - } - field.setAccessible(accessible); - } - } catch (Exception e) { - log.error(e.getMessage(), e); - } - int size = list.size(); - return cb.and(list.toArray(new Predicate[size])); - } - - @SuppressWarnings("unchecked") - private static Expression getExpression(String attributeName, Join join, Root root) { - if (ObjectUtil.isNotEmpty(join)) { - return join.get(attributeName); - } else { - return root.get(attributeName); - } - } - - private static boolean isBlank(final CharSequence cs) { - int strLen; - if (cs == null || (strLen = cs.length()) == 0) { - return true; - } - for (int i = 0; i < strLen; i++) { - if (!Character.isWhitespace(cs.charAt(i))) { - return false; - } - } - return true; - } - - public static List getAllFields(Class clazz, List fields) { - if (clazz != null) { - fields.addAll(Arrays.asList(clazz.getDeclaredFields())); - getAllFields(clazz.getSuperclass(), fields); - } - return fields; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/RedisUtils.java b/wjcy-common/src/main/java/me/zhengjie/utils/RedisUtils.java deleted file mode 100644 index c633b81..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/RedisUtils.java +++ /dev/null @@ -1,903 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.utils; - -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.data.redis.connection.RedisConnection; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.core.*; -import org.springframework.data.redis.support.atomic.RedisAtomicLong; -import org.springframework.stereotype.Component; - -import java.util.*; -import java.util.concurrent.TimeUnit; - -/** - * @author / - */ -@Component -@SuppressWarnings({"unchecked", "all"}) -public class RedisUtils { - private static final Logger log = LoggerFactory.getLogger(RedisUtils.class); - private RedisTemplate redisTemplate; - @Value("${jwt.online-key}") - private String onlineKey; - - public static String LOGIN_FAIL_COUNT = "LOGIN_FAIL_COUNT:%s"; - public static String BLOCKED_ACCOUNT = "BLOCKED_ACCOUNT:%s"; - - public RedisUtils(RedisTemplate redisTemplate) { - this.redisTemplate = redisTemplate; - } - - /** - * 指定缓存失效时间 - * - * @param key 键 - * @param time 时间(秒) - */ - public boolean expire(String key, long time) { - try { - if (time > 0) { - redisTemplate.expire(key, time, TimeUnit.SECONDS); - } - } catch (Exception e) { - log.error(e.getMessage(), e); - return false; - } - return true; - } - - /** - * 指定缓存失效时间 - * - * @param key 键 - * @param time 时间(秒) - * @param timeUnit 单位 - */ - public boolean expire(String key, long time, TimeUnit timeUnit) { - try { - if (time > 0) { - redisTemplate.expire(key, time, timeUnit); - } - } catch (Exception e) { - log.error(e.getMessage(), e); - return false; - } - return true; - } - - /** - * 根据 key 获取过期时间 - * - * @param key 键 不能为null - * @return 时间(秒) 返回0代表为永久有效 - */ - public long getExpire(Object key) { - return redisTemplate.getExpire(key, TimeUnit.SECONDS); - } - - /** - * 查找匹配key - * - * @param pattern key - * @return / - */ - public List scan(String pattern) { - ScanOptions options = ScanOptions.scanOptions().match(pattern).build(); - RedisConnectionFactory factory = redisTemplate.getConnectionFactory(); - RedisConnection rc = Objects.requireNonNull(factory).getConnection(); - Cursor cursor = rc.scan(options); - List result = new ArrayList<>(); - while (cursor.hasNext()) { - result.add(new String(cursor.next())); - } - try { - RedisConnectionUtils.releaseConnection(rc, factory); - } catch (Exception e) { - log.error(e.getMessage(), e); - } - return result; - } - - /** - * 分页查询 key - * - * @param patternKey key - * @param page 页码 - * @param size 每页数目 - * @return / - */ - public List findKeysForPage(String patternKey, int page, int size) { - ScanOptions options = ScanOptions.scanOptions().match(patternKey).build(); - RedisConnectionFactory factory = redisTemplate.getConnectionFactory(); - RedisConnection rc = Objects.requireNonNull(factory).getConnection(); - Cursor cursor = rc.scan(options); - List result = new ArrayList<>(size); - int tmpIndex = 0; - int fromIndex = page * size; - int toIndex = page * size + size; - while (cursor.hasNext()) { - if (tmpIndex >= fromIndex && tmpIndex < toIndex) { - result.add(new String(cursor.next())); - tmpIndex++; - continue; - } - // 获取到满足条件的数据后,就可以退出了 - if (tmpIndex >= toIndex) { - break; - } - tmpIndex++; - cursor.next(); - } - try { - RedisConnectionUtils.releaseConnection(rc, factory); - } catch (Exception e) { - log.error(e.getMessage(), e); - } - return result; - } - - /** - * 判断key是否存在 - * - * @param key 键 - * @return true 存在 false不存在 - */ - public boolean hasKey(String key) { - try { - return redisTemplate.hasKey(key); - } catch (Exception e) { - log.error(e.getMessage(), e); - return false; - } - } - - /** - * 删除缓存 - * - * @param key 可以传一个值 或多个 - */ - public void del(String... keys) { - if (keys != null && keys.length > 0) { - if (keys.length == 1) { - boolean result = redisTemplate.delete(keys[0]); - log.debug("--------------------------------------------"); - log.debug(new StringBuilder("删除缓存:").append(keys[0]).append(",结果:").append(result).toString()); - log.debug("--------------------------------------------"); - } else { - Set keySet = new HashSet<>(); - for (String key : keys) { - keySet.addAll(redisTemplate.keys(key)); - } - long count = redisTemplate.delete(keySet); - log.debug("--------------------------------------------"); - log.debug("成功删除缓存:" + keySet.toString()); - log.debug("缓存删除数量:" + count + "个"); - log.debug("--------------------------------------------"); - } - } - } - - /** - * setIfAbsent 如果key 不存在则 set value 并返回true - * 否则返回false; - * @param key - * @param value - * @return - */ - public Boolean setIfAbsent(String key, String value) { - - try { - return redisTemplate.opsForValue().setIfAbsent(key, value); - } catch (Exception e) { - log.error(e.getMessage(), e); - return false; - } - } - - // ============================String============================= - - /** - * 普通缓存获取 - * - * @param key 键 - * @return 值 - */ - public Object get(String key) { - return key == null ? null : redisTemplate.opsForValue().get(key); - } - - /** - * 批量获取 - * - * @param keys - * @return - */ - public List multiGet(List keys) { - Object obj = redisTemplate.opsForValue().multiGet(Collections.singleton(keys)); - return null; - } - - /** - * 普通缓存放入 - * - * @param key 键 - * @param value 值 - * @return true成功 false失败 - */ - public boolean set(String key, Object value) { - try { - redisTemplate.opsForValue().set(key, value); - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - return false; - } - } - - /** - * 普通缓存放入并设置时间 - * - * @param key 键 - * @param value 值 - * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 - * @return true成功 false 失败 - */ - public boolean set(String key, Object value, long time) { - try { - if (time > 0) { - redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); - } else { - set(key, value); - } - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - return false; - } - } - - /** - * 普通缓存放入并设置时间 - * - * @param key 键 - * @param value 值 - * @param time 时间 - * @param timeUnit 类型 - * @return true成功 false 失败 - */ - public boolean set(String key, Object value, long time, TimeUnit timeUnit) { - try { - if (time > 0) { - redisTemplate.opsForValue().set(key, value, time, timeUnit); - } else { - set(key, value); - } - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - return false; - } - } - - // ================================Map================================= - - /** - * HashGet - * - * @param key 键 不能为null - * @param item 项 不能为null - * @return 值 - */ - public Object hget(String key, String item) { - return redisTemplate.opsForHash().get(key, item); - } - - /** - * 获取hashKey对应的所有键值 - * - * @param key 键 - * @return 对应的多个键值 - */ - public Map hmget(String key) { - return redisTemplate.opsForHash().entries(key); - - } - - /** - * HashSet - * - * @param key 键 - * @param map 对应多个键值 - * @return true 成功 false 失败 - */ - public boolean hmset(String key, Map map) { - try { - redisTemplate.opsForHash().putAll(key, map); - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - return false; - } - } - - /** - * HashSet 并设置时间 - * - * @param key 键 - * @param map 对应多个键值 - * @param time 时间(秒) - * @return true成功 false失败 - */ - public boolean hmset(String key, Map map, long time) { - try { - redisTemplate.opsForHash().putAll(key, map); - if (time > 0) { - expire(key, time); - } - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - return false; - } - } - - /** - * 向一张hash表中放入数据,如果不存在将创建 - * - * @param key 键 - * @param item 项 - * @param value 值 - * @return true 成功 false失败 - */ - public boolean hset(String key, String item, Object value) { - try { - redisTemplate.opsForHash().put(key, item, value); - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - return false; - } - } - - /** - * 向一张hash表中放入数据,如果不存在将创建 - * - * @param key 键 - * @param item 项 - * @param value 值 - * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 - * @return true 成功 false失败 - */ - public boolean hset(String key, String item, Object value, long time) { - try { - redisTemplate.opsForHash().put(key, item, value); - if (time > 0) { - expire(key, time); - } - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - return false; - } - } - - /** - * 删除hash表中的值 - * - * @param key 键 不能为null - * @param item 项 可以使多个 不能为null - */ - public void hdel(String key, Object... item) { - redisTemplate.opsForHash().delete(key, item); - } - - /** - * 判断hash表中是否有该项的值 - * - * @param key 键 不能为null - * @param item 项 不能为null - * @return true 存在 false不存在 - */ - public boolean hHasKey(String key, String item) { - return redisTemplate.opsForHash().hasKey(key, item); - } - - /** - * hash递增 如果不存在,就会创建一个 并把新增后的值返回 - * - * @param key 键 - * @param item 项 - * @param by 要增加几(大于0) - * @return - */ - public double hincr(String key, String item, double by) { - return redisTemplate.opsForHash().increment(key, item, by); - } - - /** - * 自增 - * @param key - * @param liveTime 单位秒 - * @return - */ - public Long incrAndExpire(String key, long liveTime) { - RedisAtomicLong entityIdCounter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory()); - Long increment = entityIdCounter.getAndIncrement(); - - if ((null == increment || increment.longValue() == 0) && liveTime > 0) {//初始设置过期时间 - entityIdCounter.expire(liveTime, TimeUnit.SECONDS); - } - - return Long.valueOf(StrUtil.toString(get(key))); - } - - /** - * hash递减 - * - * @param key 键 - * @param item 项 - * @param by 要减少记(小于0) - * @return - */ - public double hdecr(String key, String item, double by) { - return redisTemplate.opsForHash().increment(key, item, -by); - } - - // ============================set============================= - - /** - * 根据key获取Set中的所有值 - * - * @param key 键 - * @return - */ - public Set sGet(String key) { - try { - return redisTemplate.opsForSet().members(key); - } catch (Exception e) { - log.error(e.getMessage(), e); - return null; - } - } - - /** - * 随机返回并删除名称为key的set中的一个元素 - * - * @param key 键 - * @return - */ - public ZSetOperations.TypedTuple randomObj(String key) { - try { - Long xxx = redisTemplate.opsForZSet().size(key); - if (ObjectUtil.isEmpty(xxx)) { - return null; - } - Set> allSet = redisTemplate.opsForZSet().rangeWithScores(key,0,-1); - // 随机数 - int leng = allSet.size(); - Random r = new Random(); - Integer arrayindex = r.nextInt(leng); - List> results = new ArrayList<>(allSet); - ZSetOperations.TypedTuple randomObj = results.get(arrayindex); - return randomObj; - } catch (Exception e) { - log.error(e.getMessage(), e); - return null; - } - } - - /** - * 根据value从一个set中查询,是否存在 - * - * @param key 键 - * @param value 值 - * @return true 存在 false不存在 - */ - public boolean sHasKey(String key, Object value) { - try { - return redisTemplate.opsForSet().isMember(key, value); - } catch (Exception e) { - log.error(e.getMessage(), e); - return false; - } - } - - /** - * 将数据放入set缓存 - * - * @param key 键 - * @param values 值 可以是多个 - * @return 成功个数 - */ - public long sSet(String key, Object... values) { - try { - return redisTemplate.opsForSet().add(key, values); - } catch (Exception e) { - log.error(e.getMessage(), e); - return 0; - } - } - - /** - * 将set数据放入缓存 - * - * @param key 键 - * @param time 时间(秒) - * @param values 值 可以是多个 - * @return 成功个数 - */ - public long sSetAndTime(String key, long time, Object... values) { - try { - Long count = redisTemplate.opsForSet().add(key, values); - if (time > 0) { - expire(key, time); - } - return count; - } catch (Exception e) { - log.error(e.getMessage(), e); - return 0; - } - } - - /** - * 获取set缓存的长度 - * - * @param key 键 - * @return - */ - public long sGetSetSize(String key) { - try { - return redisTemplate.opsForSet().size(key); - } catch (Exception e) { - log.error(e.getMessage(), e); - return 0; - } - } - - /** - * 移除值为value的 - * - * @param key 键 - * @param values 值 可以是多个 - * @return 移除的个数 - */ - public long setRemove(String key, Object... values) { - try { - Long count = redisTemplate.opsForSet().remove(key, values); - return count; - } catch (Exception e) { - log.error(e.getMessage(), e); - return 0; - } - } - - // ===============================list================================= - - /** - * 获取list缓存的内容 - * - * @param key 键 - * @param start 开始 - * @param end 结束 0 到 -1代表所有值 - * @return - */ - public List lGet(String key, long start, long end) { - try { - return redisTemplate.opsForList().range(key, start, end); - } catch (Exception e) { - log.error(e.getMessage(), e); - return null; - } - } - - /** - * rpop - * - * @param key 键 - * @return - */ - public Object rPop(String key) { - try { - return redisTemplate.opsForList().rightPop(key); - } catch (Exception e) { - log.error(e.getMessage(), e); - return null; - } - } - - /** - * rpop - * - * @param key 键 - * @return - */ - public Object lPop(String key) { - try { - return redisTemplate.opsForList().leftPop(key); - } catch (Exception e) { - log.error(e.getMessage(), e); - return null; - } - } - - /** - * rightPush - * - * @param key 键 - * @return - */ - public Object rPush(String key, Object object) { - try { - return redisTemplate.opsForList().rightPush(key, object); - } catch (Exception e) { - log.error(e.getMessage(), e); - return null; - } - } - - /** - * lPush - * - * @param key 键 - * @return - */ - public Object lPush(String key, Object object) { - try { - return redisTemplate.opsForList().leftPush(key, object); - } catch (Exception e) { - log.error(e.getMessage(), e); - return null; - } - } - - /** - * 获取list缓存的长度 - * - * @param key 键 - * @return - */ - public long lGetListSize(String key) { - try { - return redisTemplate.opsForList().size(key); - } catch (Exception e) { - log.error(e.getMessage(), e); - return 0; - } - } - - /** - * 通过索引 获取list中的值 - * - * @param key 键 - * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推 - * @return - */ - public Object lGetIndex(String key, long index) { - try { - return redisTemplate.opsForList().index(key, index); - } catch (Exception e) { - log.error(e.getMessage(), e); - return null; - } - } - - /** - * 将list放入缓存 - * - * @param key 键 - * @param value 值 - * @return - */ - public boolean lSet(String key, Object value) { - try { - redisTemplate.opsForList().leftPush(key, value); - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - return false; - } - } - - /** - * 将list放入缓存 - * - * @param key 键 - * @param value 值 - * @param time 时间(秒) - * @return - */ - public boolean lSet(String key, Object value, long time) { - try { - redisTemplate.opsForList().rightPush(key, value); - if (time > 0) { - expire(key, time); - } - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - return false; - } - } - - /** - * 将String放入缓存 - * - * @param key 键 - * @param value 值 - * @param time 时间(秒) - * @return - */ - public boolean put(String key, Object value, long time) { - try { - redisTemplate.opsForValue().set(key, value); - if (time > 0) { - expire(key, time); - } - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - return false; - } - } - - /** - * 将list放入缓存 - * - * @param key 键 - * @param value 值 - * @return - */ - public boolean lSet(String key, List value) { - try { - redisTemplate.opsForList().rightPushAll(key, value); - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - return false; - } - } - - /** - * 将list放入缓存 - * - * @param key 键 - * @param value 值 - * @param time 时间(秒) - * @return - */ - public boolean lSet(String key, List value, long time) { - try { - redisTemplate.opsForList().rightPushAll(key, value); - if (time > 0) { - expire(key, time); - } - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - return false; - } - } - - /** - * 根据索引修改list中的某条数据 - * - * @param key 键 - * @param index 索引 - * @param value 值 - * @return / - */ - public boolean lUpdateIndex(String key, long index, Object value) { - try { - redisTemplate.opsForList().set(key, index, value); - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - return false; - } - } - - /** - * 移除N个值为value - * - * @param key 键 - * @param count 移除多少个 - * @param value 值 - * @return 移除的个数 - */ - public long lRemove(String key, long count, Object value) { - try { - return redisTemplate.opsForList().remove(key, count, value); - } catch (Exception e) { - log.error(e.getMessage(), e); - return 0; - } - } - - /** - * @param prefix 前缀 - * @param ids id - */ - public void delByKeys(String prefix, Set ids) { - Set keys = new HashSet<>(); - for (Long id : ids) { - keys.addAll(redisTemplate.keys(new StringBuffer(prefix).append(id).toString())); - } - long count = redisTemplate.delete(keys); - // 此处提示可自行删除 - log.debug("--------------------------------------------"); - log.debug("成功删除缓存:" + keys.toString()); - log.debug("缓存删除数量:" + count + "个"); - log.debug("--------------------------------------------"); - } - - // ===============================setsort================================= - - /** - * 添加元素到变量中同时指定元素的分值。 - * @param key - * @param value - * @param score - * @return - */ - public boolean zSortAdd(String key, Object value, double score) { - try { - redisTemplate.opsForZSet().add(key, value, score); - return true; - } catch (Exception e) { - log.error(e.getMessage(), e); - return false; - } - } - - /** - * 根据分值移除区间元素。 - * @param key - * @param min - * @param max - * @return - */ - public Long removeRangeByScore(String key, double min, double max) { - return redisTemplate.opsForZSet().removeRangeByScore(key, min, max); - } - - /** - * 获取变量指定区间的元素。 - * @param key - * @param start - * @param end - * @return - */ - public Set range(String key, long start, long end) { - return redisTemplate.opsForZSet().range(key, start, end); - } - - /** - * 返回有序集 key 中,成员 member 的 score 值。 - * 如果 member 元素不是有序集 key 的成员,或 key 不存在,返回 nil 。 - * @param key - * @param member - * @return - */ - public Double zscore(String key, Object member) { - return redisTemplate.opsForZSet().score(key, member); - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/RedissonUtil.java b/wjcy-common/src/main/java/me/zhengjie/utils/RedissonUtil.java deleted file mode 100644 index f02ed00..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/RedissonUtil.java +++ /dev/null @@ -1,167 +0,0 @@ -package me.zhengjie.utils; - - -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.exception.BadRequestException; -import org.redisson.api.*; -import org.redisson.config.Config; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; -import java.io.IOException; -import java.util.concurrent.TimeUnit; - -/** - *

- * redisson - *

- * - * @Author xx - * @Date 2021/8/11 - **/ -@Slf4j -@Component("redissonUtil") -public class RedissonUtil { - - @Resource - private RedissonClient redissonClient; - - public void getRedissonClient() throws IOException { - Config config = redissonClient.getConfig(); -// System.out.println(config.toJSON().toString()); - } - - /**` - * 获取字符串对象 - * - * @param objectName - * @return - */ - public RBucket getRBucket(String objectName) { - RBucket bucket = redissonClient.getBucket(objectName); - return bucket; - } - - /** - * 获取Map对象 - * - * @param objectName - * @return - */ - public RMap getRMap(String objectName) { - RMap map = redissonClient.getMap(objectName); - return map; - } - - /** - * 获取有序集合 - * - * @param objectName - * @return - */ - public RSortedSet getRSortedSet(String objectName) { - RSortedSet sortedSet = redissonClient.getSortedSet(objectName); - return sortedSet; - } - - /** - * 获取集合 - * - * @param objectName - * @return - */ - public RSet getRSet(String objectName) { - RSet rSet = redissonClient.getSet(objectName); - return rSet; - } - - /** - * 获取列表 - * - * @param objectName - * @return - */ - public RList getRList(String objectName) { - RList rList = redissonClient.getList(objectName); - return rList; - } - - /** - * 获取队列 - * - * @param objectName - * @return - */ - public RQueue getRQueue(String objectName) { - RQueue rQueue = redissonClient.getQueue(objectName); - return rQueue; - } - - /** - * 获取双端队列 - * - * @param objectName - * @return - */ - public RDeque getRDeque(String objectName) { - RDeque rDeque = redissonClient.getDeque(objectName); - return rDeque; - } - - - /** - * 获取锁 - * - * @param objectName - * @return - */ - public RLock getRLock(String objectName) { - RLock rLock = redissonClient.getLock(objectName); - return rLock; - } - - /** - * 获取读取锁 - * - * @param objectName - * @return - */ - public RReadWriteLock getRWLock(String objectName) { - RReadWriteLock rwlock = redissonClient.getReadWriteLock(objectName); - return rwlock; - } - - /** - * 获取原子数 - * - * @param objectName - * @return - */ - public RAtomicLong getRAtomicLong(String objectName) { - RAtomicLong rAtomicLong = redissonClient.getAtomicLong(objectName); - return rAtomicLong; - } - - /** - * 获取记数锁 - * - * @param objectName - * @return - */ - public RCountDownLatch getRCountDownLatch(String objectName) { - RCountDownLatch rCountDownLatch = redissonClient.getCountDownLatch(objectName); - return rCountDownLatch; - } - - /** - * 获取消息的Topic - * - * @param objectName - * @return - */ - public RTopic getRTopic(String objectName) { - RTopic rTopic = redissonClient.getTopic(objectName); - return rTopic; - } -} - diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/RequestHolder.java b/wjcy-common/src/main/java/me/zhengjie/utils/RequestHolder.java deleted file mode 100644 index 2720ae5..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/RequestHolder.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.utils; - -import cn.hutool.core.convert.Convert; -import cn.hutool.core.util.ObjectUtil; -import me.zhengjie.enums.LanguageEnum; -import org.springframework.web.context.request.RequestAttributes; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; -import javax.servlet.http.HttpServletRequest; -import java.util.Objects; - -/** - * 获取 HttpServletRequest - * @author Zheng Jie - * @date 2018-11-24 - */ -public class RequestHolder { - - public static HttpServletRequest getHttpServletRequest() { - return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest(); - } - - public static String getLanguage() { - RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); - if (ObjectUtil.isNull(requestAttributes) || !(requestAttributes instanceof ServletRequestAttributes)) { - return LanguageEnum.ZH.getValue(); - } - HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest(); - if (ObjectUtil.isNull(request)) { - return LanguageEnum.ZH.getValue(); - } - return Convert.toStr(request.getHeader("language"), LanguageEnum.ZH.getValue()); - } - -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/RsaUtils.java b/wjcy-common/src/main/java/me/zhengjie/utils/RsaUtils.java deleted file mode 100644 index b42cec7..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/RsaUtils.java +++ /dev/null @@ -1,202 +0,0 @@ -package me.zhengjie.utils; - -import org.apache.commons.codec.binary.Base64; -import javax.crypto.Cipher; -import java.io.ByteArrayOutputStream; -import java.security.*; -import java.security.interfaces.RSAPrivateKey; -import java.security.interfaces.RSAPublicKey; -import java.security.spec.PKCS8EncodedKeySpec; -import java.security.spec.X509EncodedKeySpec; - -/** - * @author https://www.cnblogs.com/nihaorz/p/10690643.html - * @description Rsa 工具类,公钥私钥生成,加解密 - * @date 2020-05-18 - **/ -public class RsaUtils { - - private static final String SRC = "panpan@123"; - - public static void main(String[] args) throws Exception { -// System.out.println("\n"); -// RsaKeyPair keyPair = generateKeyPair(); -// System.out.println("公钥:" + keyPair.getPublicKey()); -// System.out.println("私钥:" + keyPair.getPrivateKey()); -// System.out.println("\n"); -// test1(keyPair); -// System.out.println("\n"); -// test2(keyPair); -// System.out.println("\n"); - - - String text1 = encryptByPublicKey("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdFXJjqlBdh1ri8hS2bEvwjREJyRAqruwtf+c/bgFiBOxuW4LAVIiMnimfnmLiL0/h0Q1YLKjrnFkOwXLvZTgwwCiX1uF5WhOyCsGEEQDhfvFTlInemFNdi8zqWxoONbRBb9wJbqS8K6LtzXu2Oltu5hzqQXKwY+sNCVbKCrt/KwIDAQAB", RsaUtils.SRC); - System.out.println(text1); - } - - /** - * 公钥加密私钥解密 - */ - private static void test1(RsaKeyPair keyPair) throws Exception { - System.out.println("***************** 公钥加密私钥解密开始 *****************"); - String text1 = encryptByPublicKey(keyPair.getPublicKey(), RsaUtils.SRC); - String text2 = decryptByPrivateKey(keyPair.getPrivateKey(), text1); - System.out.println("加密前:" + RsaUtils.SRC); - System.out.println("加密后:" + text1); - System.out.println("解密后:" + text2); - if (RsaUtils.SRC.equals(text2)) { - System.out.println("解密字符串和原始字符串一致,解密成功"); - } else { - System.out.println("解密字符串和原始字符串不一致,解密失败"); - } - System.out.println("***************** 公钥加密私钥解密结束 *****************"); - } - - /** - * 私钥加密公钥解密 - * @throws Exception / - */ - private static void test2(RsaKeyPair keyPair) throws Exception { - System.out.println("***************** 私钥加密公钥解密开始 *****************"); - String text1 = encryptByPrivateKey(keyPair.getPrivateKey(), RsaUtils.SRC); - String text2 = decryptByPublicKey(keyPair.getPublicKey(), text1); - System.out.println("加密前:" + RsaUtils.SRC); - System.out.println("加密后:" + text1); - System.out.println("解密后:" + text2); - if (RsaUtils.SRC.equals(text2)) { - System.out.println("解密字符串和原始字符串一致,解密成功"); - } else { - System.out.println("解密字符串和原始字符串不一致,解密失败"); - } - System.out.println("***************** 私钥加密公钥解密结束 *****************"); - } - - /** - * 公钥解密 - * - * @param publicKeyText 公钥 - * @param text 待解密的信息 - * @return / - * @throws Exception / - */ - public static String decryptByPublicKey(String publicKeyText, String text) throws Exception { - X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText)); - KeyFactory keyFactory = KeyFactory.getInstance("RSA"); - PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec); - Cipher cipher = Cipher.getInstance("RSA"); - cipher.init(Cipher.DECRYPT_MODE, publicKey); - byte[] result = doLongerCipherFinal(Cipher.DECRYPT_MODE, cipher, Base64.decodeBase64(text)); - return new String(result); - } - - /** - * 私钥加密 - * - * @param privateKeyText 私钥 - * @param text 待加密的信息 - * @return / - * @throws Exception / - */ - public static String encryptByPrivateKey(String privateKeyText, String text) throws Exception { - PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText)); - KeyFactory keyFactory = KeyFactory.getInstance("RSA"); - PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); - Cipher cipher = Cipher.getInstance("RSA"); - cipher.init(Cipher.ENCRYPT_MODE, privateKey); - byte[] result = doLongerCipherFinal(Cipher.ENCRYPT_MODE, cipher, text.getBytes()); - return Base64.encodeBase64String(result); - } - - /** - * 私钥解密 - * - * @param privateKeyText 私钥 - * @param text 待解密的文本 - * @return / - * @throws Exception / - */ - public static String decryptByPrivateKey(String privateKeyText, String text) throws Exception { - PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText)); - KeyFactory keyFactory = KeyFactory.getInstance("RSA"); - PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5); - Cipher cipher = Cipher.getInstance("RSA"); - cipher.init(Cipher.DECRYPT_MODE, privateKey); - byte[] result = doLongerCipherFinal(Cipher.DECRYPT_MODE, cipher, Base64.decodeBase64(text)); - return new String(result); - } - - /** - * 公钥加密 - * - * @param publicKeyText 公钥 - * @param text 待加密的文本 - * @return / - */ - public static String encryptByPublicKey(String publicKeyText, String text) throws Exception { - X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText)); - KeyFactory keyFactory = KeyFactory.getInstance("RSA"); - PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec2); - Cipher cipher = Cipher.getInstance("RSA"); - cipher.init(Cipher.ENCRYPT_MODE, publicKey); - byte[] result = doLongerCipherFinal(Cipher.ENCRYPT_MODE, cipher, text.getBytes()); - return Base64.encodeBase64String(result); - } - - private static byte[] doLongerCipherFinal(int opMode,Cipher cipher, byte[] source) throws Exception { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - if (opMode == Cipher.DECRYPT_MODE) { - out.write(cipher.doFinal(source)); - } else { - int offset = 0; - int totalSize = source.length; - while (totalSize - offset > 0) { - int size = Math.min(cipher.getOutputSize(0) - 11, totalSize - offset); - out.write(cipher.doFinal(source, offset, size)); - offset += size; - } - } - out.close(); - return out.toByteArray(); - } - - /** - * 构建RSA密钥对 - * - * @return / - * @throws NoSuchAlgorithmException / - */ - public static RsaKeyPair generateKeyPair() throws NoSuchAlgorithmException { - KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); - keyPairGenerator.initialize(1024); - KeyPair keyPair = keyPairGenerator.generateKeyPair(); - RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic(); - RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate(); - String publicKeyString = Base64.encodeBase64String(rsaPublicKey.getEncoded()); - String privateKeyString = Base64.encodeBase64String(rsaPrivateKey.getEncoded()); - return new RsaKeyPair(publicKeyString, privateKeyString); - } - - - /** - * RSA密钥对对象 - */ - public static class RsaKeyPair { - - private final String publicKey; - private final String privateKey; - - public RsaKeyPair(String publicKey, String privateKey) { - this.publicKey = publicKey; - this.privateKey = privateKey; - } - - public String getPublicKey() { - return publicKey; - } - - public String getPrivateKey() { - return privateKey; - } - - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/SecurityUtils.java b/wjcy-common/src/main/java/me/zhengjie/utils/SecurityUtils.java deleted file mode 100644 index dfeee43..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/SecurityUtils.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.utils; - -import cn.hutool.json.JSONArray; -import cn.hutool.json.JSONObject; -import cn.hutool.json.JSONUtil; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.utils.enums.DataScopeEnum; -import org.springframework.http.HttpStatus; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import java.util.List; - -/** - * 获取当前登录的用户 - * @author Zheng Jie - * @date 2019-01-17 - */ -@Slf4j -public class SecurityUtils { - - /** - * 获取当前登录的用户 - * @return UserDetails - */ - public static UserDetails getCurrentUser() { - UserDetailsService userDetailsService = SpringContextHolder.getBean(UserDetailsService.class); - return userDetailsService.loadUserByUsername(getCurrentUsername()); - } - - /** - * 获取系统用户名称 - * - * @return 系统用户名称 - */ - public static String getCurrentUsername() { - final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - if (authentication == null) { - throw new BadRequestException(HttpStatus.UNAUTHORIZED, "当前登录状态过期"); - } - if (authentication.getPrincipal() instanceof UserDetails) { - UserDetails userDetails = (UserDetails) authentication.getPrincipal(); - return userDetails.getUsername(); - } - throw new BadRequestException(HttpStatus.UNAUTHORIZED, "找不到当前登录的信息"); - } - - /** - * 获取系统用户ID - * @return 系统用户ID - */ - public static Long getCurrentUserId() { - UserDetails userDetails = getCurrentUser(); - return new JSONObject(new JSONObject(userDetails).get("user")).get("id", Long.class); - } - - /** - * 是否是总商户号 - * @return true:是 - */ - public static boolean isAdmin() { - UserDetails userDetails = getCurrentUser(); - return new JSONObject(new JSONObject(userDetails).get("user")).get("isAdmin", Boolean.class); - } - - - public static boolean isNotAdmin() { - return !isAdmin(); - } - - /** - * 获取当前用户的数据权限 - * @return / - */ - public static List getCurrentUserDataScope(){ - UserDetails userDetails = getCurrentUser(); - JSONArray array = JSONUtil.parseArray(new JSONObject(userDetails).get("dataScopes")); - return JSONUtil.toList(array,Long.class); - } - - /** - * 获取数据权限级别 - * @return 级别 - */ - public static String getDataScopeType() { - List dataScopes = getCurrentUserDataScope(); - if(dataScopes.size() != 0){ - return ""; - } - return DataScopeEnum.ALL.getValue(); - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/ServletUtils.java b/wjcy-common/src/main/java/me/zhengjie/utils/ServletUtils.java deleted file mode 100644 index 3c68d32..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/ServletUtils.java +++ /dev/null @@ -1,184 +0,0 @@ -package me.zhengjie.utils; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import java.net.URLEncoder; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import javax.servlet.ServletRequest; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; - -import cn.hutool.core.convert.Convert; -import org.springframework.web.context.request.RequestAttributes; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; - -/** - * 客户端工具类 - * - * @author - */ -public class ServletUtils -{ - /** - * 获取String参数 - */ - public static String getParameter(String name) - { - return getRequest().getParameter(name); - } - - /** - * 获取String参数 - */ - public static String getParameter(String name, String defaultValue) - { - return Convert.toStr(getRequest().getParameter(name), defaultValue); - } - - /** - * 获取Integer参数 - */ - public static Integer getParameterToInt(String name) - { - return Convert.toInt(getRequest().getParameter(name)); - } - - /** - * 获取Integer参数 - */ - public static Integer getParameterToInt(String name, Integer defaultValue) - { - return Convert.toInt(getRequest().getParameter(name), defaultValue); - } - - /** - * 获取Boolean参数 - */ - public static Boolean getParameterToBool(String name) - { - return Convert.toBool(getRequest().getParameter(name)); - } - - /** - * 获取Boolean参数 - */ - public static Boolean getParameterToBool(String name, Boolean defaultValue) - { - return Convert.toBool(getRequest().getParameter(name), defaultValue); - } - - /** - * 获得所有请求参数 - * - * @param request 请求对象{@link ServletRequest} - * @return Map - */ - public static Map getParams(ServletRequest request) - { - final Map map = request.getParameterMap(); - return Collections.unmodifiableMap(map); - } - - /** - * 获得所有请求参数 - * - * @param request 请求对象{@link ServletRequest} - * @return Map - */ - public static Map getParamMap(ServletRequest request) - { - Map params = new HashMap<>(); - for (Map.Entry entry : getParams(request).entrySet()) - { - params.put(entry.getKey(), StringUtils.join(entry.getValue(), ",")); - } - return params; - } - - /** - * 获取request - */ - public static HttpServletRequest getRequest() - { - return getRequestAttributes().getRequest(); - } - - /** - * 获取response - */ - public static HttpServletResponse getResponse() - { - return getRequestAttributes().getResponse(); - } - - /** - * 获取session - */ - public static HttpSession getSession() - { - return getRequest().getSession(); - } - - public static ServletRequestAttributes getRequestAttributes() - { - RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); - return (ServletRequestAttributes) attributes; - } - - /** - * 将字符串渲染到客户端 - * - * @param response 渲染对象 - * @param string 待渲染的字符串 - */ - public static void renderString(HttpServletResponse response, String string) - { - try - { - response.setStatus(200); - response.setContentType("application/json"); - response.setCharacterEncoding("utf-8"); - response.getWriter().print(string); - } - catch (IOException e) - { - e.printStackTrace(); - } - } - - /** - * 是否是Ajax异步请求 - * - * @param request - */ - public static boolean isAjaxRequest(HttpServletRequest request) - { - String accept = request.getHeader("accept"); - if (accept != null && accept.contains("application/json")) - { - return true; - } - - String xRequestedWith = request.getHeader("X-Requested-With"); - if (xRequestedWith != null && xRequestedWith.contains("XMLHttpRequest")) - { - return true; - } - - String uri = request.getRequestURI(); - if (NewStringUtils.inStringIgnoreCase(uri, ".json", ".xml")) - { - return true; - } - - String ajax = request.getParameter("__ajax"); - return NewStringUtils.inStringIgnoreCase(ajax, "json", "xml"); - } - - -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/SpringContextHolder.java b/wjcy-common/src/main/java/me/zhengjie/utils/SpringContextHolder.java deleted file mode 100644 index 4f3aaf6..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/SpringContextHolder.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.utils; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.DisposableBean; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.core.env.Environment; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * @author Jie - * @date 2019-01-07 - */ -@Slf4j -public class SpringContextHolder implements ApplicationContextAware, DisposableBean { - - private static ApplicationContext applicationContext = null; - private static final List CALL_BACKS = new ArrayList<>(); - private static boolean addCallback = true; - - /** - * 针对 某些初始化方法,在SpringContextHolder 未初始化时 提交回调方法。 - * 在SpringContextHolder 初始化后,进行回调使用 - * - * @param callBack 回调函数 - */ - public synchronized static void addCallBacks(CallBack callBack) { - if (addCallback) { - SpringContextHolder.CALL_BACKS.add(callBack); - } else { - log.warn("CallBack:{} 已无法添加!立即执行", callBack.getCallBackName()); - callBack.executor(); - } - } - - /** - * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. - */ - @SuppressWarnings("unchecked") - public static T getBean(String name) { - assertContextInjected(); - return (T) applicationContext.getBean(name); - } - - public static Map getBeansOfType(Class tClass) { - assertContextInjected(); - return applicationContext.getBeansOfType(tClass); - } - - /** - * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. - */ - public static T getBean(Class requiredType) { - assertContextInjected(); - return applicationContext.getBean(requiredType); - } - - /** - * 获取SpringBoot 配置信息 - * - * @param property 属性key - * @param defaultValue 默认值 - * @param requiredType 返回类型 - * @return / - */ - public static T getProperties(String property, T defaultValue, Class requiredType) { - T result = defaultValue; - try { - result = getBean(Environment.class).getProperty(property, requiredType); - } catch (Exception ignored) {} - return result; - } - - /** - * 获取SpringBoot 配置信息 - * - * @param property 属性key - * @return / - */ - public static String getProperties(String property) { - return getProperties(property, null, String.class); - } - - /** - * 获取SpringBoot 配置信息 - * - * @param property 属性key - * @param requiredType 返回类型 - * @return / - */ - public static T getProperties(String property, Class requiredType) { - return getProperties(property, null, requiredType); - } - - /** - * 检查ApplicationContext不为空. - */ - private static void assertContextInjected() { - if (applicationContext == null) { - throw new IllegalStateException("applicaitonContext属性未注入, 请在applicationContext" + - ".xml中定义SpringContextHolder或在SpringBoot启动类中注册SpringContextHolder."); - } - } - - /** - * 清除SpringContextHolder中的ApplicationContext为Null. - */ - private static void clearHolder() { - log.debug("清除SpringContextHolder中的ApplicationContext:" - + applicationContext); - applicationContext = null; - } - - @Override - public void destroy() { - SpringContextHolder.clearHolder(); - } - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - if (SpringContextHolder.applicationContext != null) { - log.warn("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext); - } - SpringContextHolder.applicationContext = applicationContext; - if (addCallback) { - for (CallBack callBack : SpringContextHolder.CALL_BACKS) { - callBack.executor(); - } - CALL_BACKS.clear(); - } - SpringContextHolder.addCallback = false; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/StringUtil.java b/wjcy-common/src/main/java/me/zhengjie/utils/StringUtil.java deleted file mode 100644 index c2c474d..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/StringUtil.java +++ /dev/null @@ -1,200 +0,0 @@ -package me.zhengjie.utils; - - -import cn.hutool.core.convert.Convert; -import cn.hutool.core.util.ObjectUtil; - -import java.text.SimpleDateFormat; -import java.time.LocalDate; -import java.util.Calendar; -import java.util.LinkedList; -import java.util.List; -/** - *

- * 驼峰与下划线的属性名互相转换 - *

- * - * @Author xx - * @Date 2021/7/20 - **/ -public class StringUtil { - - /** - * 先按英文逗号打散成字符串数组,在随机从中选择一个返回 - * @author: zeng - */ - public static String spiltAndRandom(String str){ - if (ObjectUtil.isEmpty(str)) { - return null; - } - String[] split = str.split(","); - - int randomNum = (int) (Math.random() * split.length); - return split[randomNum]; - } - - /** - * 验证4段ip地址是否符合规范,并且开始的ip不能大于结束的ip - * - * @return - */ - public static boolean verifyIpAddr(String beginIp, String endIp) { - String[] beginIPsplit = beginIp.split("\\."); - String[] endIPsplit = endIp.split("\\."); - if (beginIPsplit.length == 4 && endIPsplit.length == 4) { - for (int i = 0; i < 4; i++) { - if (Convert.toInt(beginIPsplit[i]) < 0 || Convert.toInt(beginIPsplit[i]) > 255) { - return false; - } - if (Convert.toInt(endIPsplit[i]) < 0 || Convert.toInt(endIPsplit[i]) > 255) { - return false; - } -// if (Convert.toInt(beginIPsplit[i]) > Convert.toInt(endIPsplit[i])) { -// return false; -// } - } - return true; - } - return false; - } - - /** - * 转换为下划线 - * - * @param camelCaseName - * @return - */ - public static String underscoreName(String camelCaseName) { - StringBuilder result = new StringBuilder(); - if (camelCaseName != null && camelCaseName.length() > 0) { - result.append(camelCaseName.substring(0, 1).toLowerCase()); - for (int i = 1; i < camelCaseName.length(); i++) { - char ch = camelCaseName.charAt(i); - if (Character.isUpperCase(ch)) { - result.append("_"); - result.append(Character.toLowerCase(ch)); - } else { - result.append(ch); - } - } - } - return result.toString(); - } - - /** - * 转换为驼峰 - * - * @param underscoreName - * @return - */ - public static String camelCaseName(String underscoreName) { - StringBuilder result = new StringBuilder(); - if (underscoreName != null && underscoreName.length() > 0) { - boolean flag = false; - for (int i = 0; i < underscoreName.length(); i++) { - char ch = underscoreName.charAt(i); - if ("_".charAt(0) == ch) { - flag = true; - } else { - if (flag) { - result.append(Character.toUpperCase(ch)); - flag = false; - } else { - result.append(ch); - } - } - } - } - return result.toString(); - } - - public static String getDeviceType(String userAgent) { - if (ObjectUtil.isNotEmpty(userAgent)) { - - userAgent = userAgent.toUpperCase(); - - if (userAgent.contains("WINDOWS")) { - return "WINDOWS"; - } - if (userAgent.contains("IPHONE")) { - return "IOS"; - } - if (userAgent.contains("HUAWEI")) { - return "华为"; - } - if (userAgent.contains("MI")) { - return "小米"; - } - if (userAgent.contains("VIVO")) { - return "VIVO"; - } - if (userAgent.contains("OPPO")) { - return "OPPO"; - } - if (userAgent.contains("MEIZU")) { - return "魅族"; - } - if (userAgent.contains("SM-")) { - return "三星"; - } - if (userAgent.contains("ANDROID")){ - return "安卓"; - } - } - return "未知"; - } - - //设置时间格式 - static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); - - /** - * 获取当月第一天 yyyy-MM-dd 格式日期 - * @return - */ - public static String getMonthFirstDay() { - Calendar ca = Calendar.getInstance(); - ca.add(Calendar.MONTH, 0); - ca.set(Calendar.DAY_OF_MONTH, 1); - String firstDay = format.format(ca.getTime()); - return firstDay; - } - /** - * 获取当月最后一天 yyyy-MM-dd 格式日期 - * @return - */ - public static String getMonthLastDay() { - //获得实体类 - Calendar ca = Calendar.getInstance(); - //设置最后一天 - ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH)); - //最后一天格式化 - String lastDay = format.format(ca.getTime()); - return lastDay; - } - - /** - * 获取当月每天的 yyyy-MM-dd 格式日期 - * @return - */ - public static List getMonthAllDay() { - List list = new LinkedList(); - LocalDate monthFirstDay = DateUtil.parseLocalDateFormatyMd(getMonthFirstDay()); - LocalDate monthLastDay = DateUtil.parseLocalDateFormatyMd(getMonthLastDay()); - while (true) { - list.add(monthFirstDay.toString()); - if (monthFirstDay.equals(monthLastDay)) { - return list; - } - monthFirstDay = monthFirstDay.plusDays(1); - } - } - - - public static void main(String[] args) { - // System.out.println(StringUtil.underscoreName("orderNo")); -// getMonthAllDay().forEach(System.out::println); - - String deviceType = getDeviceType("NX629J(Android/11) (com.hj.bybf8) UniApp/0.28.0 1080x2340"); - System.out.println(deviceType); - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/StringUtils.java b/wjcy-common/src/main/java/me/zhengjie/utils/StringUtils.java deleted file mode 100644 index b5c2bd6..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/StringUtils.java +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.utils; - -import cn.hutool.http.HttpUtil; -import cn.hutool.json.JSONObject; -import cn.hutool.json.JSONUtil; -import me.zhengjie.config.SystemConfig; -import nl.basjes.parse.useragent.UserAgent; -import nl.basjes.parse.useragent.UserAgentAnalyzer; -import org.lionsoul.ip2region.DataBlock; -import org.lionsoul.ip2region.DbConfig; -import org.lionsoul.ip2region.DbSearcher; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.servlet.http.HttpServletRequest; -import java.io.File; -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.net.UnknownHostException; -import java.util.Calendar; -import java.util.Date; -import java.util.Enumeration; - -/** - * @author Zheng Jie - * 字符串工具类, 继承org.apache.commons.lang3.StringUtils类 - */ -public class StringUtils extends org.apache.commons.lang3.StringUtils { - - private static final Logger log = LoggerFactory.getLogger(StringUtils.class); - private static boolean ipLocal = false; - private static File file = null; - private static DbConfig config; - private static final char SEPARATOR = '_'; - private static final String UNKNOWN = "unknown"; - - private static final UserAgentAnalyzer userAgentAnalyzer = UserAgentAnalyzer - .newBuilder() - .hideMatcherLoadStats() - .withCache(10000) - .withField(UserAgent.AGENT_NAME_VERSION) - .build(); - - - static { - SpringContextHolder.addCallBacks(() -> { - StringUtils.ipLocal = SpringContextHolder.getProperties("ip.local-parsing", false, Boolean.class); - if (ipLocal) { - /* - * 此文件为独享 ,不必关闭 - */ -// String path = "ip2region/ip2region.db"; -// String name = "ip2region.db"; - try { - config = new DbConfig(); - file = new File(SystemConfig.IP2REGION_DB_PATH); - } catch (Exception e) { - log.error(e.getMessage(), e); - } - } - }); - } - - /** - * 驼峰命名法工具 - * - * @return toCamelCase(" hello_world ") == "helloWorld" - * toCapitalizeCamelCase("hello_world") == "HelloWorld" - * toUnderScoreCase("helloWorld") = "hello_world" - */ - public static String toCamelCase(String s) { - if (s == null) { - return null; - } - - s = s.toLowerCase(); - - StringBuilder sb = new StringBuilder(s.length()); - boolean upperCase = false; - for (int i = 0; i < s.length(); i++) { - char c = s.charAt(i); - - if (c == SEPARATOR) { - upperCase = true; - } else if (upperCase) { - sb.append(Character.toUpperCase(c)); - upperCase = false; - } else { - sb.append(c); - } - } - - return sb.toString(); - } - - /** - * 驼峰命名法工具 - * - * @return toCamelCase(" hello_world ") == "helloWorld" - * toCapitalizeCamelCase("hello_world") == "HelloWorld" - * toUnderScoreCase("helloWorld") = "hello_world" - */ - public static String toCapitalizeCamelCase(String s) { - if (s == null) { - return null; - } - s = toCamelCase(s); - return s.substring(0, 1).toUpperCase() + s.substring(1); - } - - /** - * 驼峰命名法工具 - * - * @return toCamelCase(" hello_world ") == "helloWorld" - * toCapitalizeCamelCase("hello_world") == "HelloWorld" - * toUnderScoreCase("helloWorld") = "hello_world" - */ - static String toUnderScoreCase(String s) { - if (s == null) { - return null; - } - - StringBuilder sb = new StringBuilder(); - boolean upperCase = false; - for (int i = 0; i < s.length(); i++) { - char c = s.charAt(i); - - boolean nextUpperCase = true; - - if (i < (s.length() - 1)) { - nextUpperCase = Character.isUpperCase(s.charAt(i + 1)); - } - - if ((i > 0) && Character.isUpperCase(c)) { - if (!upperCase || !nextUpperCase) { - sb.append(SEPARATOR); - } - upperCase = true; - } else { - upperCase = false; - } - - sb.append(Character.toLowerCase(c)); - } - - return sb.toString(); - } - - /** - * 获取ip地址 - */ - public static String getIp(HttpServletRequest request) { - String ip = request.getHeader("X-Real-IP"); - if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { - ip = request.getHeader("X-Forwarded-For"); - } - if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { - ip = request.getHeader("Proxy-Client-IP"); - } - if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { - ip = request.getHeader("WL-Proxy-Client-IP"); - } - if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { - ip = request.getRemoteAddr(); - } - String comma = ","; - String localhost = "127.0.0.1"; - if (ip.contains(comma)) { - ip = ip.split(",")[0]; - } - if (localhost.equals(ip)) { - // 获取本机真正的ip地址 - try { - ip = InetAddress.getLocalHost().getHostAddress(); - } catch (UnknownHostException e) { - log.error(e.getMessage(), e); - } - } - return ip; - } - - /** - * 根据ip获取详细地址 - */ - public static String getCityInfo(String ip) { - if (ipLocal) { - return getLocalCityInfo(ip); - } else { - return getHttpCityInfo(ip); - } - } - - /** - * 根据ip获取详细地址 - */ - public static String getHttpCityInfo(String ip) { - String api = String.format(ElAdminConstant.Url.IP_URL, ip); - JSONObject object = JSONUtil.parseObj(HttpUtil.get(api)); - return object.get("addr", String.class); - } - - /** - * 根据ip获取详细地址 - */ - public static String getLocalCityInfo(String ip) { - try { - DataBlock dataBlock = new DbSearcher(config, file.getPath()) - .binarySearch(ip); - String region = dataBlock.getRegion(); - String address = region.replace("0|", ""); - char symbol = '|'; - if (address.charAt(address.length() - 1) == symbol) { - address = address.substring(0, address.length() - 1); - } - return address.equals(ElAdminConstant.REGION) ? "内网IP" : address; - } catch (Exception e) { - log.error(e.getMessage(), e); - } - return ""; - } - - public static String getBrowser(HttpServletRequest request) { - UserAgent.ImmutableUserAgent userAgent = userAgentAnalyzer.parse(request.getHeader("User-Agent")); - return userAgent.get(UserAgent.AGENT_NAME_VERSION).getValue(); - } - - /** - * 获得当天是周几 - */ - public static String getWeekDay() { - String[] weekDays = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; - Calendar cal = Calendar.getInstance(); - cal.setTime(new Date()); - - int w = cal.get(Calendar.DAY_OF_WEEK) - 1; - if (w < 0) { - w = 0; - } - return weekDays[w]; - } - - /** - * 获取当前机器的IP - * - * @return / - */ - public static String getLocalIp() { - try { - InetAddress candidateAddress = null; - // 遍历所有的网络接口 - for (Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); interfaces.hasMoreElements();) { - NetworkInterface anInterface = interfaces.nextElement(); - // 在所有的接口下再遍历IP - for (Enumeration inetAddresses = anInterface.getInetAddresses(); inetAddresses.hasMoreElements();) { - InetAddress inetAddr = inetAddresses.nextElement(); - // 排除loopback类型地址 - if (!inetAddr.isLoopbackAddress()) { - if (inetAddr.isSiteLocalAddress()) { - // 如果是site-local地址,就是它了 - return inetAddr.getHostAddress(); - } else if (candidateAddress == null) { - // site-local类型的地址未被发现,先记录候选地址 - candidateAddress = inetAddr; - } - } - } - } - if (candidateAddress != null) { - return candidateAddress.getHostAddress(); - } - // 如果没有发现 non-loopback地址.只能用最次选的方案 - InetAddress jdkSuppliedAddress = InetAddress.getLocalHost(); - if (jdkSuppliedAddress == null) { - return ""; - } - return jdkSuppliedAddress.getHostAddress(); - } catch (Exception e) { - return ""; - } - } - - public static String append(String str, char appendValue, int count) { - - StringBuilder stringBuilder = new StringBuilder(str); - for (int i = 0; i < count; i++) { - stringBuilder.append(appendValue); - } - - return stringBuilder.toString(); - } - - - /** - * 首字母大写 - * - * @param string - * @return - */ - public static String toUpperCase4Index(String string) { - char[] methodName = string.toCharArray(); - methodName[0] = toUpperCase(methodName[0]); - return String.valueOf(methodName); - } - - /** - * 字符转成大写 - * - * @param chars - * @return - */ - public static char toUpperCase(char chars) { - if (97 <= chars && chars <= 122) { - chars ^= 32; - } - return chars; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/ThrowableUtil.java b/wjcy-common/src/main/java/me/zhengjie/utils/ThrowableUtil.java deleted file mode 100644 index 075a65c..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/ThrowableUtil.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.utils; - -import java.io.PrintWriter; -import java.io.StringWriter; - -/** - * 异常工具 2019-01-06 - * @author Zheng Jie - */ -public class ThrowableUtil { - - /** - * 获取堆栈信息 - */ - public static String getStackTrace(Throwable throwable){ - StringWriter sw = new StringWriter(); - try (PrintWriter pw = new PrintWriter(sw)) { - throwable.printStackTrace(pw); - return sw.toString(); - } - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/TransformMap.java b/wjcy-common/src/main/java/me/zhengjie/utils/TransformMap.java deleted file mode 100644 index c5aa2be..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/TransformMap.java +++ /dev/null @@ -1,60 +0,0 @@ -package me.zhengjie.utils; - - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.convert.Convert; -import cn.hutool.core.util.ObjectUtil; - -import java.util.Collections; -import java.util.Map; -/** - *

- * DTO 转为 map集合,并过滤时间 - *

- * - * @Author xx - * @Date 2021/7/22 - **/ -public class TransformMap { - - public static Map toMap(Object dto) { - if (dto == null) { - return Collections.emptyMap(); - } - Object obj = EmptyAttributeFiler.emptyAttributeFiler(dto); - Map map = BeanUtil.beanToMap(obj); - if (obj instanceof Map) { - map = (Map)obj; - } - String stime = Convert.toStr(map.get("stime")); - String etime = Convert.toStr(map.get("etime")); - if (ObjectUtil.isAllNotEmpty(stime,etime) && (stime.length()== etime.length() && stime.length()==10)) { - map.put("stime", map.get("stime").toString() + " 00:00:00"); - map.put("etime", map.get("etime").toString() + " 23:59:59"); - } - Integer page = Convert.toInt(map.get("page")); - Integer pageSize = Convert.toInt(map.get("pageSize")); - if (ObjectUtil.isNotNull(page) && ObjectUtil.isNotNull(pageSize)) { - if (page < 1) { - page = 1; - } - if (pageSize < 1) { - pageSize = 10; - map.put("pageSize", 10); - } - map.put("page", (page - 1) * pageSize); - } - Double minPrice =Convert.toDouble(map.get("minPrice")); - if(ObjectUtil.isNotNull(minPrice)){ - map.put("minPrice",minPrice*100); - } - - Double maxPrice =Convert.toDouble(map.get("maxPrice")); - if(ObjectUtil.isNotNull(maxPrice)){ - map.put("maxPrice",maxPrice*100); - } - return map; - } - - -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/TransformQueryWrapper.java b/wjcy-common/src/main/java/me/zhengjie/utils/TransformQueryWrapper.java deleted file mode 100644 index f796fd0..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/TransformQueryWrapper.java +++ /dev/null @@ -1,165 +0,0 @@ -package me.zhengjie.utils; - - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import me.zhengjie.entity.QueryWrapperAndPage; - -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Date; -import java.util.Map; -/** - *

- * DTO 转为 QueryWrapper,并过滤时间 - *

- * - * @Author xx - * @Date 2021/7/20 - **/ -public class TransformQueryWrapper { - - /** - * DTO 转QueryWrapperAndPage - * 时间特殊处理 其他都是等于 - * 参数对象 属性命名 保持与书库驼峰对应 - * @param dto - * @return - */ - public QueryWrapperAndPage dtoToQueryWrapper(Object dto) { - QueryWrapperAndPage queryWrapperAndPage = new QueryWrapperAndPage(); - QueryWrapper queryWrapper = new QueryWrapper<>(); - Page page = new Page<>(1,10); - Map dtoMap = BeanUtil.beanToMap(dto); - if (ObjectUtil.isNotNull(dtoMap.get("stime"))) { - queryWrapper.ge("created_at", dtoMap.get("stime").toString() + " 00:00:00"); - dtoMap.remove("stime"); - } - - if (ObjectUtil.isNotNull(dtoMap.get("etime"))) { - queryWrapper.le("created_at", dtoMap.get("etime").toString() + " 23:59:59"); - dtoMap.remove("etime"); - } - if (ObjectUtil.isNotNull(dtoMap.get("guessStime"))) { - queryWrapper.ge("completion_time", dtoMap.get("guessStime").toString() + " 00:00:00"); - dtoMap.remove("guessStime"); - } - - if (ObjectUtil.isNotNull(dtoMap.get("guessEtime"))) { - queryWrapper.le("completion_time", dtoMap.get("guessEtime").toString() + " 23:59:59"); - dtoMap.remove("guessEtime"); - } - if (ObjectUtil.isNotNull(dtoMap.get("gamestime"))) { - queryWrapper.ge("start_time", dtoMap.get("gamestime").toString() + " 00:00:00"); - dtoMap.remove("gamestime"); - } - - if (ObjectUtil.isNotNull(dtoMap.get("gameetime"))) { - queryWrapper.le("start_time", dtoMap.get("gameetime").toString() + " 23:59:59"); - dtoMap.remove("gameetime"); - } - - if (ObjectUtil.isNotNull(dtoMap.get("releaseStime"))) { - queryWrapper.ge("release_time", dtoMap.get("releaseStime").toString() + " 00:00:00"); - dtoMap.remove("releaseStime"); - } - - if (ObjectUtil.isNotNull(dtoMap.get("releaseEtime"))) { - queryWrapper.le("release_time", dtoMap.get("releaseEtime").toString() + " 23:59:59"); - dtoMap.remove("releaseEtime"); - } - // 封装所有分页信息 - if (ObjectUtil.isNotEmpty(dtoMap.get("page")) && ObjectUtil.isNotEmpty(dtoMap.get("pageSize"))) { - page.setCurrent(Long.valueOf(dtoMap.get("page").toString())); - page.setSize(Long.valueOf(dtoMap.get("pageSize").toString())); - queryWrapperAndPage.setPage(page); - dtoMap.remove("page"); - dtoMap.remove("pageSize"); - } - - // 封装所有查询条件信息 - for (Map.Entry map :dtoMap.entrySet()) { - if (ObjectUtil.isNotEmpty(map.getValue())){ - queryWrapper.eq(StringUtil.underscoreName(map.getKey()), map.getValue()); - } - } - - queryWrapperAndPage.setQueryWrapper(queryWrapper); - - return queryWrapperAndPage; - } - - /** - * 目前都是等值赋值。 需要的话在后续拓展 - * @param model - * @return - */ - public static QueryWrapper toQueryWrapper(Object model) { - - QueryWrapper queryWrapper = new QueryWrapper<>(); - - // 通过反射 赋值 - Field[] field = model.getClass().getDeclaredFields(); - try { - // 遍历所有属性 - for (int j = 0; j < field.length; j++) { - // 获取属性的名字 - String name = field[j].getName(); - // 将属性的首字符大写,方便构造get,set方法 - name = name.substring(0, 1).toUpperCase() + name.substring(1); - // 获取属性的类型 - String type = field[j].getGenericType().toString(); - // 如果type是类类型,则前面包含"class ",后面跟类名 - if ("class java.lang.String".equals(type)) { - Method m = model.getClass().getMethod("get" + name); - // 调用getter方法获取属性值 - String value = (String) m.invoke(model); - if (ObjectUtil.isNotEmpty(value)) { - queryWrapper.eq(name, value); - } - } - if ("class java.lang.Integer".equals(type)) { - Method m = model.getClass().getMethod("get" + name); - Integer value = (Integer) m.invoke(model); - - if (ObjectUtil.isNotEmpty(value)){ - queryWrapper.eq(name, value); - } - } - if ("class java.lang.Boolean".equals(type)) { - Method m = model.getClass().getMethod("get" + name); - Boolean value = (Boolean) m.invoke(model); - - if (ObjectUtil.isNotEmpty(value)){ - queryWrapper.eq(name, value); - } - } - if ("class java.util.Date".equals(type)) { - Method m = model.getClass().getMethod("get" + name); - Date value = (Date) m.invoke(model); - - if (ObjectUtil.isNotEmpty(value)){ - queryWrapper.eq(name, value); - } - } - - // 如果有需要,可以仿照上面继续进行扩充,再增加对其它类型的判断 - } - }catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (SecurityException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } - - return queryWrapper; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/TranslatorUtil.java b/wjcy-common/src/main/java/me/zhengjie/utils/TranslatorUtil.java deleted file mode 100644 index f2bd5d2..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/TranslatorUtil.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.utils; - -import cn.hutool.json.JSONArray; -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.net.HttpURLConnection; -import java.net.URL; -import java.net.URLEncoder; - -/** - * @author Zheng Jie - * 翻译工具类 - */ -public class TranslatorUtil { - - public static String translate(String word){ - try { - String url = "https://translate.googleapis.com/translate_a/single?" + - "client=gtx&" + - "sl=en" + - "&tl=zh-CN" + - "&dt=t&q=" + URLEncoder.encode(word, "UTF-8"); - - URL obj = new URL(url); - HttpURLConnection con = (HttpURLConnection) obj.openConnection(); - con.setRequestProperty("User-Agent", "Mozilla/5.0"); - - BufferedReader in = new BufferedReader( - new InputStreamReader(con.getInputStream())); - String inputLine; - StringBuilder response = new StringBuilder(); - - while ((inputLine = in.readLine()) != null) { - response.append(inputLine); - } - in.close(); - return parseResult(response.toString()); - }catch (Exception e){ - return word; - } - } - - private static String parseResult(String inputJson){ - JSONArray jsonArray2 = (JSONArray) new JSONArray(inputJson).get(0); - StringBuilder result = new StringBuilder(); - for (Object o : jsonArray2) { - result.append(((JSONArray) o).get(0).toString()); - } - return result.toString(); - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/ValidationUtil.java b/wjcy-common/src/main/java/me/zhengjie/utils/ValidationUtil.java deleted file mode 100644 index c2c81d2..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/ValidationUtil.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.utils; - -import cn.hutool.core.util.ObjectUtil; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.exception.BadRequestException; -import org.hibernate.validator.internal.constraintvalidators.hv.EmailValidator; - -import java.lang.reflect.Field; - -/** - * 验证工具 - * @author Zheng Jie - * @date 2018-11-23 - */ -@Slf4j -public class ValidationUtil{ - - /** - * 验证空 - */ - public static void isNull(Object obj, String entity, String parameter , Object value){ - if(ObjectUtil.isNull(obj)){ - String msg = entity + " 不存在: "+ parameter +" is "+ value; - throw new BadRequestException(msg); - } - } - - /** - * 验证是否为邮箱 - */ - public static boolean isEmail(String email) { - return new EmailValidator().isValid(email, null); - } - - - /** - * 反射检验对象是否包含指定名称的 变量 - * @param fieldName - * @param obj - * @return - */ - public static Boolean isExistFieldName(String fieldName, Object obj) { - if (obj == null || StringUtils.isEmpty(fieldName)) { - return false; - } - //获取这个类的所有属性 - Field[] fields = obj.getClass().getDeclaredFields(); - //循环遍历所有的fields - for (int i = 0; i < fields.length; i++) { - if (fields[i].getName().equals(fieldName)) { - return true; - } - } - return false; - } - -// /** -// * 判断是否包含 passType -// * @param mqSettlePassCurrencyTypeList -// * @param passType -// * @return -// */ -// public static Boolean isContainPassType(List mqSettlePassCurrencyTypeList, Integer passType) { -// if (ObjectUtil.isEmpty(mqSettlePassCurrencyTypeList) || ObjectUtil.isEmpty(passType)) { -// log.error("---isContainPassType------mqSettlePassCurrencyTypeList-------null"); -// return false; -// } -// List list = mqSettlePassCurrencyTypeList.stream().filter(l->l.getPassType().equals(passType)).collect(Collectors.toList()); -// if (ObjectUtil.isNotEmpty(list)) { -// return true; -// } -// -// log.error("---isContainPassType------mqSettlePassCurrencyTypeList----return---null"); -// return false; -// } -// -// /** -// * 判断是否包含 passType 中的currencyType -// * @param mqSettlePassCurrencyTypeList -// * @param passType -// * @param currencyType -// * @return -// */ -// public static Boolean isContainPassCurrencyType(List mqSettlePassCurrencyTypeList, Integer passType, Integer currencyType) { -// if (ObjectUtil.isEmpty(mqSettlePassCurrencyTypeList) || ObjectUtil.isEmpty(passType) || ObjectUtil.isEmpty(currencyType)) { -// log.error("---isContainPassCurrencyType------mqSettlePassCurrencyTypeList-------null"); -// return false; -// } -// -// List list = mqSettlePassCurrencyTypeList.stream().filter(l->l.getPassType().equals(passType)).collect(Collectors.toList()); -// if (ObjectUtil.isEmpty(list)) { -// log.error("---isContainPassCurrencyType------List----return---false"); -// return false; -// } -// -// for (MqSettlePassCurrencyType mqSettlePassCurrencyType:list) { -// List currencyTypeList = mqSettlePassCurrencyType.getCurrencyList(); -// if (ObjectUtil.isEmpty(currencyTypeList)) { -// continue; -// } -// -// List currencyList = currencyTypeList.stream().filter(c->c.getCurrencyType().equals(currencyType)).collect(Collectors.toList()); -// if (ObjectUtil.isNotEmpty(currencyList)) { -// return true; -// } -// } -// -// log.error("---isContainPassCurrencyType------mqSettlePassCurrencyTypeList----return---false"); -// return false; -// } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/YdCallBackUtil.java b/wjcy-common/src/main/java/me/zhengjie/utils/YdCallBackUtil.java deleted file mode 100644 index 6a6b29f..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/YdCallBackUtil.java +++ /dev/null @@ -1,89 +0,0 @@ -package me.zhengjie.utils; - -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.json.JSONObject; -import cn.hutool.json.JSONUtil; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.config.BeanFactory; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.CtApply; -import me.zhengjie.entity.CtRebot; -import me.zhengjie.entity.ReturnObje; -import me.zhengjie.entity.YdSign; -import me.zhengjie.enums.YesOrNoEnum; -import me.zhengjie.error.ErrorCodeEnum; -import me.zhengjie.service.CtRebotService; -import org.springframework.transaction.annotation.Transactional; - -import javax.servlet.http.HttpServletRequest; -import java.util.Map; - -/** - * 影刀回调 - * - * @author rch - * @create 2022-08-23 - */ -@Slf4j -public class YdCallBackUtil { - - @Transactional(rollbackFor = Exception.class) - public Dto callback(HttpServletRequest httpServletRequest, CtApply ctApply, String data){ - log.info("=======影刀回调=======callback"); - String requestUrl = httpServletRequest.getRequestURI(); - Map map = httpServletRequest.getParameterMap(); - if (ObjectUtil.isEmpty(map.get("sign"))) { - return Dto.getInstance(ErrorCodeEnum.ERROR_PARAM_NULL); - } - - String getSign = map.get("sign")[0]; - JSONObject jsonObject = JSONUtil.parseObj(data); - - // 根据task枚举获取 应用信息 取出 accessKey 和 accessKeySecret 用于鉴权 - if (ObjectUtil.isEmpty(ctApply) || ObjectUtil.isEmpty(getSign) - || ObjectUtil.isEmpty(jsonObject) - || ObjectUtil.isEmpty(ctApply.getAccessKeyId()) - || ObjectUtil.isEmpty(ctApply.getAccessKeySecret())) { - return Dto.getInstance(ErrorCodeEnum.ERROR_PARAM_NULL); - } - - String accessKeyId = ctApply.getAccessKeyId(); - String accessKeySecret = ctApply.getAccessKeySecret(); - - // 鉴权 - YdSign ydSign = new YdSign(); - ydSign.setTimestamp(Long.valueOf(map.get("timestamp")[0])); - ydSign.setAccessKeyId(accessKeyId); - ydSign.setAccessKeySecret(accessKeySecret); - ydSign.setBodyMd5(map.get("bodyMd5")[0]); - - log.info("-------map:{}" , JSONUtil.toJsonStr(map)); - log.info("====ydSign====={}", JSONUtil.toJsonStr(ydSign)); - String sign = YdSignUtil.getSign(ydSign); - log.info("====sign:{} ---getSign:{}", sign, getSign); - if (ObjectUtil.isEmpty(sign) || !getSign.equals(sign)) { - return Dto.getInstance(ErrorCodeEnum.ERROR_CALLBACK_SIGN_NULL); - } - - // TODO 获取设备id 然后修改设备状态是未占用 - CtRebotService ctRebotService = BeanFactory.getBean(CtRebotService.class); - ReturnObje returnObje = JSONUtil.toBean(data, ReturnObje.class); - String rebotClientName = returnObje.getRobotClientName(); - CtRebot ctRebot = ctRebotService.getByAccountNameLock(rebotClientName); - if (ObjectUtil.isEmpty(ctRebot)) { - // 有问题 不执行 - System.out.println("===========设备有问题==========="); - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_OR_OCCUPY); - } - if (YesOrNoEnum.NO.eqValue(ctRebot.getStatus())) { - return Dto.returnResult(true); - } - - // 修改机器人状态 不管是什么状态,执行完成之后在我们平台就是修改为 待占用即可 - CtRebot updateCtRebot = new CtRebot(); - updateCtRebot.setId(ctRebot.getId()); - updateCtRebot.setStatus(YesOrNoEnum.NO.value()); - Boolean resultBoolean = ctRebotService.updateById(updateCtRebot); - return Dto.returnResult(resultBoolean); - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/YdParamsCheck.java b/wjcy-common/src/main/java/me/zhengjie/utils/YdParamsCheck.java deleted file mode 100644 index b69eea3..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/YdParamsCheck.java +++ /dev/null @@ -1,54 +0,0 @@ -package me.zhengjie.utils; - -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.json.JSONUtil; -import me.zhengjie.entity.quartz.Boss; -import me.zhengjie.entity.quartz.Param; - -import java.util.List; - -/** - * 检验影刀参数是否是json数组格式 - * - * @author rch - * @create 2022-08-17 - */ -public class YdParamsCheck { - - /** - * params 是json格式则返回true 否则返回false - * @param str - * @return - */ - public static Boolean paramIsJson(String str) { - - if (ObjectUtil.isEmpty(str)) { - return false; - } - - if (!JSONUtil.isJson(str)) { - return false; - } - - Boss boss = JSONUtil.toBean(str, Boss.class); - if (ObjectUtil.isEmpty(boss) || ObjectUtil.isEmpty(boss.getParams())) { - return false; - } - - List paramList = boss.getParams(); - for (Param param:paramList) { - if (ObjectUtil.isEmpty(param)) { - return false; - } - } - - return true; - } - - public static void main(String[] args) { - String str = "{\"accountName\":\"linbiaoyuan@vogocm\",\"applyId\":2,\"params\":1}"; - str = "{\"accountName\":\"linbiaoyuan@vogocm\",\"applyId\":2,\"params\":[{\"name\":\"id\",\"value\":\"1\",\"type\":\"str\"}]}"; - Boolean boolean1 = paramIsJson(str); - System.out.println("==========boolean1:" + boolean1); - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/YdSignUtil.java b/wjcy-common/src/main/java/me/zhengjie/utils/YdSignUtil.java deleted file mode 100644 index 7acc18d..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/YdSignUtil.java +++ /dev/null @@ -1,94 +0,0 @@ -package me.zhengjie.utils; - -import cn.hutool.core.util.ObjectUtil; -import me.zhengjie.entity.YdSign; - -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; -import java.nio.charset.Charset; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.time.format.DateTimeFormatter; -import java.util.Date; - -/** - * 影刀鉴权工具类 - * - * @author rch - * @create 2022-07-26 - */ -public class YdSignUtil { - - private static final char[] DIGITS_LOWER = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};; - - private static final String UTF8_NAME = "UTF-8"; - - private static final Charset UTF8_CHARSET = Charset.forName(UTF8_NAME); - - - public static String getSign(YdSign ydSign) { - String sign = null; - if (ObjectUtil.isEmpty(ydSign) - || ObjectUtil.isEmpty(ydSign.getAccessKeyId()) - || ObjectUtil.isEmpty(ydSign.getTimestamp()) - || ObjectUtil.isEmpty(ydSign.getBodyMd5()) - || ObjectUtil.isEmpty(ydSign.getAccessKeySecret())) { - return sign; - } - - //由回调接口回传 - long timestamp = ydSign.getTimestamp(); - //影刀控制台配置的accessKeyId - String accessKeyId = ydSign.getAccessKeyId(); - //影刀控制台配置的accessKeySecret - String accessKeySecret = ydSign.getAccessKeySecret(); - //由回调接口回传 - String bodyMd5 = ydSign.getBodyMd5(); - DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - Date date = new Date(timestamp); - LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()); - - System.out.println(bodyMd5); - StringBuilder sb = new StringBuilder(); - sb.append("accessKeyId="); - sb.append(accessKeyId); - sb.append("&bodyMd5="); - sb.append(bodyMd5); - sb.append("×tamp="); - sb.append(pattern.format(localDateTime)); - - String originalStr = sb.toString(); - byte[] keyBytes = accessKeySecret.getBytes(); - SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "HmacSHA1"); - try { - Mac mac = Mac.getInstance("HmacSHA1"); - mac.init(secretKey); - byte[] rawHmac = mac.doFinal(originalStr.getBytes(UTF8_CHARSET)); - sign = encodeHex(rawHmac); - System.out.println("sign: " + sign); - } catch (Exception e) { - e.printStackTrace(); - return sign; - } - - return sign; - } - - /** - * 转换16进制 - * - * @param data - * @return - */ - private static String encodeHex(byte[] data) { - int l = data.length; - char[] out = new char[l << 1]; - int i = 0; - - for(int var5 = 0; i < l; ++i) { - out[var5++] = DIGITS_LOWER[(240 & data[i]) >>> 4]; - out[var5++] = DIGITS_LOWER[15 & data[i]]; - } - return new String(out); - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/enums/CodeBiEnum.java b/wjcy-common/src/main/java/me/zhengjie/utils/enums/CodeBiEnum.java deleted file mode 100644 index 661e0a0..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/enums/CodeBiEnum.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.utils.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - *

- * 验证码业务场景 - *

- * @author Zheng Jie - * @date 2020-05-02 - */ -@Getter -@AllArgsConstructor -public enum CodeBiEnum { - - /* 旧邮箱修改邮箱 */ - ONE(1, "旧邮箱修改邮箱"), - - /* 通过邮箱修改密码 */ - TWO(2, "通过邮箱修改密码"); - - private final Integer code; - private final String description; - - public static CodeBiEnum find(Integer code) { - for (CodeBiEnum value : CodeBiEnum.values()) { - if (code.equals(value.getCode())) { - return value; - } - } - return null; - } - -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/enums/CodeEnum.java b/wjcy-common/src/main/java/me/zhengjie/utils/enums/CodeEnum.java deleted file mode 100644 index 916862a..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/enums/CodeEnum.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.utils.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - *

- * 验证码业务场景对应的 Redis 中的 key - *

- * @author Zheng Jie - * @date 2020-05-02 - */ -@Getter -@AllArgsConstructor -public enum CodeEnum { - - /* 通过手机号码重置邮箱 */ - PHONE_RESET_EMAIL_CODE("phone_reset_email_code_", "通过手机号码重置邮箱"), - - /* 通过旧邮箱重置邮箱 */ - EMAIL_RESET_EMAIL_CODE("email_reset_email_code_", "通过旧邮箱重置邮箱"), - - /* 通过手机号码重置密码 */ - PHONE_RESET_PWD_CODE("phone_reset_pwd_code_", "通过手机号码重置密码"), - - /* 通过邮箱重置密码 */ - EMAIL_RESET_PWD_CODE("email_reset_pwd_code_", "通过邮箱重置密码"); - - private final String key; - private final String description; -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/enums/DataScopeEnum.java b/wjcy-common/src/main/java/me/zhengjie/utils/enums/DataScopeEnum.java deleted file mode 100644 index 5352b7b..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/enums/DataScopeEnum.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.utils.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - *

- * 数据权限枚举 - *

- * @author Zheng Jie - * @date 2020-05-07 - */ -@Getter -@AllArgsConstructor -public enum DataScopeEnum { - - /* 全部的数据权限 */ - ALL("全部", "全部的数据权限"), - - /* 自己部门的数据权限 */ - THIS_LEVEL("本级", "自己部门的数据权限"), - - /* 自定义的数据权限 */ - CUSTOMIZE("自定义", "自定义的数据权限"); - - private final String value; - private final String description; - - public static DataScopeEnum find(String val) { - for (DataScopeEnum dataScopeEnum : DataScopeEnum.values()) { - if (val.equals(dataScopeEnum.getValue())) { - return dataScopeEnum; - } - } - return null; - } - -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/enums/RequestMethodEnum.java b/wjcy-common/src/main/java/me/zhengjie/utils/enums/RequestMethodEnum.java deleted file mode 100644 index 1b65c78..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/enums/RequestMethodEnum.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.utils.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * @author Zheng Jie - * @website https://el-admin.vip - * @description - * @date 2020-06-10 - **/ -@Getter -@AllArgsConstructor -public enum RequestMethodEnum { - - /** - * 搜寻 @AnonymousGetMapping - */ - GET("GET"), - - /** - * 搜寻 @AnonymousPostMapping - */ - POST("POST"), - - /** - * 搜寻 @AnonymousPutMapping - */ - PUT("PUT"), - - /** - * 搜寻 @AnonymousPatchMapping - */ - PATCH("PATCH"), - - /** - * 搜寻 @AnonymousDeleteMapping - */ - DELETE("DELETE"), - - /** - * 否则就是所有 Request 接口都放行 - */ - ALL("All"); - - /** - * Request 类型 - */ - private final String type; - - public static RequestMethodEnum find(String type) { - for (RequestMethodEnum value : RequestMethodEnum.values()) { - if (type.equals(value.getType())) { - return value; - } - } - return ALL; - } -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/excel/ExcelClassField.java b/wjcy-common/src/main/java/me/zhengjie/utils/excel/ExcelClassField.java deleted file mode 100644 index 2107f6e..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/excel/ExcelClassField.java +++ /dev/null @@ -1,79 +0,0 @@ -package me.zhengjie.utils.excel; - -import java.util.LinkedHashMap; - -/** - * ExcelClassField - * - * @author rch - * @create 2022-06-22 - */ -public class ExcelClassField { - - /** 字段名称 */ - private String fieldName; - - /** 表头名称 */ - private String name; - - /** 映射关系 */ - private LinkedHashMap kvMap; - - /** 示例值 */ - private Object example; - - /** 排序 */ - private int sort; - - /** 是否为注解字段:0-否,1-是 */ - private int hasAnnotation; - - public String getFieldName() { - return fieldName; - } - - public void setFieldName(String fieldName) { - this.fieldName = fieldName; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public LinkedHashMap getKvMap() { - return kvMap; - } - - public void setKvMap(LinkedHashMap kvMap) { - this.kvMap = kvMap; - } - - public Object getExample() { - return example; - } - - public void setExample(Object example) { - this.example = example; - } - - public int getSort() { - return sort; - } - - public void setSort(int sort) { - this.sort = sort; - } - - public int getHasAnnotation() { - return hasAnnotation; - } - - public void setHasAnnotation(int hasAnnotation) { - this.hasAnnotation = hasAnnotation; - } - -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/excel/ExcelExport.java b/wjcy-common/src/main/java/me/zhengjie/utils/excel/ExcelExport.java deleted file mode 100644 index 706d95b..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/excel/ExcelExport.java +++ /dev/null @@ -1,30 +0,0 @@ -package me.zhengjie.utils.excel; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * ExcelExport - * - * @author rch - * @create 2022-06-22 - */ -@Target(ElementType.FIELD) -@Retention(RetentionPolicy.RUNTIME) -public @interface ExcelExport { - - /** 字段名称 */ - String value(); - - /** 导出排序先后: 数字越小越靠前(默认按Java类字段顺序导出) */ - int sort() default 0; - - /** 导出映射,格式如:0-未知;1-男;2-女 */ - String kv() default ""; - - /** 导出模板示例值(有值的话,直接取该值,不做映射) */ - String example() default ""; - -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/excel/ExcelImport.java b/wjcy-common/src/main/java/me/zhengjie/utils/excel/ExcelImport.java deleted file mode 100644 index 5110dad..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/excel/ExcelImport.java +++ /dev/null @@ -1,34 +0,0 @@ -package me.zhengjie.utils.excel; - - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * ExcelImport - * - * @author rch - * @create 2022-06-22 - */ -@Target(ElementType.FIELD) -@Retention(RetentionPolicy.RUNTIME) -public @interface ExcelImport { - - /** 字段名称 */ - String value(); - - /** 导出映射,格式如:0-未知;1-男;2-女 */ - String kv() default ""; - - /** 是否为必填字段(默认为非必填) */ - boolean required() default false; - - /** 最大长度(默认255) */ - int maxLength() default 255; - - /** 导入唯一性验证(多个字段则取联合验证) */ - boolean unique() default false; - -} diff --git a/wjcy-common/src/main/java/me/zhengjie/utils/excel/ExcelUtils.java b/wjcy-common/src/main/java/me/zhengjie/utils/excel/ExcelUtils.java deleted file mode 100644 index 59b1998..0000000 --- a/wjcy-common/src/main/java/me/zhengjie/utils/excel/ExcelUtils.java +++ /dev/null @@ -1,993 +0,0 @@ -package me.zhengjie.utils.excel; - -import cn.hutool.core.util.ObjectUtil; -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import org.apache.poi.hssf.usermodel.HSSFDataValidation; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; -import org.apache.poi.ss.usermodel.*; -import org.apache.poi.ss.usermodel.ClientAnchor.AnchorType; -import org.apache.poi.ss.util.CellRangeAddress; -import org.apache.poi.ss.util.CellRangeAddressList; -import org.apache.poi.xssf.streaming.SXSSFWorkbook; -import org.apache.poi.xssf.usermodel.XSSFClientAnchor; -import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import org.springframework.web.multipart.MultipartFile; - -import javax.servlet.ServletOutputStream; -import javax.servlet.http.HttpServletResponse; -import java.io.*; -import java.lang.reflect.Field; -import java.math.BigDecimal; -import java.math.RoundingMode; -import java.net.URL; -import java.text.NumberFormat; -import java.text.SimpleDateFormat; -import java.util.*; -import java.util.Map.Entry; -import java.util.regex.Pattern; - -/** - * Excel导入导出工具类 - * - * @author rch - * @create 2022-06-22 - */ -public class ExcelUtils { - private static final String XLSX = ".xlsx"; - private static final String XLS = ".xls"; - public static final String ROW_MERGE = "row_merge"; - public static final String COLUMN_MERGE = "column_merge"; - private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; - private static final String ROW_NUM = "rowNum"; - private static final String ROW_DATA = "rowData"; - private static final String ROW_TIPS = "rowTips"; - private static final int CELL_OTHER = 0; - private static final int CELL_ROW_MERGE = 1; - private static final int CELL_COLUMN_MERGE = 2; - private static final int IMG_HEIGHT = 30; - private static final int IMG_WIDTH = 30; - private static final char LEAN_LINE = '/'; - private static final int BYTES_DEFAULT_LENGTH = 10240; - private static final NumberFormat NUMBER_FORMAT = NumberFormat.getNumberInstance(); - - - public static List readFile(File file, Class clazz) throws Exception { - JSONArray array = readFile(file); - return getBeanList(array, clazz); - } - - public static List readMultipartFile(MultipartFile mFile, Class clazz) throws Exception { - JSONArray array = readMultipartFile(mFile); - return getBeanList(array, clazz); - } - - public static JSONArray readFile(File file) throws Exception { - return readExcel(null, file); - } - - public static JSONArray readMultipartFile(MultipartFile mFile) throws Exception { - return readExcel(mFile, null); - } - - public static Map readFileManySheet(File file) throws Exception { - return readExcelManySheet(null, file); - } - - public static Map readFileManySheet(MultipartFile file) throws Exception { - return readExcelManySheet(file, null); - } - - private static List getBeanList(JSONArray array, Class clazz) throws Exception { - List list = new ArrayList<>(); - Map uniqueMap = new HashMap<>(16); - for (int i = 0; i < array.size(); i++) { - list.add(getBean(clazz, array.getJSONObject(i), uniqueMap)); - } - return list; - } - - /** - * 获取每个对象的数据 - */ - private static T getBean(Class c, JSONObject obj, Map uniqueMap) throws Exception { - T t = c.newInstance(); - Field[] fields = c.getDeclaredFields(); - List errMsgList = new ArrayList<>(); - boolean hasRowTipsField = false; - StringBuilder uniqueBuilder = new StringBuilder(); - int rowNum = 0; - for (Field field : fields) { - // 行号 - if (field.getName().equals(ROW_NUM)) { - rowNum = obj.getInteger(ROW_NUM); - field.setAccessible(true); - field.set(t, rowNum); - continue; - } - // 是否需要设置异常信息 - if (field.getName().equals(ROW_TIPS)) { - hasRowTipsField = true; - continue; - } - // 原始数据 - if (field.getName().equals(ROW_DATA)) { - field.setAccessible(true); - field.set(t, obj.toString()); - continue; - } - // 设置对应属性值 - setFieldValue(t, field, obj, uniqueBuilder, errMsgList); - } - // 数据唯一性校验 - if (uniqueBuilder.length() > 0) { - if (uniqueMap.containsValue(uniqueBuilder.toString())) { - Set rowNumKeys = uniqueMap.keySet(); - for (Integer num : rowNumKeys) { - if (uniqueMap.get(num).equals(uniqueBuilder.toString())) { - errMsgList.add(String.format("数据唯一性校验失败,(%s)与第%s行重复)", uniqueBuilder, num)); - } - } - } else { - uniqueMap.put(rowNum, uniqueBuilder.toString()); - } - } - // 失败处理 - if (errMsgList.isEmpty() && !hasRowTipsField) { - return t; - } - StringBuilder sb = new StringBuilder(); - int size = errMsgList.size(); - for (int i = 0; i < size; i++) { - if (i == size - 1) { - sb.append(errMsgList.get(i)); - } else { - sb.append(errMsgList.get(i)).append(";"); - } - } - // 设置错误信息 - for (Field field : fields) { - if (field.getName().equals(ROW_TIPS)) { - field.setAccessible(true); - field.set(t, sb.toString()); - } - } - return t; - } - - private static void setFieldValue(T t, Field field, JSONObject obj, StringBuilder uniqueBuilder, List errMsgList) { - // 获取 ExcelImport 注解属性 - ExcelImport annotation = field.getAnnotation(ExcelImport.class); - if (annotation == null) { - return; - } - String cname = annotation.value(); - if (cname.trim().length() == 0) { - return; - } - // 获取具体值 - String val = null; - if (obj.containsKey(cname)) { - val = getString(obj.getString(cname)); - } - if (val == null) { - return; - } - field.setAccessible(true); - // 判断是否必填 - boolean require = annotation.required(); - if (require && val.isEmpty()) { - errMsgList.add(String.format("[%s]不能为空", cname)); - return; - } - // 数据唯一性获取 - boolean unique = annotation.unique(); - if (unique) { - if (uniqueBuilder.length() > 0) { - uniqueBuilder.append("--").append(val); - } else { - uniqueBuilder.append(val); - } - } - // 判断是否超过最大长度 - int maxLength = annotation.maxLength(); - if (maxLength > 0 && val.length() > maxLength) { - errMsgList.add(String.format("[%s]长度不能超过%s个字符(当前%s个字符)", cname, maxLength, val.length())); - } - // 判断当前属性是否有映射关系 - LinkedHashMap kvMap = getKvMap(annotation.kv()); - if (!kvMap.isEmpty()) { - boolean isMatch = false; - for (String key : kvMap.keySet()) { - if (kvMap.get(key).equals(val)) { - val = key; - isMatch = true; - break; - } - } - if (!isMatch) { - errMsgList.add(String.format("[%s]的值不正确(当前值为%s)", cname, val)); - return; - } - } - // 其余情况根据类型赋值 - String fieldClassName = field.getType().getSimpleName(); - try { - if ("String".equalsIgnoreCase(fieldClassName)) { - field.set(t, val); - } else if ("boolean".equalsIgnoreCase(fieldClassName)) { - field.set(t, Boolean.valueOf(val)); - } else if ("int".equalsIgnoreCase(fieldClassName) || "Integer".equals(fieldClassName)) { - try { - field.set(t, Integer.valueOf(val)); - } catch (NumberFormatException e) { - errMsgList.add(String.format("[%s]的值格式不正确(当前值为%s)", cname, val)); - } - } else if ("double".equalsIgnoreCase(fieldClassName)) { - field.set(t, Double.valueOf(val)); - } else if ("long".equalsIgnoreCase(fieldClassName)) { - field.set(t, Long.valueOf(val)); - } else if ("BigDecimal".equalsIgnoreCase(fieldClassName)) { - field.set(t, new BigDecimal(val)); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - private static Map readExcelManySheet(MultipartFile mFile, File file) throws IOException { - Workbook book = getWorkbook(mFile, file); - if (book == null) { - return Collections.emptyMap(); - } - Map map = new LinkedHashMap<>(); - for (int i = 0; i < book.getNumberOfSheets(); i++) { - Sheet sheet = book.getSheetAt(i); - JSONArray arr = readSheet(sheet); - map.put(sheet.getSheetName(), arr); - } - book.close(); - return map; - } - - private static JSONArray readExcel(MultipartFile mFile, File file) throws IOException { - Workbook book = getWorkbook(mFile, file); - if (book == null) { - return new JSONArray(); - } - JSONArray array = readSheet(book.getSheetAt(0)); - book.close(); - return array; - } - - private static Workbook getWorkbook(MultipartFile mFile, File file) throws IOException { - boolean fileNotExist = (file == null || !file.exists()); - if (mFile == null && fileNotExist) { - return null; - } - // 解析表格数据 - InputStream in; - String fileName; - if (mFile != null) { - // 上传文件解析 - in = mFile.getInputStream(); - fileName = getString(mFile.getOriginalFilename()).toLowerCase(); - } else { - // 本地文件解析 - in = new FileInputStream(file); - fileName = file.getName().toLowerCase(); - } - Workbook book; - if (fileName.endsWith(XLSX)) { - book = new XSSFWorkbook(in); - } else if (fileName.endsWith(XLS)) { - POIFSFileSystem poifsFileSystem = new POIFSFileSystem(in); - book = new HSSFWorkbook(poifsFileSystem); - } else { - return null; - } - in.close(); - return book; - } - - private static JSONArray readSheet(Sheet sheet) { - // 首行下标 - int rowStart = sheet.getFirstRowNum(); - // 尾行下标 - int rowEnd = sheet.getLastRowNum(); - // 获取表头行 - Row headRow = sheet.getRow(rowStart); - if (headRow == null) { - return new JSONArray(); - } - int cellStart = headRow.getFirstCellNum(); - int cellEnd = headRow.getLastCellNum(); - Map keyMap = new HashMap<>(16); - for (int j = cellStart; j < cellEnd; j++) { - // 获取表头数据 - String val = getCellValue(headRow.getCell(j)); - if (val != null && val.trim().length() != 0) { - keyMap.put(j, val); - } - } - // 如果表头没有数据则不进行解析 - if (keyMap.isEmpty()) { - return (JSONArray) Collections.emptyList(); - } - // 获取每行JSON对象的值 - JSONArray array = new JSONArray(); - // 如果首行与尾行相同,表明只有一行,返回表头数据 - if (rowStart == rowEnd) { - JSONObject obj = new JSONObject(); - // 添加行号 - obj.put(ROW_NUM, 1); - for (int i : keyMap.keySet()) { - obj.put(keyMap.get(i), ""); - } - array.add(obj); - return array; - } - for (int i = rowStart + 1; i <= rowEnd; i++) { - Row eachRow = sheet.getRow(i); - JSONObject obj = new JSONObject(); - // 添加行号 - obj.put(ROW_NUM, i + 1); - StringBuilder sb = new StringBuilder(); - for (int k = cellStart; k < cellEnd; k++) { - if (eachRow != null) { - String val = getCellValue(eachRow.getCell(k)); - // 所有数据添加到里面,用于判断该行是否为空 - sb.append(val); - obj.put(keyMap.get(k), val); - } - } - if (sb.length() > 0) { - array.add(obj); - } - } - return array; - } - - private static String getCellValue(Cell cell) { - // 空白或空 - if (cell == null || cell.getCellTypeEnum() == CellType.BLANK) { - return ""; - } - // String类型 - if (cell.getCellTypeEnum() == CellType.STRING) { - String val = cell.getStringCellValue(); - if (val == null || val.trim().length() == 0) { - return ""; - } - return val.trim(); - } - // 数字类型 - if (cell.getCellTypeEnum() == CellType.NUMERIC) { - String s = cell.getNumericCellValue() + ""; - // 去掉尾巴上的小数点0 - if (Pattern.matches(".*\\.0*", s)) { - return s.split("\\.")[0]; - } else { - return s; - } - } - // 布尔值类型 - if (cell.getCellTypeEnum() == CellType.BOOLEAN) { - return cell.getBooleanCellValue() + ""; - } - // 错误类型 - return cell.getCellFormula(); - } - - public static void exportTemplate(HttpServletResponse response, String fileName, Class clazz) { - exportTemplate(response, fileName, fileName, clazz, false); - } - - public static void exportTemplate(HttpServletResponse response, String fileName, String sheetName, - Class clazz) { - exportTemplate(response, fileName, sheetName, clazz, false); - } - - public static void exportTemplate(HttpServletResponse response, String fileName, Class clazz, - boolean isContainExample) { - exportTemplate(response, fileName, fileName, clazz, isContainExample); - } - - public static void exportTemplate(HttpServletResponse response, String fileName, String sheetName, - Class clazz, boolean isContainExample) { - // 获取表头字段 - List headFieldList = getExcelClassFieldList(clazz); - // 获取表头数据和示例数据 - List> sheetDataList = new ArrayList<>(); - List headList = new ArrayList<>(); - List exampleList = new ArrayList<>(); - Map> selectMap = new LinkedHashMap<>(); - for (int i = 0; i < headFieldList.size(); i++) { - ExcelClassField each = headFieldList.get(i); - headList.add(each.getName()); - exampleList.add(each.getExample()); - LinkedHashMap kvMap = each.getKvMap(); - if (kvMap != null && kvMap.size() > 0) { - selectMap.put(i, new ArrayList<>(kvMap.values())); - } - } - sheetDataList.add(headList); - if (isContainExample) { - sheetDataList.add(exampleList); - } - // 导出数据 - export(response, fileName, sheetName, sheetDataList, selectMap); - } - - private static List getExcelClassFieldList(Class clazz) { - // 解析所有字段 - Field[] fields = clazz.getDeclaredFields(); - boolean hasExportAnnotation = false; - Map> map = new LinkedHashMap<>(); - List sortList = new ArrayList<>(); - for (Field field : fields) { - ExcelClassField cf = getExcelClassField(field); - if (cf.getHasAnnotation() == 1) { - hasExportAnnotation = true; - } - int sort = cf.getSort(); - if (map.containsKey(sort)) { - map.get(sort).add(cf); - } else { - List list = new ArrayList<>(); - list.add(cf); - sortList.add(sort); - map.put(sort, list); - } - } - Collections.sort(sortList); - // 获取表头 - List headFieldList = new ArrayList<>(); - if (hasExportAnnotation) { - for (Integer sort : sortList) { - for (ExcelClassField cf : map.get(sort)) { - if (cf.getHasAnnotation() == 1) { - headFieldList.add(cf); - } - } - } - } else { - headFieldList.addAll(map.get(0)); - } - return headFieldList; - } - - private static ExcelClassField getExcelClassField(Field field) { - ExcelClassField cf = new ExcelClassField(); - String fieldName = field.getName(); - cf.setFieldName(fieldName); - ExcelExport annotation = field.getAnnotation(ExcelExport.class); - // 无 ExcelExport 注解情况 - if (annotation == null) { - cf.setHasAnnotation(0); - cf.setName(fieldName); - cf.setSort(0); - return cf; - } - // 有 ExcelExport 注解情况 - cf.setHasAnnotation(1); - cf.setName(annotation.value()); - String example = getString(annotation.example()); - if (!example.isEmpty()) { - if (isNumeric(example)) { - cf.setExample(Double.valueOf(example)); - } else { - cf.setExample(example); - } - } else { - cf.setExample(""); - } - cf.setSort(annotation.sort()); - // 解析映射 - String kv = getString(annotation.kv()); - cf.setKvMap(getKvMap(kv)); - return cf; - } - - private static LinkedHashMap getKvMap(String kv) { - LinkedHashMap kvMap = new LinkedHashMap<>(); - if (kv.isEmpty()) { - return kvMap; - } - String[] kvs = kv.split(";"); - if (kvs.length == 0) { - return kvMap; - } - for (String each : kvs) { - String[] eachKv = getString(each).split("-"); - if (eachKv.length != 2) { - continue; - } - String k = eachKv[0]; - String v = eachKv[1]; - if (k.isEmpty() || v.isEmpty()) { - continue; - } - kvMap.put(k, v); - } - return kvMap; - } - - /** - * 导出表格到本地 - * - * @param file 本地文件对象 - * @param sheetData 导出数据 - */ - public static void exportFile(File file, List> sheetData) { - if (file == null) { - System.out.println("文件创建失败"); - return; - } - if (sheetData == null) { - sheetData = new ArrayList<>(); - } - Map>> map = new HashMap<>(16); - map.put(file.getName(), sheetData); - export(null, file, file.getName(), map, null); - } - - /** - * 导出表格到本地 - * - * @param 导出数据类似,和K类型保持一致 - * @param filePath 文件父路径(如:D:/doc/excel/) - * @param fileName 文件名称(不带尾缀,如:学生表) - * @param list 导出数据 - * @throws IOException IO异常 - */ - public static File exportFile(String filePath, String fileName, List list) throws IOException { - File file = getFile(filePath, fileName); - List> sheetData = getSheetData(list); - exportFile(file, sheetData); - return file; - } - - /** - * 获取文件 - * - * @param filePath filePath 文件父路径(如:D:/doc/excel/) - * @param fileName 文件名称(不带尾缀,如:用户表) - * @return 本地File文件对象 - */ - private static File getFile(String filePath, String fileName) throws IOException { - String dirPath = getString(filePath); - String fileFullPath; - if (dirPath.isEmpty()) { - fileFullPath = fileName; - } else { - // 判定文件夹是否存在,如果不存在,则级联创建 - File dirFile = new File(dirPath); - if (!dirFile.exists()) { - dirFile.mkdirs(); - } - // 获取文件夹全名 - if (dirPath.endsWith(String.valueOf(LEAN_LINE))) { - fileFullPath = dirPath + fileName + XLSX; - } else { - fileFullPath = dirPath + LEAN_LINE + fileName + XLSX; - } - } - System.out.println(fileFullPath); - File file = new File(fileFullPath); - if (!file.exists()) { - file.createNewFile(); - } - return file; - } - - private static List> getSheetData(List list) { - // 获取表头字段 - List excelClassFieldList = getExcelClassFieldList(list.get(0).getClass()); - List headFieldList = new ArrayList<>(); - List headList = new ArrayList<>(); - Map headFieldMap = new HashMap<>(16); - for (ExcelClassField each : excelClassFieldList) { - String fieldName = each.getFieldName(); - headFieldList.add(fieldName); - headFieldMap.put(fieldName, each); - headList.add(each.getName()); - } - // 添加表头名称 - List> sheetDataList = new ArrayList<>(); - sheetDataList.add(headList); - // 获取表数据 - for (T t : list) { - Map fieldDataMap = getFieldDataMap(t); - Set fieldDataKeys = fieldDataMap.keySet(); - List rowList = new ArrayList<>(); - for (String headField : headFieldList) { - if (!fieldDataKeys.contains(headField)) { - continue; - } - Object data = fieldDataMap.get(headField); - if (data == null) { - rowList.add(""); - continue; - } - ExcelClassField cf = headFieldMap.get(headField); - // 判断是否有映射关系 - LinkedHashMap kvMap = cf.getKvMap(); - if (kvMap == null || kvMap.isEmpty()) { - rowList.add(data); - continue; - } - String val = kvMap.get(data.toString()); - if (isNumeric(val)) { - rowList.add(Double.valueOf(val)); - } else { - rowList.add(val); - } - } - sheetDataList.add(rowList); - } - return sheetDataList; - } - - private static Map getFieldDataMap(T t) { - Map map = new HashMap<>(16); - Field[] fields = t.getClass().getDeclaredFields(); - try { - for (Field field : fields) { - String fieldName = field.getName(); - field.setAccessible(true); - Object object = field.get(t); - map.put(fieldName, object); - } - } catch (IllegalArgumentException | IllegalAccessException e) { - e.printStackTrace(); - } - return map; - } - - public static void exportEmpty(HttpServletResponse response, String fileName) { - List> sheetDataList = new ArrayList<>(); - List headList = new ArrayList<>(); - headList.add("导出无数据"); - sheetDataList.add(headList); - export(response, fileName, sheetDataList); - } - - public static void export(HttpServletResponse response, String fileName, List> sheetDataList) { - export(response, fileName, fileName, sheetDataList, null); - } - - public static void exportManySheet(HttpServletResponse response, String fileName, Map>> sheetMap) { - export(response, null, fileName, sheetMap, null); - } - - - public static void export(HttpServletResponse response, String fileName, String sheetName, - List> sheetDataList) { - export(response, fileName, sheetName, sheetDataList, null); - } - - public static void export(HttpServletResponse response, String fileName, String sheetName, - List> sheetDataList, Map> selectMap) { - - Map>> map = new HashMap<>(16); - map.put(sheetName, sheetDataList); - export(response, null, fileName, map, selectMap); - } - - public static void export(HttpServletResponse response, String fileName, List list, Class template) { - // list 是否为空 - boolean lisIsEmpty = list == null || list.isEmpty(); - // 如果模板数据为空,且导入的数据为空,则导出空文件 - if (template == null && lisIsEmpty) { - exportEmpty(response, fileName); - return; - } - // 如果 list 数据,则导出模板数据 - if (lisIsEmpty) { - exportTemplate(response, fileName, template); - return; - } - // 导出数据 - List> sheetDataList = getSheetData(list); - export(response, fileName, sheetDataList); - } - - public static void export(HttpServletResponse response, String fileName, List> sheetDataList, Map> selectMap) { - export(response, fileName, fileName, sheetDataList, selectMap); - } - - private static void export(HttpServletResponse response, File file, String fileName, - Map>> sheetMap, Map> selectMap) { - // 整个 Excel 表格 book 对象 - SXSSFWorkbook book = new SXSSFWorkbook(); - // 每个 Sheet 页 - Set>>> entries = sheetMap.entrySet(); - for (Entry>> entry : entries) { - List> sheetDataList = entry.getValue(); - Sheet sheet = book.createSheet(entry.getKey()); - Drawing patriarch = sheet.createDrawingPatriarch(); - // 设置表头背景色(灰色) - CellStyle headStyle = book.createCellStyle(); - headStyle.setFillForegroundColor(IndexedColors.GREY_80_PERCENT.index); - headStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); - headStyle.setAlignment(HorizontalAlignment.CENTER); - headStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.index); - // 设置表身背景色(默认色) - CellStyle rowStyle = book.createCellStyle(); - rowStyle.setAlignment(HorizontalAlignment.CENTER); - rowStyle.setVerticalAlignment(VerticalAlignment.CENTER); - // 设置表格列宽度(默认为15个字节) - sheet.setDefaultColumnWidth(15); - // 创建合并算法数组 - int rowLength = sheetDataList.size(); - int columnLength = sheetDataList.get(0).size(); - int[][] mergeArray = new int[rowLength][columnLength]; - for (int i = 0; i < sheetDataList.size(); i++) { - // 每个 Sheet 页中的行数据 - Row row = sheet.createRow(i); - List rowList = sheetDataList.get(i); - for (int j = 0; j < rowList.size(); j++) { - // 每个行数据中的单元格数据 - Object o = rowList.get(j); - int v = 0; - if (o instanceof URL) { - // 如果要导出图片的话, 链接需要传递 URL 对象 - setCellPicture(book, row, patriarch, i, j, (URL) o); - } else { - Cell cell = row.createCell(j); - if (i == 0) { - // 第一行为表头行,采用灰色底背景 - v = setCellValue(cell, o, headStyle); - } else { - // 其他行为数据行,默认白底色 - v = setCellValue(cell, o, rowStyle); - } - } - mergeArray[i][j] = v; - } - } - // 合并单元格 - mergeCells(sheet, mergeArray); - // 设置下拉列表 - setSelect(sheet, selectMap); - } - // 写数据 - if (response != null) { - // 前端导出 - try { - write(response, book, fileName); - } catch (IOException e) { - e.printStackTrace(); - } - } else { - // 本地导出 - FileOutputStream fos; - try { - fos = new FileOutputStream(file); - ByteArrayOutputStream ops = new ByteArrayOutputStream(); - book.write(ops); - fos.write(ops.toByteArray()); - fos.close(); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - /** - * 合并当前Sheet页的单元格 - * - * @param sheet 当前 sheet 页 - * @param mergeArray 合并单元格算法 - */ - private static void mergeCells(Sheet sheet, int[][] mergeArray) { - // 横向合并 - for (int x = 0; x < mergeArray.length; x++) { - int[] arr = mergeArray[x]; - boolean merge = false; - int y1 = 0; - int y2 = 0; - for (int y = 0; y < arr.length; y++) { - int value = arr[y]; - if (value == CELL_COLUMN_MERGE) { - if (!merge) { - y1 = y; - } - y2 = y; - merge = true; - } else { - merge = false; - if (y1 > 0) { - sheet.addMergedRegion(new CellRangeAddress(x, x, (y1 - 1), y2)); - } - y1 = 0; - y2 = 0; - } - } - if (y1 > 0) { - sheet.addMergedRegion(new CellRangeAddress(x, x, (y1 - 1), y2)); - } - } - // 纵向合并 - int xLen = mergeArray.length; - int yLen = mergeArray[0].length; - for (int y = 0; y < yLen; y++) { - boolean merge = false; - int x1 = 0; - int x2 = 0; - for (int x = 0; x < xLen; x++) { - int value = mergeArray[x][y]; - if (value == CELL_ROW_MERGE) { - if (!merge) { - x1 = x; - } - x2 = x; - merge = true; - } else { - merge = false; - if (x1 > 0) { - sheet.addMergedRegion(new CellRangeAddress((x1 - 1), x2, y, y)); - } - x1 = 0; - x2 = 0; - } - } - if (x1 > 0) { - sheet.addMergedRegion(new CellRangeAddress((x1 - 1), x2, y, y)); - } - } - } - - private static void write(HttpServletResponse response, SXSSFWorkbook book, String fileName) throws IOException { - response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); - response.setCharacterEncoding("utf-8"); - String name = new String(fileName.getBytes("GBK"), "ISO8859_1") + XLSX; - response.addHeader("Content-Disposition", "attachment;filename=" + name); - ServletOutputStream out = response.getOutputStream(); - book.write(out); - out.flush(); - out.close(); - } - - private static int setCellValue(Cell cell, Object o, CellStyle style) { - // 设置样式 - cell.setCellStyle(style); - // 数据为空时 - if (ObjectUtil.isEmpty(o)) { - cell.setCellType(CellType.STRING); - cell.setCellValue(""); - return CELL_OTHER; - } - // 是否为字符串 - if (o instanceof String) { - String s = o.toString(); - if (isNumeric(s)) { - cell.setCellType(CellType.NUMERIC); - cell.setCellValue(Double.parseDouble(s)); - return CELL_OTHER; - } else { - cell.setCellType(CellType.STRING); - cell.setCellValue(s); - } - if (s.equals(ROW_MERGE)) { - return CELL_ROW_MERGE; - } else if (s.equals(COLUMN_MERGE)) { - return CELL_COLUMN_MERGE; - } else { - return CELL_OTHER; - } - } - // 是否为字符串 - if (o instanceof Integer || o instanceof Long || o instanceof Double || o instanceof Float) { - cell.setCellType(CellType.NUMERIC); - cell.setCellValue(Double.parseDouble(o.toString())); - return CELL_OTHER; - } - // 是否为Boolean - if (o instanceof Boolean) { - cell.setCellType(CellType.BOOLEAN); - cell.setCellValue((Boolean) o); - return CELL_OTHER; - } - // 如果是BigDecimal,则默认3位小数 - if (o instanceof BigDecimal) { - cell.setCellType(CellType.NUMERIC); - cell.setCellValue(((BigDecimal) o).setScale(3, RoundingMode.HALF_UP).doubleValue()); - return CELL_OTHER; - } - // 如果是Date数据,则显示格式化数据 - if (o instanceof Date) { - cell.setCellType(CellType.STRING); - cell.setCellValue(formatDate((Date) o)); - return CELL_OTHER; - } - // 如果是其他,则默认字符串类型 - cell.setCellType(CellType.STRING); - cell.setCellValue(o.toString()); - return CELL_OTHER; - } - - private static void setCellPicture(SXSSFWorkbook wb, Row sr, Drawing patriarch, int x, int y, URL url) { - // 设置图片宽高 - sr.setHeight((short) (IMG_WIDTH * IMG_HEIGHT)); - // (jdk1.7版本try中定义流可自动关闭) - try (InputStream is = url.openStream(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { - byte[] buff = new byte[BYTES_DEFAULT_LENGTH]; - int rc; - while ((rc = is.read(buff, 0, BYTES_DEFAULT_LENGTH)) > 0) { - outputStream.write(buff, 0, rc); - } - // 设置图片位置 - XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, y, x, y + 1, x + 1); - // 设置这个,图片会自动填满单元格的长宽 - anchor.setAnchorType(AnchorType.MOVE_AND_RESIZE); - patriarch.createPicture(anchor, wb.addPicture(outputStream.toByteArray(), HSSFWorkbook.PICTURE_TYPE_JPEG)); - } catch (Exception e) { - e.printStackTrace(); - } - } - - private static String formatDate(Date date) { - if (date == null) { - return ""; - } - SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT); - return format.format(date); - } - - private static void setSelect(Sheet sheet, Map> selectMap) { - if (selectMap == null || selectMap.isEmpty()) { - return; - } - Set>> entrySet = selectMap.entrySet(); - for (Entry> entry : entrySet) { - int y = entry.getKey(); - List list = entry.getValue(); - if (list == null || list.isEmpty()) { - continue; - } - String[] arr = new String[list.size()]; - for (int i = 0; i < list.size(); i++) { - arr[i] = list.get(i); - } - DataValidationHelper helper = sheet.getDataValidationHelper(); - CellRangeAddressList addressList = new CellRangeAddressList(1, 65000, y, y); - DataValidationConstraint dvc = helper.createExplicitListConstraint(arr); - DataValidation dv = helper.createValidation(dvc, addressList); - if (dv instanceof HSSFDataValidation) { - dv.setSuppressDropDownArrow(false); - } else { - dv.setSuppressDropDownArrow(true); - dv.setShowErrorBox(true); - } - sheet.addValidationData(dv); - } - } - - private static boolean isNumeric(String str) { - if ("0.0".equals(str)) { - return true; - } - if (str.length() >= 15) { - return false; - } - for (int i = str.length(); --i >= 0; ) { - if (!Character.isDigit(str.charAt(i))) { - return false; - } - } - return true; - } - - private static String getString(String s) { - if (s == null) { - return ""; - } - if (s.isEmpty()) { - return s; - } - return s.trim(); - } -} diff --git a/wjcy-common/src/test/java/me/zhengjie/utils/EncryptUtilsTest.java b/wjcy-common/src/test/java/me/zhengjie/utils/EncryptUtilsTest.java deleted file mode 100644 index f909d9d..0000000 --- a/wjcy-common/src/test/java/me/zhengjie/utils/EncryptUtilsTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package me.zhengjie.utils; - -import org.junit.Test; -import static org.junit.Assert.*; -import static me.zhengjie.utils.EncryptUtils.*; - -public class EncryptUtilsTest { - - /** - * 对称加密 - */ - @Test - public void testDesEncrypt() { - try { - assertEquals("7772841DC6099402", desEncrypt("123456")); - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * 对称解密 - */ - @Test - public void testDesDecrypt() { - try { - assertEquals("123456", desDecrypt("7772841DC6099402")); - } catch (Exception e) { - e.printStackTrace(); - } - } -} diff --git a/wjcy-common/src/test/java/me/zhengjie/utils/FileUtilTest.java b/wjcy-common/src/test/java/me/zhengjie/utils/FileUtilTest.java deleted file mode 100644 index f069c15..0000000 --- a/wjcy-common/src/test/java/me/zhengjie/utils/FileUtilTest.java +++ /dev/null @@ -1,36 +0,0 @@ -package me.zhengjie.utils; - -import org.junit.Test; -import org.springframework.mock.web.MockMultipartFile; - -import static org.junit.Assert.*; -import static me.zhengjie.utils.FileUtil.*; - -public class FileUtilTest { - - @Test - public void testToFile() { - long retval = toFile(new MockMultipartFile("foo", (byte[]) null)).getTotalSpace(); - assertEquals(500695072768L, retval); - } - - @Test - public void testGetExtensionName() { - assertEquals("foo", getExtensionName("foo")); - assertEquals("exe", getExtensionName("bar.exe")); - } - - @Test - public void testGetFileNameNoEx() { - assertEquals("foo", getFileNameNoEx("foo")); - assertEquals("bar", getFileNameNoEx("bar.txt")); - } - - @Test - public void testGetSize() { - assertEquals("1000B ", getSize(1000)); - assertEquals("1.00KB ", getSize(1024)); - assertEquals("1.00MB ", getSize(1048576)); - assertEquals("1.00GB ", getSize(1073741824)); - } -} diff --git a/wjcy-common/src/test/java/me/zhengjie/utils/StringUtilsTest.java b/wjcy-common/src/test/java/me/zhengjie/utils/StringUtilsTest.java deleted file mode 100644 index 16de472..0000000 --- a/wjcy-common/src/test/java/me/zhengjie/utils/StringUtilsTest.java +++ /dev/null @@ -1,66 +0,0 @@ -package me.zhengjie.utils; - -import cn.hutool.core.date.DateTime; -import cn.hutool.core.date.DateUtil; -import org.junit.Test; -import org.springframework.mock.web.MockHttpServletRequest; -import org.thymeleaf.util.DateUtils; - -import java.text.SimpleDateFormat; -import java.util.Date; - -import static me.zhengjie.utils.StringUtils.*; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -public class StringUtilsTest { - - @Test - public void testToCamelCase() { - assertNull(toCamelCase(null)); - } - - @Test - public void testToCapitalizeCamelCase() { - assertNull(StringUtils.toCapitalizeCamelCase(null)); - assertEquals("HelloWorld", toCapitalizeCamelCase("hello_world")); - } - - @Test - public void testToUnderScoreCase() { - assertNull(StringUtils.toUnderScoreCase(null)); - assertEquals("hello_world", toUnderScoreCase("helloWorld")); - assertEquals("\u0000\u0000", toUnderScoreCase("\u0000\u0000")); - assertEquals("\u0000_a", toUnderScoreCase("\u0000A")); - } - - @Test - public void testGetWeekDay() { - SimpleDateFormat simpleDateformat = new SimpleDateFormat("E"); - assertEquals(simpleDateformat.format(new Date()), getWeekDay()); - } - - @Test - public void testGetIP() { - assertEquals("127.0.0.1", getIp(new MockHttpServletRequest())); - } - - - - @Test - public void test123() { - // 仅一次 - Date date = DateUtil.date(); - System.out.println("date:" + date); - DateTime dateTime = DateUtil.offsetSecond(date, 5); - System.out.println("dateTime:" + dateTime); - - String onlyOnce = CronUtils.onlyOnce(DateUtil.formatDateTime(dateTime)); - String onlyOnce1 = CronUtils.onlyOnce("2022-10-10 10:10:10"); - System.out.println(onlyOnce); - - // 一部到位 - String onlyOnce2 = CronUtils.onlyOnce(DateUtil.formatDateTime(DateUtil.offsetSecond(DateUtil.date(), 5))); - System.out.println(onlyOnce2); - } -} \ No newline at end of file diff --git a/wjcy-generator/pom.xml b/wjcy-generator/pom.xml deleted file mode 100644 index 87d7e4e..0000000 --- a/wjcy-generator/pom.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - wjcy - me.zhengjie - 1.0 - - 4.0.0 - - wjcy-generator - 代码生成模块 - - - 1.9 - - - - - me.zhengjie - wjcy-common - 1.0 - - - - - org.springframework.boot - spring-boot-starter-freemarker - - - - - commons-configuration - commons-configuration - ${configuration.version} - - - \ No newline at end of file diff --git a/wjcy-generator/src/main/java/me/zhengjie/domain/ColumnInfo.java b/wjcy-generator/src/main/java/me/zhengjie/domain/ColumnInfo.java deleted file mode 100644 index fdb962a..0000000 --- a/wjcy-generator/src/main/java/me/zhengjie/domain/ColumnInfo.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.domain; - -import io.swagger.annotations.ApiModelProperty; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import me.zhengjie.utils.GenUtil; -import javax.persistence.*; -import java.io.Serializable; - -/** - * 列的数据信息 - * @author Zheng Jie - * @date 2019-01-02 - */ -@Getter -@Setter -@Entity -@NoArgsConstructor -@Table(name = "code_column_config") -public class ColumnInfo implements Serializable { - - @Id - @Column(name = "column_id") - @ApiModelProperty(value = "ID", hidden = true) - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ApiModelProperty(value = "表名") - private String tableName; - - @ApiModelProperty(value = "数据库字段名称") - private String columnName; - - @ApiModelProperty(value = "数据库字段类型") - private String columnType; - - @ApiModelProperty(value = "数据库字段键类型") - private String keyType; - - @ApiModelProperty(value = "字段额外的参数") - private String extra; - - @ApiModelProperty(value = "数据库字段描述") - private String remark; - - @ApiModelProperty(value = "是否必填") - private Boolean notNull; - - @ApiModelProperty(value = "是否在列表显示") - private Boolean listShow; - - @ApiModelProperty(value = "是否表单显示") - private Boolean formShow; - - @ApiModelProperty(value = "表单类型") - private String formType; - - @ApiModelProperty(value = "查询 1:模糊 2:精确") - private String queryType; - - @ApiModelProperty(value = "字典名称") - private String dictName; - - @ApiModelProperty(value = "日期注解") - private String dateAnnotation; - - public ColumnInfo(String tableName, String columnName, Boolean notNull, String columnType, String remark, String keyType, String extra) { - this.tableName = tableName; - this.columnName = columnName; - this.columnType = columnType; - this.keyType = keyType; - this.extra = extra; - this.notNull = notNull; - if(GenUtil.PK.equalsIgnoreCase(keyType) && GenUtil.EXTRA.equalsIgnoreCase(extra)){ - this.notNull = false; - } - this.remark = remark; - this.listShow = true; - this.formShow = true; - } -} diff --git a/wjcy-generator/src/main/java/me/zhengjie/domain/GenConfig.java b/wjcy-generator/src/main/java/me/zhengjie/domain/GenConfig.java deleted file mode 100644 index a2d6706..0000000 --- a/wjcy-generator/src/main/java/me/zhengjie/domain/GenConfig.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.domain; - -import io.swagger.annotations.ApiModelProperty; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import javax.persistence.*; -import javax.validation.constraints.NotBlank; -import java.io.Serializable; - -/** - * 代码生成配置 - * @author Zheng Jie - * @date 2019-01-03 - */ -@Getter -@Setter -@Entity -@NoArgsConstructor -@Table(name = "code_gen_config") -public class GenConfig implements Serializable { - - public GenConfig(String tableName) { - this.tableName = tableName; - } - - @Id - @Column(name = "config_id") - @ApiModelProperty(value = "ID", hidden = true) - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @NotBlank - @ApiModelProperty(value = "表名") - private String tableName; - - @ApiModelProperty(value = "接口名称") - private String apiAlias; - - @NotBlank - @ApiModelProperty(value = "包路径") - private String pack; - - @NotBlank - @ApiModelProperty(value = "模块名") - private String moduleName; - - @NotBlank - @ApiModelProperty(value = "前端文件路径") - private String path; - - @ApiModelProperty(value = "前端文件路径") - private String apiPath; - - @ApiModelProperty(value = "作者") - private String author; - - @ApiModelProperty(value = "表前缀") - private String prefix; - - @ApiModelProperty(value = "是否覆盖") - private Boolean cover = false; -} diff --git a/wjcy-generator/src/main/java/me/zhengjie/domain/vo/TableInfo.java b/wjcy-generator/src/main/java/me/zhengjie/domain/vo/TableInfo.java deleted file mode 100644 index 1d3967b..0000000 --- a/wjcy-generator/src/main/java/me/zhengjie/domain/vo/TableInfo.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.domain.vo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 表的数据信息 - * @author Zheng Jie - * @date 2019-01-02 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class TableInfo { - - /** 表名称 */ - private Object tableName; - - /** 创建日期 */ - private Object createTime; - - /** 数据库引擎 */ - private Object engine; - - /** 编码集 */ - private Object coding; - - /** 备注 */ - private Object remark; - - -} diff --git a/wjcy-generator/src/main/java/me/zhengjie/repository/ColumnInfoRepository.java b/wjcy-generator/src/main/java/me/zhengjie/repository/ColumnInfoRepository.java deleted file mode 100644 index 4638be2..0000000 --- a/wjcy-generator/src/main/java/me/zhengjie/repository/ColumnInfoRepository.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.repository; - -import me.zhengjie.domain.ColumnInfo; -import org.springframework.data.jpa.repository.JpaRepository; -import java.util.List; - -/** - * @author Zheng Jie - * @date 2019-01-14 - */ -public interface ColumnInfoRepository extends JpaRepository { - - /** - * 查询表信息 - * @param tableName 表格名 - * @return 表信息 - */ - List findByTableNameOrderByIdAsc(String tableName); -} diff --git a/wjcy-generator/src/main/java/me/zhengjie/repository/GenConfigRepository.java b/wjcy-generator/src/main/java/me/zhengjie/repository/GenConfigRepository.java deleted file mode 100644 index 18c9a0c..0000000 --- a/wjcy-generator/src/main/java/me/zhengjie/repository/GenConfigRepository.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.repository; - -import me.zhengjie.domain.GenConfig; -import org.springframework.data.jpa.repository.JpaRepository; - -/** - * @author Zheng Jie - * @date 2019-01-14 - */ -public interface GenConfigRepository extends JpaRepository { - - /** - * 查询表配置 - * @param tableName 表名 - * @return / - */ - GenConfig findByTableName(String tableName); -} diff --git a/wjcy-generator/src/main/java/me/zhengjie/rest/GenConfigController.java b/wjcy-generator/src/main/java/me/zhengjie/rest/GenConfigController.java deleted file mode 100644 index 98ec149..0000000 --- a/wjcy-generator/src/main/java/me/zhengjie/rest/GenConfigController.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.rest; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import lombok.RequiredArgsConstructor; -import me.zhengjie.domain.GenConfig; -import me.zhengjie.service.GenConfigService; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -/** - * @author Zheng Jie - * @date 2019-01-14 - */ -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/genConfig") -@Api(tags = "系统:代码生成器配置管理") -public class GenConfigController { - - private final GenConfigService genConfigService; - - @ApiOperation("查询") - @GetMapping(value = "/{tableName}") - public ResponseEntity query(@PathVariable String tableName){ - return new ResponseEntity<>(genConfigService.find(tableName), HttpStatus.OK); - } - - @ApiOperation("修改") - @PutMapping - public ResponseEntity update(@Validated @RequestBody GenConfig genConfig){ - return new ResponseEntity<>(genConfigService.update(genConfig.getTableName(), genConfig),HttpStatus.OK); - } -} diff --git a/wjcy-generator/src/main/java/me/zhengjie/rest/GeneratorController.java b/wjcy-generator/src/main/java/me/zhengjie/rest/GeneratorController.java deleted file mode 100644 index ce6a17d..0000000 --- a/wjcy-generator/src/main/java/me/zhengjie/rest/GeneratorController.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.rest; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import lombok.RequiredArgsConstructor; -import me.zhengjie.domain.ColumnInfo; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.service.GenConfigService; -import me.zhengjie.service.GeneratorService; -import me.zhengjie.utils.PageUtil; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.util.List; - -/** - * @author Zheng Jie - * @date 2019-01-02 - */ -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/generator") -@Api(tags = "系统:代码生成管理") -public class GeneratorController { - - private final GeneratorService generatorService; - private final GenConfigService genConfigService; - - @Value("${generator.enabled}") - private Boolean generatorEnabled; - - @ApiOperation("查询数据库数据") - @GetMapping(value = "/tables/all") - public ResponseEntity queryTables(){ - return new ResponseEntity<>(generatorService.getTables(), HttpStatus.OK); - } - - @ApiOperation("查询数据库数据") - @GetMapping(value = "/tables") - public ResponseEntity queryTables(@RequestParam(defaultValue = "") String name, - @RequestParam(defaultValue = "0")Integer page, - @RequestParam(defaultValue = "10")Integer size){ - int[] startEnd = PageUtil.transToStartEnd(page, size); - return new ResponseEntity<>(generatorService.getTables(name,startEnd), HttpStatus.OK); - } - - @ApiOperation("查询字段数据") - @GetMapping(value = "/columns") - public ResponseEntity queryColumns(@RequestParam String tableName){ - List columnInfos = generatorService.getColumns(tableName); - return new ResponseEntity<>(PageUtil.toPage(columnInfos,columnInfos.size()), HttpStatus.OK); - } - - @ApiOperation("保存字段数据") - @PutMapping - public ResponseEntity save(@RequestBody List columnInfos){ - generatorService.save(columnInfos); - return new ResponseEntity<>(HttpStatus.OK); - } - - @ApiOperation("同步字段数据") - @PostMapping(value = "sync") - public ResponseEntity sync(@RequestBody List tables){ - for (String table : tables) { - generatorService.sync(generatorService.getColumns(table), generatorService.query(table)); - } - return new ResponseEntity<>(HttpStatus.OK); - } - - @ApiOperation("生成代码") - @PostMapping(value = "/{tableName}/{type}") - public ResponseEntity generator(@PathVariable String tableName, @PathVariable Integer type, HttpServletRequest request, HttpServletResponse response){ - if(!generatorEnabled && type == 0){ - throw new BadRequestException("此环境不允许生成代码,请选择预览或者下载查看!"); - } - switch (type){ - // 生成代码 - case 0: generatorService.generator(genConfigService.find(tableName), generatorService.getColumns(tableName)); - break; - // 预览 - case 1: return generatorService.preview(genConfigService.find(tableName), generatorService.getColumns(tableName)); - // 打包 - case 2: generatorService.download(genConfigService.find(tableName), generatorService.getColumns(tableName), request, response); - break; - default: throw new BadRequestException("没有这个选项"); - } - return new ResponseEntity<>(HttpStatus.OK); - } -} diff --git a/wjcy-generator/src/main/java/me/zhengjie/service/GenConfigService.java b/wjcy-generator/src/main/java/me/zhengjie/service/GenConfigService.java deleted file mode 100644 index b5711f4..0000000 --- a/wjcy-generator/src/main/java/me/zhengjie/service/GenConfigService.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.service; - -import me.zhengjie.domain.GenConfig; - -/** - * @author Zheng Jie - * @date 2019-01-14 - */ -public interface GenConfigService { - - /** - * 查询表配置 - * @param tableName 表名 - * @return 表配置 - */ - GenConfig find(String tableName); - - /** - * 更新表配置 - * @param tableName 表名 - * @param genConfig 表配置 - * @return 表配置 - */ - GenConfig update(String tableName, GenConfig genConfig); -} diff --git a/wjcy-generator/src/main/java/me/zhengjie/service/GeneratorService.java b/wjcy-generator/src/main/java/me/zhengjie/service/GeneratorService.java deleted file mode 100644 index b5a1e0a..0000000 --- a/wjcy-generator/src/main/java/me/zhengjie/service/GeneratorService.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.service; - -import me.zhengjie.domain.GenConfig; -import me.zhengjie.domain.ColumnInfo; -import org.springframework.http.ResponseEntity; -import org.springframework.scheduling.annotation.Async; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.util.List; - -/** - * @author Zheng Jie - * @date 2019-01-02 - */ -public interface GeneratorService { - - /** - * 查询数据库元数据 - * @param name 表名 - * @param startEnd 分页参数 - * @return / - */ - Object getTables(String name, int[] startEnd); - - /** - * 得到数据表的元数据 - * @param name 表名 - * @return / - */ - List getColumns(String name); - - /** - * 同步表数据 - * @param columnInfos / - * @param columnInfoList / - */ - void sync(List columnInfos, List columnInfoList); - - /** - * 保持数据 - * @param columnInfos / - */ - void save(List columnInfos); - - /** - * 获取所有table - * @return / - */ - Object getTables(); - - /** - * 代码生成 - * @param genConfig 配置信息 - * @param columns 字段信息 - */ - void generator(GenConfig genConfig, List columns); - - /** - * 预览 - * @param genConfig 配置信息 - * @param columns 字段信息 - * @return / - */ - ResponseEntity preview(GenConfig genConfig, List columns); - - /** - * 打包下载 - * @param genConfig 配置信息 - * @param columns 字段信息 - * @param request / - * @param response / - */ - void download(GenConfig genConfig, List columns, HttpServletRequest request, HttpServletResponse response); - - /** - * 查询数据库的表字段数据数据 - * @param table / - * @return / - */ - List query(String table); -} diff --git a/wjcy-generator/src/main/java/me/zhengjie/service/impl/GenConfigServiceImpl.java b/wjcy-generator/src/main/java/me/zhengjie/service/impl/GenConfigServiceImpl.java deleted file mode 100644 index bc2d061..0000000 --- a/wjcy-generator/src/main/java/me/zhengjie/service/impl/GenConfigServiceImpl.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.service.impl; - -import lombok.RequiredArgsConstructor; -import me.zhengjie.domain.GenConfig; -import me.zhengjie.repository.GenConfigRepository; -import me.zhengjie.service.GenConfigService; -import me.zhengjie.utils.StringUtils; -import org.springframework.stereotype.Service; -import java.io.File; - -/** - * @author Zheng Jie - * @date 2019-01-14 - */ -@Service -@RequiredArgsConstructor -public class GenConfigServiceImpl implements GenConfigService { - - private final GenConfigRepository genConfigRepository; - - @Override - public GenConfig find(String tableName) { - GenConfig genConfig = genConfigRepository.findByTableName(tableName); - if(genConfig == null){ - return new GenConfig(tableName); - } - return genConfig; - } - - @Override - public GenConfig update(String tableName, GenConfig genConfig) { - String separator = File.separator; - String[] paths; - String symbol = "\\"; - if (symbol.equals(separator)) { - paths = genConfig.getPath().split("\\\\"); - } else { - paths = genConfig.getPath().split(File.separator); - } - StringBuilder api = new StringBuilder(); - for (String path : paths) { - api.append(path); - api.append(separator); - if ("src".equals(path)) { - api.append("api"); - break; - } - } - genConfig.setApiPath(api.toString()); - return genConfigRepository.save(genConfig); - } -} diff --git a/wjcy-generator/src/main/java/me/zhengjie/service/impl/GeneratorServiceImpl.java b/wjcy-generator/src/main/java/me/zhengjie/service/impl/GeneratorServiceImpl.java deleted file mode 100644 index 1b1803b..0000000 --- a/wjcy-generator/src/main/java/me/zhengjie/service/impl/GeneratorServiceImpl.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.service.impl; - -import cn.hutool.core.collection.CollectionUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.ZipUtil; -import lombok.RequiredArgsConstructor; -import me.zhengjie.domain.GenConfig; -import me.zhengjie.domain.ColumnInfo; -import me.zhengjie.domain.vo.TableInfo; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.repository.ColumnInfoRepository; -import me.zhengjie.service.GeneratorService; -import me.zhengjie.utils.FileUtil; -import me.zhengjie.utils.GenUtil; -import me.zhengjie.utils.PageUtil; -import me.zhengjie.utils.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Service; - -import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; -import javax.persistence.Query; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * @author Zheng Jie - * @date 2019-01-02 - */ -@Service -@RequiredArgsConstructor -public class GeneratorServiceImpl implements GeneratorService { - private static final Logger log = LoggerFactory.getLogger(GeneratorServiceImpl.class); - @PersistenceContext - private EntityManager em; - - private final ColumnInfoRepository columnInfoRepository; - - @Override - public Object getTables() { - // 使用预编译防止sql注入 - String sql = "select table_name ,create_time , engine, table_collation, table_comment from information_schema.tables " + - "where table_schema = (select database()) " + - "order by create_time desc"; - Query query = em.createNativeQuery(sql); - return query.getResultList(); - } - - @Override - public Object getTables(String name, int[] startEnd) { - // 使用预编译防止sql注入 - String sql = "select table_name ,create_time , engine, table_collation, table_comment from information_schema.tables " + - "where table_schema = (select database()) " + - "and table_name like ? order by create_time desc"; - Query query = em.createNativeQuery(sql); - query.setFirstResult(startEnd[0]); - query.setMaxResults(startEnd[1] - startEnd[0]); - query.setParameter(1, StringUtils.isNotBlank(name) ? ("%" + name + "%") : "%%"); - List result = query.getResultList(); - List tableInfos = new ArrayList<>(); - for (Object obj : result) { - Object[] arr = (Object[]) obj; - tableInfos.add(new TableInfo(arr[0], arr[1], arr[2], arr[3], ObjectUtil.isNotEmpty(arr[4]) ? arr[4] : "-")); - } - Query query1 = em.createNativeQuery("SELECT COUNT(*) from information_schema.tables where table_schema = (select database())"); - Object totalElements = query1.getSingleResult(); - return PageUtil.toPage(tableInfos, totalElements); - } - - @Override - public List getColumns(String tableName) { - List columnInfos = columnInfoRepository.findByTableNameOrderByIdAsc(tableName); - if (CollectionUtil.isNotEmpty(columnInfos)) { - return columnInfos; - } else { - columnInfos = query(tableName); - return columnInfoRepository.saveAll(columnInfos); - } - } - - @Override - public List query(String tableName) { - // 使用预编译防止sql注入 - String sql = "select column_name, is_nullable, data_type, column_comment, column_key, extra from information_schema.columns " + - "where table_name = ? and table_schema = (select database()) order by ordinal_position"; - Query query = em.createNativeQuery(sql); - query.setParameter(1, tableName); - List result = query.getResultList(); - List columnInfos = new ArrayList<>(); - for (Object obj : result) { - Object[] arr = (Object[]) obj; - columnInfos.add( - new ColumnInfo( - tableName, - arr[0].toString(), - "NO".equals(arr[1]), - arr[2].toString(), - ObjectUtil.isNotNull(arr[3]) ? arr[3].toString() : null, - ObjectUtil.isNotNull(arr[4]) ? arr[4].toString() : null, - ObjectUtil.isNotNull(arr[5]) ? arr[5].toString() : null) - ); - } - return columnInfos; - } - - @Override - public void sync(List columnInfos, List columnInfoList) { - // 第一种情况,数据库类字段改变或者新增字段 - for (ColumnInfo columnInfo : columnInfoList) { - // 根据字段名称查找 - List columns = columnInfos.stream().filter(c -> c.getColumnName().equals(columnInfo.getColumnName())).collect(Collectors.toList()); - // 如果能找到,就修改部分可能被字段 - if (CollectionUtil.isNotEmpty(columns)) { - ColumnInfo column = columns.get(0); - column.setColumnType(columnInfo.getColumnType()); - column.setExtra(columnInfo.getExtra()); - column.setKeyType(columnInfo.getKeyType()); - if (StringUtils.isBlank(column.getRemark())) { - column.setRemark(columnInfo.getRemark()); - } - columnInfoRepository.save(column); - } else { - // 如果找不到,则保存新字段信息 - columnInfoRepository.save(columnInfo); - } - } - // 第二种情况,数据库字段删除了 - for (ColumnInfo columnInfo : columnInfos) { - // 根据字段名称查找 - List columns = columnInfoList.stream().filter(c -> c.getColumnName().equals(columnInfo.getColumnName())).collect(Collectors.toList()); - // 如果找不到,就代表字段被删除了,则需要删除该字段 - if (CollectionUtil.isEmpty(columns)) { - columnInfoRepository.delete(columnInfo); - } - } - } - - @Override - public void save(List columnInfos) { - columnInfoRepository.saveAll(columnInfos); - } - - @Override - public void generator(GenConfig genConfig, List columns) { - if (genConfig.getId() == null) { - throw new BadRequestException("请先配置生成器"); - } - try { - GenUtil.generatorCode(columns, genConfig); - } catch (IOException e) { - log.error(e.getMessage(), e); - throw new BadRequestException("生成失败,请手动处理已生成的文件"); - } - } - - @Override - public ResponseEntity preview(GenConfig genConfig, List columns) { - if (genConfig.getId() == null) { - throw new BadRequestException("请先配置生成器"); - } - List> genList = GenUtil.preview(columns, genConfig); - return new ResponseEntity<>(genList, HttpStatus.OK); - } - - @Override - public void download(GenConfig genConfig, List columns, HttpServletRequest request, HttpServletResponse response) { - if (genConfig.getId() == null) { - throw new BadRequestException("请先配置生成器"); - } - try { - File file = new File(GenUtil.download(columns, genConfig)); - String zipPath = file.getPath() + ".zip"; - ZipUtil.zip(file.getPath(), zipPath); - FileUtil.downloadFile(request, response, new File(zipPath), true); - } catch (IOException e) { - throw new BadRequestException("打包失败"); - } - } -} diff --git a/wjcy-generator/src/main/java/me/zhengjie/utils/ColUtil.java b/wjcy-generator/src/main/java/me/zhengjie/utils/ColUtil.java deleted file mode 100644 index b5fcd6b..0000000 --- a/wjcy-generator/src/main/java/me/zhengjie/utils/ColUtil.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.utils; - -import org.apache.commons.configuration.*; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * sql字段转java - * - * @author Zheng Jie - * @date 2019-01-03 - */ -public class ColUtil { - private static final Logger log = LoggerFactory.getLogger(ColUtil.class); - - /** - * 转换mysql数据类型为java数据类型 - * - * @param type 数据库字段类型 - * @return String - */ - static String cloToJava(String type) { - Configuration config = getConfig(); - assert config != null; - return config.getString(type, "unknowType"); - } - - /** - * 获取配置信息 - */ - public static PropertiesConfiguration getConfig() { - try { - return new PropertiesConfiguration("generator.properties"); - } catch (ConfigurationException e) { - log.error(e.getMessage(), e); - } - return null; - } -} diff --git a/wjcy-generator/src/main/java/me/zhengjie/utils/GenUtil.java b/wjcy-generator/src/main/java/me/zhengjie/utils/GenUtil.java deleted file mode 100644 index 566b6d8..0000000 --- a/wjcy-generator/src/main/java/me/zhengjie/utils/GenUtil.java +++ /dev/null @@ -1,420 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.utils; - -import cn.hutool.core.util.StrUtil; -import cn.hutool.extra.template.*; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.domain.GenConfig; -import me.zhengjie.domain.ColumnInfo; -import org.springframework.util.ObjectUtils; - -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.Writer; -import java.time.LocalDate; -import java.util.*; - -import static me.zhengjie.utils.FileUtil.SYS_TEM_DIR; - -/** - * 代码生成 - * - * @author Zheng Jie - * @date 2019-01-02 - */ -@Slf4j -@SuppressWarnings({"unchecked", "all"}) -public class GenUtil { - - private static final String TIMESTAMP = "Timestamp"; - - private static final String BIGDECIMAL = "BigDecimal"; - - public static final String PK = "PRI"; - - public static final String EXTRA = "auto_increment"; - - /** - * 获取后端代码模板名称 - * - * @return List - */ - private static List getAdminTemplateNames() { - List templateNames = new ArrayList<>(); - templateNames.add("Entity"); - templateNames.add("Dto"); - templateNames.add("Mapper"); - templateNames.add("Controller"); - templateNames.add("QueryCriteria"); - templateNames.add("Service"); - templateNames.add("ServiceImpl"); - templateNames.add("Repository"); - return templateNames; - } - - /** - * 获取前端代码模板名称 - * - * @return List - */ - private static List getFrontTemplateNames() { - List templateNames = new ArrayList<>(); - templateNames.add("index"); - templateNames.add("api"); - return templateNames; - } - - public static List> preview(List columns, GenConfig genConfig) { - Map genMap = getGenMap(columns, genConfig); - List> genList = new ArrayList<>(); - // 获取后端模版 - List templates = getAdminTemplateNames(); - TemplateEngine engine = TemplateUtil.createEngine(new TemplateConfig("template", TemplateConfig.ResourceMode.CLASSPATH)); - for (String templateName : templates) { - Map map = new HashMap<>(1); - Template template = engine.getTemplate("generator/admin/" + templateName + ".ftl"); - map.put("content", template.render(genMap)); - map.put("name", templateName); - genList.add(map); - } - // 获取前端模版 - templates = getFrontTemplateNames(); - for (String templateName : templates) { - Map map = new HashMap<>(1); - Template template = engine.getTemplate("generator/front/" + templateName + ".ftl"); - map.put(templateName, template.render(genMap)); - map.put("content", template.render(genMap)); - map.put("name", templateName); - genList.add(map); - } - return genList; - } - - public static String download(List columns, GenConfig genConfig) throws IOException { - // 拼接的路径:/tmpeladmin-gen-temp/,这个路径在Linux下需要root用户才有权限创建,非root用户会权限错误而失败,更改为: /tmp/eladmin-gen-temp/ - // String tempPath =SYS_TEM_DIR + "eladmin-gen-temp" + File.separator + genConfig.getTableName() + File.separator; - String tempPath = SYS_TEM_DIR + "eladmin-gen-temp" + File.separator + genConfig.getTableName() + File.separator; - Map genMap = getGenMap(columns, genConfig); - TemplateEngine engine = TemplateUtil.createEngine(new TemplateConfig("template", TemplateConfig.ResourceMode.CLASSPATH)); - // 生成后端代码 - List templates = getAdminTemplateNames(); - for (String templateName : templates) { - Template template = engine.getTemplate("generator/admin/" + templateName + ".ftl"); - String filePath = getAdminFilePath(templateName, genConfig, genMap.get("className").toString(), tempPath + "eladmin" + File.separator); - assert filePath != null; - File file = new File(filePath); - // 如果非覆盖生成 - if (!genConfig.getCover() && FileUtil.exist(file)) { - continue; - } - // 生成代码 - genFile(file, template, genMap); - } - // 生成前端代码 - templates = getFrontTemplateNames(); - for (String templateName : templates) { - Template template = engine.getTemplate("generator/front/" + templateName + ".ftl"); - String path = tempPath + "eladmin-web" + File.separator; - String apiPath = path + "src" + File.separator + "api" + File.separator; - String srcPath = path + "src" + File.separator + "views" + File.separator + genMap.get("changeClassName").toString() + File.separator; - String filePath = getFrontFilePath(templateName, apiPath, srcPath, genMap.get("changeClassName").toString()); - assert filePath != null; - File file = new File(filePath); - // 如果非覆盖生成 - if (!genConfig.getCover() && FileUtil.exist(file)) { - continue; - } - // 生成代码 - genFile(file, template, genMap); - } - return tempPath; - } - - public static void generatorCode(List columnInfos, GenConfig genConfig) throws IOException { - Map genMap = getGenMap(columnInfos, genConfig); - TemplateEngine engine = TemplateUtil.createEngine(new TemplateConfig("template", TemplateConfig.ResourceMode.CLASSPATH)); - // 生成后端代码 - List templates = getAdminTemplateNames(); - for (String templateName : templates) { - Template template = engine.getTemplate("generator/admin/" + templateName + ".ftl"); - String rootPath = System.getProperty("user.dir"); - String filePath = getAdminFilePath(templateName, genConfig, genMap.get("className").toString(), rootPath); - - assert filePath != null; - File file = new File(filePath); - - // 如果非覆盖生成 - if (!genConfig.getCover() && FileUtil.exist(file)) { - continue; - } - // 生成代码 - genFile(file, template, genMap); - } - - // 生成前端代码 - templates = getFrontTemplateNames(); - for (String templateName : templates) { - Template template = engine.getTemplate("generator/front/" + templateName + ".ftl"); - String filePath = getFrontFilePath(templateName, genConfig.getApiPath(), genConfig.getPath(), genMap.get("changeClassName").toString()); - - assert filePath != null; - File file = new File(filePath); - - // 如果非覆盖生成 - if (!genConfig.getCover() && FileUtil.exist(file)) { - continue; - } - // 生成代码 - genFile(file, template, genMap); - } - } - - // 获取模版数据 - private static Map getGenMap(List columnInfos, GenConfig genConfig) { - // 存储模版字段数据 - Map genMap = new HashMap<>(16); - // 接口别名 - genMap.put("apiAlias", genConfig.getApiAlias()); - // 包名称 - genMap.put("package", genConfig.getPack()); - // 模块名称 - genMap.put("moduleName", genConfig.getModuleName()); - // 作者 - genMap.put("author", genConfig.getAuthor()); - // 创建日期 - genMap.put("date", LocalDate.now().toString()); - // 表名 - genMap.put("tableName", genConfig.getTableName()); - // 大写开头的类名 - String className = StringUtils.toCapitalizeCamelCase(genConfig.getTableName()); - // 小写开头的类名 - String changeClassName = StringUtils.toCamelCase(genConfig.getTableName()); - // 判断是否去除表前缀 - if (StringUtils.isNotEmpty(genConfig.getPrefix())) { - className = StringUtils.toCapitalizeCamelCase(StrUtil.removePrefix(genConfig.getTableName(), genConfig.getPrefix())); - changeClassName = StringUtils.toCamelCase(StrUtil.removePrefix(genConfig.getTableName(), genConfig.getPrefix())); - } - // 保存类名 - genMap.put("className", className); - // 保存小写开头的类名 - genMap.put("changeClassName", changeClassName); - // 存在 Timestamp 字段 - genMap.put("hasTimestamp", false); - // 查询类中存在 Timestamp 字段 - genMap.put("queryHasTimestamp", false); - // 存在 BigDecimal 字段 - genMap.put("hasBigDecimal", false); - // 查询类中存在 BigDecimal 字段 - genMap.put("queryHasBigDecimal", false); - // 是否需要创建查询 - genMap.put("hasQuery", false); - // 自增主键 - genMap.put("auto", false); - // 存在字典 - genMap.put("hasDict", false); - // 存在日期注解 - genMap.put("hasDateAnnotation", false); - // 保存字段信息 - List> columns = new ArrayList<>(); - // 保存查询字段的信息 - List> queryColumns = new ArrayList<>(); - // 存储字典信息 - List dicts = new ArrayList<>(); - // 存储 between 信息 - List> betweens = new ArrayList<>(); - // 存储不为空的字段信息 - List> isNotNullColumns = new ArrayList<>(); - - for (ColumnInfo column : columnInfos) { - Map listMap = new HashMap<>(16); - // 字段描述 - listMap.put("remark", column.getRemark()); - // 字段类型 - listMap.put("columnKey", column.getKeyType()); - // 主键类型 - String colType = ColUtil.cloToJava(column.getColumnType()); - // 小写开头的字段名 - String changeColumnName = StringUtils.toCamelCase(column.getColumnName()); - // 大写开头的字段名 - String capitalColumnName = StringUtils.toCapitalizeCamelCase(column.getColumnName()); - if (PK.equals(column.getKeyType())) { - // 存储主键类型 - genMap.put("pkColumnType", colType); - // 存储小写开头的字段名 - genMap.put("pkChangeColName", changeColumnName); - // 存储大写开头的字段名 - genMap.put("pkCapitalColName", capitalColumnName); - } - // 是否存在 Timestamp 类型的字段 - if (TIMESTAMP.equals(colType)) { - genMap.put("hasTimestamp", true); - } - // 是否存在 BigDecimal 类型的字段 - if (BIGDECIMAL.equals(colType)) { - genMap.put("hasBigDecimal", true); - } - // 主键是否自增 - if (EXTRA.equals(column.getExtra())) { - genMap.put("auto", true); - } - // 主键存在字典 - if (StringUtils.isNotBlank(column.getDictName())) { - genMap.put("hasDict", true); - dicts.add(column.getDictName()); - } - - // 存储字段类型 - listMap.put("columnType", colType); - // 存储字原始段名称 - listMap.put("columnName", column.getColumnName()); - // 不为空 - listMap.put("istNotNull", column.getNotNull()); - // 字段列表显示 - listMap.put("columnShow", column.getListShow()); - // 表单显示 - listMap.put("formShow", column.getFormShow()); - // 表单组件类型 - listMap.put("formType", StringUtils.isNotBlank(column.getFormType()) ? column.getFormType() : "Input"); - // 小写开头的字段名称 - listMap.put("changeColumnName", changeColumnName); - //大写开头的字段名称 - listMap.put("capitalColumnName", capitalColumnName); - // 字典名称 - listMap.put("dictName", column.getDictName()); - // 日期注解 - listMap.put("dateAnnotation", column.getDateAnnotation()); - if (StringUtils.isNotBlank(column.getDateAnnotation())) { - genMap.put("hasDateAnnotation", true); - } - // 添加非空字段信息 - if (column.getNotNull()) { - isNotNullColumns.add(listMap); - } - // 判断是否有查询,如有则把查询的字段set进columnQuery - if (!StringUtils.isBlank(column.getQueryType())) { - // 查询类型 - listMap.put("queryType", column.getQueryType()); - // 是否存在查询 - genMap.put("hasQuery", true); - if (TIMESTAMP.equals(colType)) { - // 查询中存储 Timestamp 类型 - genMap.put("queryHasTimestamp", true); - } - if (BIGDECIMAL.equals(colType)) { - // 查询中存储 BigDecimal 类型 - genMap.put("queryHasBigDecimal", true); - } - if ("between".equalsIgnoreCase(column.getQueryType())) { - betweens.add(listMap); - } else { - // 添加到查询列表中 - queryColumns.add(listMap); - } - } - // 添加到字段列表中 - columns.add(listMap); - } - // 保存字段列表 - genMap.put("columns", columns); - // 保存查询列表 - genMap.put("queryColumns", queryColumns); - // 保存字段列表 - genMap.put("dicts", dicts); - // 保存查询列表 - genMap.put("betweens", betweens); - // 保存非空字段信息 - genMap.put("isNotNullColumns", isNotNullColumns); - return genMap; - } - - /** - * 定义后端文件路径以及名称 - */ - private static String getAdminFilePath(String templateName, GenConfig genConfig, String className, String rootPath) { - String projectPath = rootPath + File.separator + genConfig.getModuleName(); - String packagePath = projectPath + File.separator + "src" + File.separator + "main" + File.separator + "java" + File.separator; - if (!ObjectUtils.isEmpty(genConfig.getPack())) { - packagePath += genConfig.getPack().replace(".", File.separator) + File.separator; - } - - if ("Entity".equals(templateName)) { - return packagePath + "domain" + File.separator + className + ".java"; - } - - if ("Controller".equals(templateName)) { - return packagePath + "rest" + File.separator + className + "Controller.java"; - } - - if ("Service".equals(templateName)) { - return packagePath + "service" + File.separator + className + "Service.java"; - } - - if ("ServiceImpl".equals(templateName)) { - return packagePath + "service" + File.separator + "impl" + File.separator + className + "ServiceImpl.java"; - } - - if ("Dto".equals(templateName)) { - return packagePath + "service" + File.separator + "dto" + File.separator + className + "Dto.java"; - } - - if ("QueryCriteria".equals(templateName)) { - return packagePath + "service" + File.separator + "dto" + File.separator + className + "QueryCriteria.java"; - } - - if ("Mapper".equals(templateName)) { - return packagePath + "service" + File.separator + "mapstruct" + File.separator + className + "Mapper.java"; - } - - if ("Repository".equals(templateName)) { - return packagePath + "repository" + File.separator + className + "Repository.java"; - } - - return null; - } - - /** - * 定义前端文件路径以及名称 - */ - private static String getFrontFilePath(String templateName, String apiPath, String path, String apiName) { - - if ("api".equals(templateName)) { - return apiPath + File.separator + apiName + ".js"; - } - - if ("index".equals(templateName)) { - return path + File.separator + "index.vue"; - } - - return null; - } - - private static void genFile(File file, Template template, Map map) throws IOException { - // 生成目标文件 - Writer writer = null; - try { - FileUtil.touch(file); - writer = new FileWriter(file); - template.render(map, writer); - } catch (TemplateException | IOException e) { - throw new RuntimeException(e); - } finally { - assert writer != null; - writer.close(); - } - } -} diff --git a/wjcy-logging/pom.xml b/wjcy-logging/pom.xml deleted file mode 100644 index 98d6734..0000000 --- a/wjcy-logging/pom.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - wjcy - me.zhengjie - 1.0 - - 4.0.0 - - wjcy-logging - 日志模块 - - - - me.zhengjie - wjcy-common - 1.0 - - - \ No newline at end of file diff --git a/wjcy-logging/src/main/java/me/zhengjie/annotation/Log.java b/wjcy-logging/src/main/java/me/zhengjie/annotation/Log.java deleted file mode 100644 index ac0a0cd..0000000 --- a/wjcy-logging/src/main/java/me/zhengjie/annotation/Log.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.annotation; - -import me.zhengjie.annotation.type.LogActionType; -import me.zhengjie.annotation.type.LogDaoType; -import me.zhengjie.annotation.type.LogGetIdType; -import me.zhengjie.annotation.type.LogGetValueType; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @author Zheng Jie - * @date 2018-11-24 - */ -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -public @interface Log { - String value() default ""; - - String[] daoNames() default {}; - - LogGetIdType[] idTypes() default {LogGetIdType.ID}; - - LogGetValueType[] valuesTypes() default {LogGetValueType.ID}; - - LogDaoType daoType() default LogDaoType.MyBATISPLUS; - - boolean trueList() default false; - - /** - * 是否启用 - * - * @return - */ - boolean enable() default true; - - LogActionType type() default LogActionType.SELECT; -} diff --git a/wjcy-logging/src/main/java/me/zhengjie/annotation/type/LogActionType.java b/wjcy-logging/src/main/java/me/zhengjie/annotation/type/LogActionType.java deleted file mode 100644 index e99d671..0000000 --- a/wjcy-logging/src/main/java/me/zhengjie/annotation/type/LogActionType.java +++ /dev/null @@ -1,34 +0,0 @@ -package me.zhengjie.annotation.type; - -/** - *

- * 日志类型 - *

- * - * @Author xx - * @Date 2021/7/22 - **/ -public enum LogActionType { - /** - * 增删改查 - */ - ADD("新增"), - SELECT("查询"), - UPDATE("更新"), - DELETE("删除"), - LOGIN("登录"), - EXPORT("导出"); - private String value; - - LogActionType(String value) { - this.value = value; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } -} diff --git a/wjcy-logging/src/main/java/me/zhengjie/annotation/type/LogDaoType.java b/wjcy-logging/src/main/java/me/zhengjie/annotation/type/LogDaoType.java deleted file mode 100644 index 2c96f80..0000000 --- a/wjcy-logging/src/main/java/me/zhengjie/annotation/type/LogDaoType.java +++ /dev/null @@ -1,30 +0,0 @@ -package me.zhengjie.annotation.type; - -/** - *

- *日志使用dao类型 - *

- * - * @Author xx - * @Date 2021/7/22 - **/ -public enum LogDaoType { - /** - * 增删改查 - */ - MyBATISPLUS("myabtisPlus"), - SPRINGDATAJPA("springDataJpa"); - private String value; - - LogDaoType(String value) { - this.value = value; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } -} diff --git a/wjcy-logging/src/main/java/me/zhengjie/annotation/type/LogGetIdType.java b/wjcy-logging/src/main/java/me/zhengjie/annotation/type/LogGetIdType.java deleted file mode 100644 index cb4a005..0000000 --- a/wjcy-logging/src/main/java/me/zhengjie/annotation/type/LogGetIdType.java +++ /dev/null @@ -1,36 +0,0 @@ -package me.zhengjie.annotation.type; - -/** - *

- * 日志获取修改前信息使用id类型 具体有别的在具体添加 - *

- * - * @Author xx - * @Date 2021/7/22 - **/ -public enum LogGetIdType { - - /** ID */ - ID("id"), - /** IDS */ - IDS("ids"), - /** MEMBER_ID */ - MEMBER_ID("memberId"), - /** AUTHMEMBER_ID */ - AUTHMEMBER_ID("authMemberId"), - /** ROOM_Id */ - ROOM_Id("roomId"); - private String value; - - LogGetIdType(String value) { - this.value = value; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } -} diff --git a/wjcy-logging/src/main/java/me/zhengjie/annotation/type/LogGetValueType.java b/wjcy-logging/src/main/java/me/zhengjie/annotation/type/LogGetValueType.java deleted file mode 100644 index 1024cbb..0000000 --- a/wjcy-logging/src/main/java/me/zhengjie/annotation/type/LogGetValueType.java +++ /dev/null @@ -1,32 +0,0 @@ -package me.zhengjie.annotation.type; - -/** - *

- * 日志获取修改前信息使用id对应值 具体有别的在具体添加 - *

- * - * @Author xx - * @Date 2021/7/22 - **/ -public enum LogGetValueType { - - /** ID */ - ID("id"), - /** MEMBER_ID */ - MEMBER_ID("memberId"), - /** ROOM_ID */ - ROOM_ID("roomId"); - private String value; - - LogGetValueType(String value) { - this.value = value; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } -} diff --git a/wjcy-logging/src/main/java/me/zhengjie/aspect/LogAspect.java b/wjcy-logging/src/main/java/me/zhengjie/aspect/LogAspect.java deleted file mode 100644 index 01bce24..0000000 --- a/wjcy-logging/src/main/java/me/zhengjie/aspect/LogAspect.java +++ /dev/null @@ -1,98 +0,0 @@ -///* -// * Copyright 2019-2020 Zheng Jie -// * -// * Licensed under the Apache License, Version 2.0 (the "License"); -// * you may not use this file except in compliance with the License. -// * You may obtain a copy of the License at -// * -// * http://www.apache.org/licenses/LICENSE-2.0 -// * -// * Unless required by applicable law or agreed to in writing, software -// * distributed under the License is distributed on an "AS IS" BASIS, -// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// * See the License for the specific language governing permissions and -// * limitations under the License. -// */ -//package me.zhengjie.aspect; -// -//import lombok.extern.slf4j.Slf4j; -//import me.zhengjie.domain.Log; -//import me.zhengjie.service.LogService; -//import me.zhengjie.utils.RequestHolder; -//import me.zhengjie.utils.SecurityUtils; -//import me.zhengjie.utils.StringUtils; -//import me.zhengjie.utils.ThrowableUtil; -//import org.aspectj.lang.JoinPoint; -//import org.aspectj.lang.ProceedingJoinPoint; -//import org.aspectj.lang.annotation.AfterThrowing; -//import org.aspectj.lang.annotation.Around; -//import org.aspectj.lang.annotation.Aspect; -//import org.aspectj.lang.annotation.Pointcut; -//import org.springframework.stereotype.Component; -//import javax.servlet.http.HttpServletRequest; -// -///** -// * @author Zheng Jie -// * @date 2018-11-24 -// */ -//@Component -//@Aspect -//@Slf4j -//public class LogAspect { -// -// private final LogService logService; -// -// ThreadLocal currentTime = new ThreadLocal<>(); -// -// public LogAspect(LogService logService) { -// this.logService = logService; -// } -// -// /** -// * 配置切入点 -// */ -// @Pointcut("@annotation(me.zhengjie.annotation.Log)") -// public void logPointcut() { -// // 该方法无方法体,主要为了让同类中其他方法使用此切入点 -// } -// -// /** -// * 配置环绕通知,使用在方法logPointcut()上注册的切入点 -// * -// * @param joinPoint join point for advice -// */ -// @Around("logPointcut()") -// public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable { -// Object result; -// currentTime.set(System.currentTimeMillis()); -// result = joinPoint.proceed(); -// Log log = new Log("INFO",System.currentTimeMillis() - currentTime.get()); -// currentTime.remove(); -// HttpServletRequest request = RequestHolder.getHttpServletRequest(); -// logService.save(getUsername(), StringUtils.getBrowser(request), StringUtils.getIp(request),joinPoint, log); -// return result; -// } -// -// /** -// * 配置异常通知 -// * -// * @param joinPoint join point for advice -// * @param e exception -// */ -// @AfterThrowing(pointcut = "logPointcut()", throwing = "e") -// public void logAfterThrowing(JoinPoint joinPoint, Throwable e) { -// Log log = new Log("ERROR",System.currentTimeMillis() - currentTime.get()); -// currentTime.remove(); -// log.setExceptionDetail(ThrowableUtil.getStackTrace(e).getBytes()); -// HttpServletRequest request = RequestHolder.getHttpServletRequest(); -// logService.save(getUsername(), StringUtils.getBrowser(request), StringUtils.getIp(request), (ProceedingJoinPoint)joinPoint, log); -// } -// -// public String getUsername() { -// try { -// return SecurityUtils.getCurrentUsername(); -// }catch (Exception e){ -// return ""; -// } -// } -//} diff --git a/wjcy-logging/src/main/java/me/zhengjie/domain/Log.java b/wjcy-logging/src/main/java/me/zhengjie/domain/Log.java deleted file mode 100644 index baed7df..0000000 --- a/wjcy-logging/src/main/java/me/zhengjie/domain/Log.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.domain; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import org.hibernate.annotations.CreationTimestamp; -import javax.persistence.*; -import java.io.Serializable; -import java.sql.Timestamp; - - -/** - * @author Zheng Jie - * @date 2018-11-24 - */ -@Entity -@Getter -@Setter -@Table(name = "sys_log") -@NoArgsConstructor -public class Log implements Serializable { - - @Id - @Column(name = "log_id") - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - /** 操作用户 */ - private String username; - - /** 描述 */ - private String description; - - /** 方法名 */ - private String method; - - /** 参数 */ - private String params; - - /** 日志类型 */ - private String logType; - - /** 请求ip */ - private String requestIp; - - /** 地址 */ - private String address; - - /** 浏览器 */ - private String browser; - - /** 请求耗时 */ - private Long time; - - /** 异常详细 */ - private String exceptionDetail; - - /** 创建日期 */ - @CreationTimestamp - private Timestamp createTime; - - /** 用户类型 */ - private Integer type; - - /** 日志记录 */ - private String platParams; - - @Transient - private Boolean trueList; - - public Log(String logType, Long time) { - this.logType = logType; - this.time = time; - } - public Log(String logType, Long time, Integer type) { - this.logType = logType; - this.time = time; - this.type = type; - } -} diff --git a/wjcy-logging/src/main/java/me/zhengjie/enums/LogTypeEnum.java b/wjcy-logging/src/main/java/me/zhengjie/enums/LogTypeEnum.java deleted file mode 100644 index eb87f89..0000000 --- a/wjcy-logging/src/main/java/me/zhengjie/enums/LogTypeEnum.java +++ /dev/null @@ -1,33 +0,0 @@ -package me.zhengjie.enums; -/** - *

- * 日志类型 - *

- * - * @Author xx - * @Date 2021/7/22 - **/ -public enum LogTypeEnum { - /** - * 是否展示详情类型 - * 1 修改 - * 0 不展示 - * 2 新增 - */ - - NO_PLAT_PARAMS(0), - SHOW_PLAT_PARAMS(1), - SHOW_ADD_PARAMS(2), - SHOW_LOGIN_PARAMS(3); - - private final Integer value; - - private LogTypeEnum(Integer value) { - this.value = value; - } - - - public Integer value() { - return this.value; - } -} diff --git a/wjcy-logging/src/main/java/me/zhengjie/repository/LogRepository.java b/wjcy-logging/src/main/java/me/zhengjie/repository/LogRepository.java deleted file mode 100644 index 0414b3e..0000000 --- a/wjcy-logging/src/main/java/me/zhengjie/repository/LogRepository.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.repository; - -import me.zhengjie.domain.Log; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; -import org.springframework.data.jpa.repository.Modifying; -import org.springframework.data.jpa.repository.Query; -import org.springframework.stereotype.Repository; - -import java.util.List; - -/** - * @author Zheng Jie - * @date 2018-11-24 - */ -@Repository -public interface LogRepository extends JpaRepository, JpaSpecificationExecutor { - - /** - * 根据日志类型删除信息 - * @param logType 日志类型 - */ - @Modifying - @Query(value = "delete from sys_log where log_type = ?1", nativeQuery = true) - void deleteByLogType(String logType); - - /** - * 根据日志类型和显示类型删除信息 - * @param logType 日志类型 - */ - @Modifying - @Query(value = " delete from sys_log where log_type = ?1 and type in ?2",nativeQuery = true) - void deleteByLogTypeAndTypeContains(String logType, List typeList); -} diff --git a/wjcy-logging/src/main/java/me/zhengjie/rest/LogController.java b/wjcy-logging/src/main/java/me/zhengjie/rest/LogController.java deleted file mode 100644 index 23d27db..0000000 --- a/wjcy-logging/src/main/java/me/zhengjie/rest/LogController.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.rest; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import lombok.RequiredArgsConstructor; -import me.zhengjie.annotation.Log; -import me.zhengjie.dto.Dto; -import me.zhengjie.enums.LogTypeEnum; -import me.zhengjie.service.LogService; -import me.zhengjie.service.dto.LogQueryCriteria; -import me.zhengjie.utils.SecurityUtils; -import org.springframework.data.domain.Pageable; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.Arrays; - -/** - * @author Zheng Jie - * @date 2018-11-24 - */ -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/logs") -@Api(tags = "系统:日志管理") -public class LogController { - - private final LogService logService; - - @Log("导出操作日志数据") - @ApiOperation("导出操作日志数据") - @GetMapping(value = "/queryLog/download") - @PreAuthorize("@el.check('options:export')") - public void downloadLog(HttpServletResponse response, LogQueryCriteria criteria) throws IOException { - criteria.setLogType("INFO"); - criteria.setType(Arrays.asList(LogTypeEnum.SHOW_ADD_PARAMS.value(), LogTypeEnum.SHOW_PLAT_PARAMS.value(), LogTypeEnum.NO_PLAT_PARAMS.value())); - logService.download(logService.queryAll(criteria), response); - } - - @Log("导出登录日志数据") - @ApiOperation("导出登录日志数据") - @GetMapping(value = "/queryLogin/download") - @PreAuthorize("@el.check('login:export')") - public void downloadLogin(HttpServletResponse response, LogQueryCriteria criteria) throws IOException { - criteria.setLogType("INFO"); - criteria.setType(Arrays.asList(LogTypeEnum.SHOW_LOGIN_PARAMS.value())); - logService.download(logService.queryAll(criteria), response); - } - - @Log("导出错误数据") - @ApiOperation("导出错误数据") - @GetMapping(value = "/error/download") -// @PreAuthorize("@el.check()") - public void downloadErrorLog(HttpServletResponse response, LogQueryCriteria criteria) throws IOException { - criteria.setLogType("ERROR"); - logService.download(logService.queryAll(criteria), response); - } - - @GetMapping(value = "/queryLog") - @ApiOperation("日志查询") - @PreAuthorize("@el.check('options:list')") - public ResponseEntity queryLog(LogQueryCriteria criteria, Pageable pageable){ - criteria.setLogType("INFO"); - criteria.setType(Arrays.asList(LogTypeEnum.SHOW_ADD_PARAMS.value(), LogTypeEnum.SHOW_PLAT_PARAMS.value(), LogTypeEnum.NO_PLAT_PARAMS.value())); - return new ResponseEntity<>(logService.queryAll(criteria,pageable), HttpStatus.OK); - } - - @GetMapping(value = "/queryLogin") - @ApiOperation("日志查询") - @PreAuthorize("@el.check('login:list')") - public ResponseEntity queryLogin(LogQueryCriteria criteria, Pageable pageable){ - criteria.setLogType("INFO"); - criteria.setType(Arrays.asList(LogTypeEnum.SHOW_LOGIN_PARAMS.value())); - return new ResponseEntity<>(logService.queryAll(criteria,pageable), HttpStatus.OK); - } - - /** - * 根据id 修改前后日志变化详情 - * @param id - * @return - */ - @GetMapping(value = "/updateDetail/{id}") - @ApiOperation("日志查询") -// @PreAuthorize("@el.check()") - public Dto updateDetail(@PathVariable Long id){ - return Dto.returnResult(logService.queryUpdateDatail(id)); - } - - - - @GetMapping(value = "/user") - @ApiOperation("用户日志查询") - public ResponseEntity queryUserLog(LogQueryCriteria criteria, Pageable pageable){ - criteria.setLogType("INFO"); - criteria.setBlurry(SecurityUtils.getCurrentUsername()); - return new ResponseEntity<>(logService.queryAllByUser(criteria,pageable), HttpStatus.OK); - } - - @GetMapping(value = "/error") - @ApiOperation("错误日志查询") -// @PreAuthorize("@el.check()") - public ResponseEntity queryErrorLog(LogQueryCriteria criteria, Pageable pageable){ - criteria.setLogType("ERROR"); - return new ResponseEntity<>(logService.queryAll(criteria,pageable), HttpStatus.OK); - } - - @GetMapping(value = "/error/{id}") - @ApiOperation("日志异常详情查询") -// @PreAuthorize("@el.check()") - public ResponseEntity queryErrorLogs(@PathVariable Long id){ - return new ResponseEntity<>(logService.findByErrDetail(id), HttpStatus.OK); - } - @DeleteMapping(value = "/del/error") - @Log("删除所有ERROR日志") - @ApiOperation("删除所有ERROR日志") -// @PreAuthorize("@el.check()") - public ResponseEntity delAllErrorLog(){ - logService.delAllByError(); - return new ResponseEntity<>(HttpStatus.OK); - } - - @DeleteMapping(value = "/del/logInfo") - @Log("删除所有INFO操作日志") - @ApiOperation("删除所有INFO操作日志") - @PreAuthorize("@el.check('options:del')") - public ResponseEntity delAllLogInfo(){ - logService.deleteByLogTypeAndType("INFO", Arrays.asList(LogTypeEnum.SHOW_ADD_PARAMS.value(), LogTypeEnum.NO_PLAT_PARAMS.value(), LogTypeEnum.SHOW_PLAT_PARAMS.value())); - return new ResponseEntity<>(HttpStatus.OK); - } - - @DeleteMapping(value = "/del/loginInfo") - @Log("删除所有INFO登录日志") - @ApiOperation("删除所有INFO登录日志") - @PreAuthorize("@el.check('login:del')") - public ResponseEntity delAllLoginInfo(){ - logService.deleteByLogTypeAndType("INFO", Arrays.asList(LogTypeEnum.SHOW_LOGIN_PARAMS.value())); - return new ResponseEntity<>(HttpStatus.OK); - } -} diff --git a/wjcy-logging/src/main/java/me/zhengjie/service/LogService.java b/wjcy-logging/src/main/java/me/zhengjie/service/LogService.java deleted file mode 100644 index 0dc6497..0000000 --- a/wjcy-logging/src/main/java/me/zhengjie/service/LogService.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.service; - -import me.zhengjie.domain.Log; -import me.zhengjie.service.dto.LogQueryCriteria; -import org.aspectj.lang.ProceedingJoinPoint; -import org.springframework.data.domain.Pageable; -import org.springframework.scheduling.annotation.Async; - -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.List; - -/** - * @author Zheng Jie - * @date 2018-11-24 - */ -public interface LogService { - - /** - * 分页查询 - * @param criteria 查询条件 - * @param pageable 分页参数 - * @return / - */ - Object queryAll(LogQueryCriteria criteria, Pageable pageable); - - /** - * 查询全部数据 - * @param criteria 查询条件 - * @return / - */ - List queryAll(LogQueryCriteria criteria); - - /** - * 查询修改数据详情 - * @param id 查询条件 - * @return / - */ - Object queryUpdateDatail(Long id); - - /** - * 查询用户日志 - * @param criteria 查询条件 - * @param pageable 分页参数 - * @return - - */ - Object queryAllByUser(LogQueryCriteria criteria, Pageable pageable); - - /** - * 保存日志数据 - * @param username 用户 - * @param browser 浏览器 - * @param ip 请求IP - * @param joinPoint / - * @param log 日志实体 - */ - @Async - void save(String username, String browser, String ip, ProceedingJoinPoint joinPoint, Log log, Object beforeJson); - - /** - * 查询异常详情 - * @param id 日志ID - * @return Object - */ - Object findByErrDetail(Long id); - - /** - * 导出日志 - * @param logs 待导出的数据 - * @param response / - * @throws IOException / - */ - void download(List logs, HttpServletResponse response) throws IOException; - - /** - * 删除所有错误日志 - */ - void delAllByError(); - - /** - * 删除所有INFO日志 - */ - void delAllByInfo(); - - void deleteByLogTypeAndType(String logType, List typeList); -} diff --git a/wjcy-logging/src/main/java/me/zhengjie/service/dto/LogErrorDTO.java b/wjcy-logging/src/main/java/me/zhengjie/service/dto/LogErrorDTO.java deleted file mode 100644 index bc0d4ec..0000000 --- a/wjcy-logging/src/main/java/me/zhengjie/service/dto/LogErrorDTO.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.service.dto; - -import lombok.Data; -import java.io.Serializable; -import java.sql.Timestamp; - -/** -* @author Zheng Jie -* @date 2019-5-22 -*/ -@Data -public class LogErrorDTO implements Serializable { - - private Long id; - - private String username; - - private String description; - - private String method; - - private String params; - - private String browser; - - private String requestIp; - - private String address; - - private Timestamp createTime; -} \ No newline at end of file diff --git a/wjcy-logging/src/main/java/me/zhengjie/service/dto/LogQueryCriteria.java b/wjcy-logging/src/main/java/me/zhengjie/service/dto/LogQueryCriteria.java deleted file mode 100644 index dcc41f6..0000000 --- a/wjcy-logging/src/main/java/me/zhengjie/service/dto/LogQueryCriteria.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.service.dto; - -import lombok.Data; -import me.zhengjie.annotation.Query; -import java.sql.Timestamp; -import java.util.List; - -/** - * 日志查询类 - * @author Zheng Jie - * @date 2019-6-4 09:23:07 - */ -@Data -public class LogQueryCriteria { - - @Query(blurry = "username,description,address,requestIp,method,params") - private String blurry; - - @Query - private String logType; - - @Query(type = Query.Type.IN) - private List type; - - @Query(type = Query.Type.BETWEEN) - private List createTime; -} diff --git a/wjcy-logging/src/main/java/me/zhengjie/service/dto/LogSmallDTO.java b/wjcy-logging/src/main/java/me/zhengjie/service/dto/LogSmallDTO.java deleted file mode 100644 index d074fd1..0000000 --- a/wjcy-logging/src/main/java/me/zhengjie/service/dto/LogSmallDTO.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.service.dto; - -import lombok.Data; -import java.io.Serializable; -import java.sql.Timestamp; - -/** - * @author Zheng Jie - * @date 2019-5-22 - */ -@Data -public class LogSmallDTO implements Serializable { - - private String description; - - private String requestIp; - - private Long time; - - private String address; - - private String browser; - - private Timestamp createTime; -} diff --git a/wjcy-logging/src/main/java/me/zhengjie/service/impl/LogServiceImpl.java b/wjcy-logging/src/main/java/me/zhengjie/service/impl/LogServiceImpl.java deleted file mode 100644 index 2d449fa..0000000 --- a/wjcy-logging/src/main/java/me/zhengjie/service/impl/LogServiceImpl.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.service.impl; - -import cn.hutool.core.lang.Dict; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.json.JSONArray; -import cn.hutool.json.JSONObject; -import cn.hutool.json.JSONUtil; -import lombok.RequiredArgsConstructor; -import me.zhengjie.domain.Log; -import me.zhengjie.enums.LogTypeEnum; -import me.zhengjie.repository.LogRepository; -import me.zhengjie.service.LogService; -import me.zhengjie.service.dto.LogQueryCriteria; -import me.zhengjie.service.mapstruct.LogErrorMapper; -import me.zhengjie.service.mapstruct.LogSmallMapper; -import me.zhengjie.utils.*; -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.reflect.MethodSignature; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestParam; - -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.lang.reflect.Method; -import java.lang.reflect.Parameter; -import java.util.*; - -/** - * @author Zheng Jie - * @date 2018-11-24 - */ -@Service -@RequiredArgsConstructor -public class LogServiceImpl implements LogService { - private static final Logger log = LoggerFactory.getLogger(LogServiceImpl.class); - private final LogRepository logRepository; - private final LogErrorMapper logErrorMapper; - private final LogSmallMapper logSmallMapper; - - - @Override - public Object queryAll(LogQueryCriteria criteria, Pageable pageable) { - Page page = logRepository.findAll(((root, criteriaQuery, cb) -> QueryHelp.getPredicate(root, criteria, cb)), pageable); - String status = "ERROR"; - if (status.equals(criteria.getLogType())) { - return PageUtil.toPage(page.map(logErrorMapper::toDto)); - } - return page; - } - - @Override - public List queryAll(LogQueryCriteria criteria) { - return logRepository.findAll(((root, criteriaQuery, cb) -> QueryHelp.getPredicate(root, criteria, cb))); - } - - @Override - public Object queryUpdateDatail(Long id) { - Log log = logRepository.findById(id).orElseGet(Log::new); - ValidationUtil.isNull(log.getId(), "Log", "id", id); - String details = log.getPlatParams(); - return Dict.create().set("platParams", new String(ObjectUtil.isNotNull(details) ? details : "")); - } - - @Override - public Object queryAllByUser(LogQueryCriteria criteria, Pageable pageable) { - Page page = logRepository.findAll(((root, criteriaQuery, cb) -> QueryHelp.getPredicate(root, criteria, cb)), pageable); - return PageUtil.toPage(page.map(logSmallMapper::toDto)); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void save(String username, String browser, String ip, ProceedingJoinPoint joinPoint, Log log, Object beforeJson) { - - MethodSignature signature = (MethodSignature) joinPoint.getSignature(); - Method method = signature.getMethod(); - me.zhengjie.annotation.Log aopLog = method.getAnnotation(me.zhengjie.annotation.Log.class); - - // 方法路径 - String methodName = joinPoint.getTarget().getClass().getName() + "." + signature.getName() + "()"; - - //参数值 - List argValues = new ArrayList<>(Arrays.asList(joinPoint.getArgs())); - - // 修改前的数据整理,仅仅只存储变化的数据即可 - StringBuilder params = new StringBuilder("[ "); - JSONArray jsonArray = new JSONArray(); - boolean showBoolean = false; - if (ObjectUtil.isNotEmpty(beforeJson) && LogTypeEnum.SHOW_PLAT_PARAMS.value().equals(log.getType())) { - jsonArray.add(jsonUnion(argValues.get(0), beforeJson)); - } - - if (LogTypeEnum.SHOW_PLAT_PARAMS.value().equals(log.getType()) || LogTypeEnum.SHOW_ADD_PARAMS.value().equals(log.getType())) { - showBoolean = true; - } - - //参数名称 - for (Object argValue : argValues) { - if (ObjectUtil.isNotEmpty(argValue)) { - params.append(EmptyAttributeFiler.emptyAttributeFilerToString(argValue)).append(" "); - if (showBoolean) { - if (log.getTrueList()) { - jsonArray = new JSONArray(argValue); - } else { - JSONObject tempBefJsonObj = new JSONObject(argValue); - jsonArray.add(tempBefJsonObj); - } - } - } - } - - // 描述 - if (log != null && ObjectUtil.isEmpty(log.getDescription())) { - log.setDescription(aopLog.value()); - } - assert log != null; - log.setRequestIp(ip); - - String loginPath = "login"; - if (loginPath.equals(signature.getName())) { - try { - username = new JSONObject(argValues.get(0)).get("username").toString(); - } catch (Exception e) { - LogServiceImpl.log.error(e.getMessage(), e); - } - } - -// log.setAddress(IpUtils.getIpAddr()); - log.setMethod(methodName); - log.setUsername(username); - log.setParams(params.toString() + " ]"); - if (showBoolean) { - log.setPlatParams(jsonArray.toString()); - } - log.setBrowser(browser); - logRepository.save(log); - } - - /** - * 赋值资源 - * 根据source中的key除吊target中多余的数据。 - * 使target数据结构保持和source一致 - * @param source - * @param target - * @return - */ - public JSONObject jsonUnion(Object source, Object target) { - - JSONObject targetObj = new JSONObject(target); - JSONObject sourceObj = new JSONObject(source); - - - Map objMap = new LinkedHashMap<>(); - - if (ObjectUtil.isNotEmpty(sourceObj)) { - for (Map.Entry sourceEntry: sourceObj.entrySet()) { - String key = sourceEntry.getKey(); - Object value = sourceEntry.getValue(); - - // 判断是否存在key - if (targetObj.containsKey(key)) { - objMap.put(key, targetObj.get(key)); - } - } - } - - return new JSONObject(objMap); - } - - @Override - public Object findByErrDetail(Long id) { - Log log = logRepository.findById(id).orElseGet(Log::new); - ValidationUtil.isNull(log.getId(), "Log", "id", id); - String details = log.getExceptionDetail(); - return Dict.create().set("exception", new String(ObjectUtil.isNotNull(details) ? details : "")); - } - - @Override - public void download(List logs, HttpServletResponse response) throws IOException { - List> list = new ArrayList<>(); - for (Log log : logs) { - Map map = new LinkedHashMap<>(); - map.put("用户名", log.getUsername()); - map.put("IP", log.getRequestIp()); - map.put("IP来源", log.getAddress()); - map.put("描述", log.getDescription()); - map.put("浏览器", log.getBrowser()); - map.put("请求耗时/毫秒", log.getTime()); - map.put("异常详情", new String(ObjectUtil.isNotNull(log.getExceptionDetail()) ? log.getExceptionDetail() : "")); - map.put("创建日期", log.getCreateTime()); - list.add(map); - } - FileUtil.downloadExcel(list, response); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delAllByError() { - logRepository.deleteByLogType("ERROR"); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delAllByInfo() { - logRepository.deleteByLogType("INFO"); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void deleteByLogTypeAndType(String logType, List typeList) { - logRepository.deleteByLogTypeAndTypeContains(logType, typeList); - } -} diff --git a/wjcy-logging/src/main/java/me/zhengjie/service/mapstruct/LogErrorMapper.java b/wjcy-logging/src/main/java/me/zhengjie/service/mapstruct/LogErrorMapper.java deleted file mode 100644 index 3ae02c9..0000000 --- a/wjcy-logging/src/main/java/me/zhengjie/service/mapstruct/LogErrorMapper.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.service.mapstruct; - -import me.zhengjie.base.BaseMapper; -import me.zhengjie.domain.Log; -import me.zhengjie.service.dto.LogErrorDTO; -import org.mapstruct.Mapper; -import org.mapstruct.ReportingPolicy; - -/** - * @author Zheng Jie - * @date 2019-5-22 - */ -@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface LogErrorMapper extends BaseMapper { - -} \ No newline at end of file diff --git a/wjcy-logging/src/main/java/me/zhengjie/service/mapstruct/LogSmallMapper.java b/wjcy-logging/src/main/java/me/zhengjie/service/mapstruct/LogSmallMapper.java deleted file mode 100644 index 9f2972a..0000000 --- a/wjcy-logging/src/main/java/me/zhengjie/service/mapstruct/LogSmallMapper.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.service.mapstruct; - -import me.zhengjie.base.BaseMapper; -import me.zhengjie.domain.Log; -import me.zhengjie.service.dto.LogSmallDTO; -import org.mapstruct.Mapper; -import org.mapstruct.ReportingPolicy; - -/** - * @author Zheng Jie - * @date 2019-5-22 - */ -@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface LogSmallMapper extends BaseMapper { - -} \ No newline at end of file diff --git a/wjcy-system/pom.xml b/wjcy-system/pom.xml deleted file mode 100644 index 0998697..0000000 --- a/wjcy-system/pom.xml +++ /dev/null @@ -1,128 +0,0 @@ - - - - wjcy - me.zhengjie - 1.0 - - 4.0.0 - jar - wjcy-system - 核心模块 - - - 0.11.1 - - 5.8.0 - - - - - - me.zhengjie - wjcy-generator - 1.0 - - - me.zhengjie - wjcy-common - - - - - - - me.zhengjie - wjcy-tools - 1.0 - - - - - org.springframework.boot - spring-boot-starter-websocket - - - - - io.jsonwebtoken - jjwt-api - ${jjwt.version} - - - io.jsonwebtoken - jjwt-impl - ${jjwt.version} - - - io.jsonwebtoken - jjwt-jackson - ${jjwt.version} - - - - - ch.ethz.ganymed - ganymed-ssh2 - build210 - - - com.jcraft - jsch - 0.1.55 - - - - - com.github.oshi - oshi-core - 5.7.1 - - - - - org.quartz-scheduler - quartz - - - - - org.apache.rocketmq - rocketmq-client - 4.4.0 - - - - - - - - src/main/resources - - **/*.* - - - **/*.db - - true - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - org.apache.maven.plugins - maven-surefire-plugin - - true - - - - - diff --git a/wjcy-system/src/main/java/me/zhengjie/AppRun.java b/wjcy-system/src/main/java/me/zhengjie/AppRun.java deleted file mode 100644 index ed24406..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/AppRun.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie; - -import io.swagger.annotations.Api; -import me.zhengjie.annotation.rest.AnonymousGetMapping; -import me.zhengjie.utils.SpringContextHolder; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; -import org.springframework.boot.web.servlet.server.ServletWebServerFactory; -import org.springframework.context.annotation.Bean; -import org.springframework.data.jpa.repository.config.EnableJpaAuditing; -import org.springframework.scheduling.annotation.EnableAsync; -import org.springframework.transaction.annotation.EnableTransactionManagement; -import org.springframework.web.bind.annotation.RestController; - -/** - * 开启审计功能 -> @EnableJpaAuditing - * - * @author Zheng Jie - * @date 2018/11/15 9:20:19 - */ -@EnableAsync -@RestController -@Api(hidden = true) -@SpringBootApplication -@EnableTransactionManagement -@EnableJpaAuditing(auditorAwareRef = "auditorAware") -public class AppRun { - - public static void main(String[] args) { - SpringApplication.run(AppRun.class, args); - } - - @Bean - public SpringContextHolder springContextHolder() { - return new SpringContextHolder(); - } - - @Bean - public ServletWebServerFactory webServerFactory() { - TomcatServletWebServerFactory fa = new TomcatServletWebServerFactory(); - fa.addConnectorCustomizers(connector -> connector.setProperty("relaxedQueryChars", "[]{}")); - return fa; - } - - /** - * 访问首页提示 - * - * @return / - */ - @AnonymousGetMapping("/") - public String index() { - return "Backend service started successfully"; - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/aspect/FormSubmissionAspect.java b/wjcy-system/src/main/java/me/zhengjie/aspect/FormSubmissionAspect.java deleted file mode 100644 index e1cfec0..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/aspect/FormSubmissionAspect.java +++ /dev/null @@ -1,93 +0,0 @@ -package me.zhengjie.aspect; - -import cn.hutool.core.util.ObjectUtil; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.annotation.FormSubmission; -import me.zhengjie.dto.Dto; -import me.zhengjie.modules.security.config.bean.SecurityProperties; -import me.zhengjie.utils.RedisUtils; -import me.zhengjie.utils.RequestHolder; -import org.aspectj.lang.JoinPoint; -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.AfterThrowing; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Pointcut; -import org.aspectj.lang.reflect.MethodSignature; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Map; - -import static me.zhengjie.config.constant.Constants.FORM_SUB_TOKEN; -import static me.zhengjie.error.ErrorCodeEnum.FORM_SUBMISSION_REPETITION_ERROR; - -/** - *

- * 表单提交 切面 - *

- * - * @author: rch - * @since: 2022-08-30 - */ -@Component -@Aspect -@Slf4j -public class FormSubmissionAspect { - @Resource - private RedisUtils redisUtils; - @Resource - private SecurityProperties securityProperties; - - /** - * 配置切入点 - */ - @Pointcut("@annotation(me.zhengjie.annotation.FormSubmission)") - public void formSubMissionAspectPointcut() { - } - - /** 配置环绕通知,formSubMissionAspectPointcut()上注册的切入点 */ - @Around("formSubMissionAspectPointcut()") - public Object formSubMissionAspectAround(ProceedingJoinPoint joinPoint) throws Throwable { - MethodSignature signature = (MethodSignature) joinPoint.getSignature(); - Method signatureMethod = signature.getMethod(); - FormSubmission formSubMission = signatureMethod.getAnnotation(FormSubmission.class); - HttpServletRequest request = RequestHolder.getHttpServletRequest(); - String uri = request.getRequestURI(); - String token = request.getHeader(securityProperties.getHeader()); -// Object[] args = joinPoint.getArgs(); // 参数值 - if (formSubMission.isOpen() && ObjectUtil.isNotEmpty(token)) { - -// String key = FORM_SUB_TOKEN + uri + args.toString(); - String key = FORM_SUB_TOKEN + uri; - Long count = redisUtils.incrAndExpire(key, formSubMission.second()); - /** 设置成功count=1 */ - if (count == null || count > 1) { - return Dto.getInstance(FORM_SUBMISSION_REPETITION_ERROR); - } - } - return joinPoint.proceed(); - } - - /** 配置异常通知 */ - @AfterThrowing(pointcut = "formSubMissionAspectPointcut()", throwing = "e") - public void formSubMissionAspectAfterThrowing(JoinPoint joinPoint, Exception e) { - HttpServletRequest request = RequestHolder.getHttpServletRequest(); - String uri = request.getRequestURI(); - // 接口请求的参数 - Object[] args = joinPoint.getArgs(); - // 记录报错信息 - log.error("表单重复提交验证报错,请求的接口地址:{},请求参数:{}",uri,args); - } - - - private Map transitionToMap(Object object) { - if (ObjectUtil.isNotNull(object) && object instanceof Map){ - return (Map) object; - } - return new HashMap(16); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/config/ConfigurerAdapter.java b/wjcy-system/src/main/java/me/zhengjie/config/ConfigurerAdapter.java deleted file mode 100644 index e76512b..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/config/ConfigurerAdapter.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.config; - -import com.alibaba.fastjson.serializer.SerializerFeature; -import com.alibaba.fastjson.support.config.FastJsonConfig; -import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.MediaType; -import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.web.cors.CorsConfiguration; -import org.springframework.web.cors.UrlBasedCorsConfigurationSource; -import org.springframework.web.filter.CorsFilter; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; - -/** - * WebMvcConfigurer - * - * @author Zheng Jie - * @date 2018-11-30 - */ -@Configuration -@EnableWebMvc -public class ConfigurerAdapter implements WebMvcConfigurer { - - /** 文件配置 */ - private final FileProperties properties; - - public ConfigurerAdapter(FileProperties properties) { - this.properties = properties; - } - - @Bean - public CorsFilter corsFilter() { - UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); - CorsConfiguration config = new CorsConfiguration(); - config.setAllowCredentials(true); - config.addAllowedOrigin("*"); - config.addAllowedHeader("*"); - config.addAllowedMethod("*"); - source.registerCorsConfiguration("/**", config); - return new CorsFilter(source); - } - - @Override - public void addResourceHandlers(ResourceHandlerRegistry registry) { - FileProperties.ElPath path = properties.getPath(); - String avatarUtl = "file:" + path.getAvatar().replace("\\","/"); - String pathUtl = "file:" + path.getPath().replace("\\","/"); - registry.addResourceHandler("/avatar/**").addResourceLocations(avatarUtl).setCachePeriod(0); - registry.addResourceHandler("/file/**").addResourceLocations(pathUtl).setCachePeriod(0); - registry.addResourceHandler("/**").addResourceLocations("classpath:/META-INF/resources/").setCachePeriod(0); - } - - @Override - public void configureMessageConverters(List> converters) { - // 使用 fastjson 序列化,会导致 @JsonIgnore 失效,可以使用 @JSONField(serialize = false) 替换 - FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter(); - List supportMediaTypeList = new ArrayList<>(); - supportMediaTypeList.add(MediaType.APPLICATION_JSON_UTF8); - FastJsonConfig config = new FastJsonConfig(); - config.setDateFormat("yyyy-MM-dd HH:mm:ss"); - config.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect); - converter.setFastJsonConfig(config); - converter.setSupportedMediaTypes(supportMediaTypeList); - converter.setDefaultCharset(StandardCharsets.UTF_8); - converters.add(converter); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/config/CorsConfig.java b/wjcy-system/src/main/java/me/zhengjie/config/CorsConfig.java deleted file mode 100644 index 3cd3209..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/config/CorsConfig.java +++ /dev/null @@ -1,20 +0,0 @@ -package me.zhengjie.config; - -import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.config.annotation.InterceptorRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -/** - *

- * 跨域配置 - *

- * - * @Author xx - * @Date 2021/7/28 - **/ -@Configuration -public class CorsConfig implements WebMvcConfigurer { - @Override - public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(new CorsInterceptor()).addPathPatterns("/**"); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/config/GoogleAuthProperties.java b/wjcy-system/src/main/java/me/zhengjie/config/GoogleAuthProperties.java deleted file mode 100644 index bd5fcd0..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/config/GoogleAuthProperties.java +++ /dev/null @@ -1,58 +0,0 @@ -package me.zhengjie.config; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Configuration; -import org.springframework.stereotype.Component; - -/** - * Google Auth Properties - * @author rch - * @date 2020-08-25 - */ -@Component -@Configuration -public class GoogleAuthProperties { - - public static int SECRET_SIZE; - - public static String SEED; - - public static String RANDOM_NUMBER_ALGORITHM; - - public static String REDIS_GOOGLE_AUTH_KEY; - - public static String QR_CREATE_PREFIX_URL; - - /** default 3 - max 17 (from google docs)最多可偏移的时间*/ - public static int WINDOW_SIZE; - - @Value("${auth.secret_size}") - public void setSecretSize(int secretSize) { - SECRET_SIZE = secretSize; - } - - @Value("${auth.seed}") - public void setSEED(String SEED) { - GoogleAuthProperties.SEED = SEED; - } - - @Value("${auth.random_number_algorithm}") - public void setRandomNumberAlgorithm(String randomNumberAlgorithm) { - RANDOM_NUMBER_ALGORITHM = randomNumberAlgorithm; - } - - @Value("${auth.window_size}") - public void setWindowSize(int window_size) { - GoogleAuthProperties.WINDOW_SIZE = window_size; - } - - @Value("${auth.redis_google_auth_key}") - public void setRedisGoogleAuthKey(String redisGoogleAuthKey) { - REDIS_GOOGLE_AUTH_KEY = redisGoogleAuthKey; - } - - @Value("${auth.qr_create_prefix_url}") - public void setQrCreatePrefixUrl(String qrCreatePrefixUrl) { - QR_CREATE_PREFIX_URL = qrCreatePrefixUrl; - } -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/config/WebSocketConfig.java b/wjcy-system/src/main/java/me/zhengjie/config/WebSocketConfig.java deleted file mode 100644 index f55f5c6..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/config/WebSocketConfig.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.socket.server.standard.ServerEndpointExporter; - -/** - * @author ZhangHouYing - * @date 2019-08-24 15:44 - */ -@Configuration -public class WebSocketConfig { - - @Bean - public ServerEndpointExporter serverEndpointExporter() { - return new ServerEndpointExporter(); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/config/thread/AsyncTaskExecutePool.java b/wjcy-system/src/main/java/me/zhengjie/config/thread/AsyncTaskExecutePool.java deleted file mode 100644 index 8df107e..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/config/thread/AsyncTaskExecutePool.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.config.thread; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; -import org.springframework.context.annotation.Configuration; -import org.springframework.scheduling.annotation.AsyncConfigurer; -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; -import java.util.concurrent.Executor; -import java.util.concurrent.ThreadPoolExecutor; - -/** - * 异步任务线程池装配类 - * @author https://juejin.im/entry/5abb8f6951882555677e9da2 - * @date 2019年10月31日15:06:18 - */ -@Slf4j -@Configuration -public class AsyncTaskExecutePool implements AsyncConfigurer { - - /** 注入配置类 */ - private final AsyncTaskProperties config; - - public AsyncTaskExecutePool(AsyncTaskProperties config) { - this.config = config; - } - - @Override - public Executor getAsyncExecutor() { - ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); - //核心线程池大小 - executor.setCorePoolSize(config.getCorePoolSize()); - //最大线程数 - executor.setMaxPoolSize(config.getMaxPoolSize()); - //队列容量 - executor.setQueueCapacity(config.getQueueCapacity()); - //活跃时间 - executor.setKeepAliveSeconds(config.getKeepAliveSeconds()); - //线程名字前缀 - executor.setThreadNamePrefix("el-async-"); - // setRejectedExecutionHandler:当pool已经达到max size的时候,如何处理新任务 - // CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行 - executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); - executor.initialize(); - return executor; - } - - @Override - public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { - return (throwable, method, objects) -> { - log.error("===="+throwable.getMessage()+"====", throwable); - log.error("exception method:"+method.getName()); - }; - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/config/thread/AsyncTaskProperties.java b/wjcy-system/src/main/java/me/zhengjie/config/thread/AsyncTaskProperties.java deleted file mode 100644 index 21fdfd8..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/config/thread/AsyncTaskProperties.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.config.thread; - -import lombok.Data; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Component; - -/** - * 线程池配置属性类 - * @author https://juejin.im/entry/5abb8f6951882555677e9da2 - * @date 2019年10月31日14:58:18 - */ -@Data -@Component -@ConfigurationProperties(prefix = "task.pool") -public class AsyncTaskProperties { - - private int corePoolSize; - - private int maxPoolSize; - - private int keepAliveSeconds; - - private int queueCapacity; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/config/thread/TheadFactoryName.java b/wjcy-system/src/main/java/me/zhengjie/config/thread/TheadFactoryName.java deleted file mode 100644 index 4cc8ae9..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/config/thread/TheadFactoryName.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.config.thread; - -import org.springframework.stereotype.Component; - -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * 自定义线程名称 - * @author Zheng Jie - * @date 2019年10月31日17:49:55 - */ -@Component -public class TheadFactoryName implements ThreadFactory { - - private static final AtomicInteger POOL_NUMBER = new AtomicInteger(1); - private final ThreadGroup group; - private final AtomicInteger threadNumber = new AtomicInteger(1); - private final String namePrefix; - - public TheadFactoryName() { - this("el-pool"); - } - - private TheadFactoryName(String name){ - SecurityManager s = System.getSecurityManager(); - group = (s != null) ? s.getThreadGroup() : - Thread.currentThread().getThreadGroup(); - //此时namePrefix就是 name + 第几个用这个工厂创建线程池的 - this.namePrefix = name + - POOL_NUMBER.getAndIncrement(); - } - - @Override - public Thread newThread(Runnable r) { - //此时线程的名字 就是 namePrefix + -thread- + 这个线程池中第几个执行的线程 - Thread t = new Thread(group, r, - namePrefix + "-thread-"+threadNumber.getAndIncrement(), - 0); - if (t.isDaemon()) { - t.setDaemon(false); - } - if (t.getPriority() != Thread.NORM_PRIORITY) { - t.setPriority(Thread.NORM_PRIORITY); - } - return t; - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/config/thread/ThreadPoolExecutorUtil.java b/wjcy-system/src/main/java/me/zhengjie/config/thread/ThreadPoolExecutorUtil.java deleted file mode 100644 index 9a36abd..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/config/thread/ThreadPoolExecutorUtil.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.config.thread; - -import me.zhengjie.utils.SpringContextHolder; - -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -/** - * 用于获取自定义线程池 - * @author Zheng Jie - * @date 2019年10月31日18:16:47 - */ -public class ThreadPoolExecutorUtil { - - public static ThreadPoolExecutor getPoll(){ - AsyncTaskProperties properties = SpringContextHolder.getBean(AsyncTaskProperties.class); - return new ThreadPoolExecutor( - properties.getCorePoolSize(), - properties.getMaxPoolSize(), - properties.getKeepAliveSeconds(), - TimeUnit.SECONDS, - new ArrayBlockingQueue<>(properties.getQueueCapacity()), - new TheadFactoryName() - ); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/aspect/LogAspect.java b/wjcy-system/src/main/java/me/zhengjie/modules/aspect/LogAspect.java deleted file mode 100644 index 5618c65..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/aspect/LogAspect.java +++ /dev/null @@ -1,154 +0,0 @@ -package me.zhengjie.modules.aspect; - - -import cn.hutool.core.collection.ListUtil; -import cn.hutool.core.util.ObjectUtil; -import com.alibaba.fastjson.JSONObject; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.annotation.type.LogActionType; -import me.zhengjie.annotation.type.LogDaoType; -import me.zhengjie.annotation.type.LogGetIdType; -import me.zhengjie.config.BeanFactory; -import me.zhengjie.domain.Log; -import me.zhengjie.dto.Dto; -import me.zhengjie.enums.LogTypeEnum; -import me.zhengjie.service.LogService; -import me.zhengjie.utils.*; -import org.aspectj.lang.JoinPoint; -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.AfterThrowing; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Pointcut; -import org.aspectj.lang.reflect.MethodSignature; -import org.springframework.stereotype.Component; - -import javax.servlet.http.HttpServletRequest; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Map; - -/** - * @author rch - * @date 2020-08-20 - */ -@Component -@Aspect -@Slf4j -public class LogAspect { - - private final LogService logService; - - ThreadLocal currentTime = new ThreadLocal<>(); - - public LogAspect(LogService logService) { - this.logService = logService; - } - - /** - * 配置切入点 - */ - @Pointcut("@annotation(me.zhengjie.annotation.Log)") - public void logPointcut() { - // 该方法无方法体,主要为了让同类中其他方法使用此切入点 - } - - /** - * 配置环绕通知,使用在方法logPointcut()上注册的切入点 - * - * @param joinPoint join point for advice - */ - @Around("logPointcut()") - public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable { - Object result; - currentTime.set(System.currentTimeMillis()); - - // 判断是否是修改 如果是修改则获取修改前的信息 - // 如果是修改时间记录json数组,第一个为修改前的json 第二个为修改后的json数据 - MethodSignature signature = (MethodSignature) joinPoint.getSignature(); - Method method = signature.getMethod(); - me.zhengjie.annotation.Log aopLog = method.getAnnotation(me.zhengjie.annotation.Log.class); - //修改之前的数据 - JSONObject beforeJson = new JSONObject(); - Integer type = LogTypeEnum.NO_PLAT_PARAMS.value(); - if (LogActionType.UPDATE.equals(aopLog.type()) && ObjectUtil.isNotEmpty(aopLog.daoNames())) { - - //参数值 获取ID - JSONObject afterJson = JSONObject.parseObject(JSONObject.toJSONString(joinPoint.getArgs()[0])); - String[] daoNames = aopLog.daoNames(); - - // mybatis Plus Dao - if (LogDaoType.MyBATISPLUS.equals(aopLog.daoType())) { - type = LogTypeEnum.SHOW_PLAT_PARAMS.value(); - for (int i = 0; i < daoNames.length; i++) { - String daoName = daoNames[i]; - String idKey = aopLog.idTypes()[i].getValue(); - String valueKey = aopLog.valuesTypes()[i].getValue(); - Map queryMap = new HashMap<>(16); - queryMap.put(StringUtil.underscoreName(idKey), Long.valueOf(afterJson.getString(valueKey))); - Object beforeObj = BeanFactory.getBean(daoName, BaseMapper.class).selectByMap(queryMap).get(0); - cn.hutool.json.JSONObject tempBefJsonObj = new cn.hutool.json.JSONObject(beforeObj); - beforeJson.putAll(tempBefJsonObj); - } - } - // springBoot Data Jpa -因为springBoot Data JPa 该种类型 数据库结果映射对象不是json类型。暂定不支持先不修改不管 - if (LogDaoType.SPRINGDATAJPA.equals(aopLog.daoType())) { - // 逻辑大体同上 - } - } - - // 新增 - if (LogActionType.ADD.equals(aopLog.type())) { - type = LogTypeEnum.SHOW_ADD_PARAMS.value(); - } - - // 登录 - if (LogActionType.LOGIN.equals(aopLog.type())) { - type = LogTypeEnum.SHOW_LOGIN_PARAMS.value(); - } - - result = joinPoint.proceed(); - Log log = new Log("INFO", System.currentTimeMillis() - currentTime.get(), type); - log.setTrueList(aopLog.trueList()); - if (LogActionType.LOGIN.equals(aopLog.type())) { - // 记录失败原因 - if (ObjectUtil.isNotNull(result) && result instanceof Dto) { - log.setDescription(((Dto) result).getMessage()); - } - } - currentTime.remove(); - HttpServletRequest request = RequestHolder.getHttpServletRequest(); - logService.save(getUsername(), StringUtils.getBrowser(request), StringUtils.getIp(request), joinPoint, log, beforeJson); - return result; - } - - /** - * 配置异常通知 - * - * @param joinPoint join point for advice - * @param e exception - */ - @AfterThrowing(pointcut = "logPointcut()", throwing = "e") - public void logAfterThrowing(JoinPoint joinPoint, Throwable e) { - System.out.println("---------"); - System.out.println(e); - System.out.println(joinPoint); - long now = System.currentTimeMillis(); - long time = now - currentTime.get(); - Integer value = LogTypeEnum.NO_PLAT_PARAMS.value(); - Log log = new Log("ERROR", time, value); - currentTime.remove(); - log.setExceptionDetail(ThrowableUtil.getStackTrace(e)); - HttpServletRequest request = RequestHolder.getHttpServletRequest(); - logService.save(getUsername(), StringUtils.getBrowser(request), StringUtils.getIp(request), (ProceedingJoinPoint) joinPoint, log, null); - } - - public String getUsername() { - try { - return SecurityUtils.getCurrentUsername(); - } catch (Exception e) { - return ""; - } - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/capital/controller/FileUploadController.java b/wjcy-system/src/main/java/me/zhengjie/modules/capital/controller/FileUploadController.java deleted file mode 100644 index 5a197d6..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/capital/controller/FileUploadController.java +++ /dev/null @@ -1,51 +0,0 @@ -package me.zhengjie.modules.capital.controller; - -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.annotation.Log; -import me.zhengjie.config.SystemConfig; -import me.zhengjie.dto.Dto; -import me.zhengjie.service.FileUploadService; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.List; - -/** - *

- * 图片上传 - *

- * - * @author: rch - * @since: 2022-06-22 - */ -@Slf4j -@RestController -public class FileUploadController { - - @Resource - private FileUploadService fileUploadService; - - /** - * 后台管理图片上传 - */ - @Log("图片上传") - @PostMapping("/api/file/uploadFile") - public Dto apiUpload(HttpServletResponse response, HttpServletRequest request) throws IOException { - List filePaths = fileUploadService.uploadify(request, response); - return Dto.returnResult(null).setData("list", filePaths); - } - - /** - * 获取图片域名 - */ - @Log("图片上传") - @GetMapping("/api/file/doMainName") - public Dto doMainName() throws IOException { - return Dto.returnResult(SystemConfig.FILE_VISIT_ADDR); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/capital/controller/GoogleAuthController.java b/wjcy-system/src/main/java/me/zhengjie/modules/capital/controller/GoogleAuthController.java deleted file mode 100644 index 963532a..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/capital/controller/GoogleAuthController.java +++ /dev/null @@ -1,144 +0,0 @@ -package me.zhengjie.modules.capital.controller; - -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import lombok.RequiredArgsConstructor; -import me.zhengjie.annotation.AnonymousAccess; -import me.zhengjie.annotation.Log; -import me.zhengjie.annotation.type.LogActionType; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.CtSettingSite; -import me.zhengjie.error.ErrorCodeEnum; -import me.zhengjie.modules.system.service.UserService; -import me.zhengjie.modules.system.service.dto.GoogleAuthQrBarCodeUrlDTO; -import me.zhengjie.modules.system.service.dto.UpdateGoogleAuthDTO; -import me.zhengjie.modules.utils.GoogleAuthenticatorUtil; -import me.zhengjie.service.SettingSiteService; -import me.zhengjie.service.vo.AdminGoogleAuthInfoVO; -import me.zhengjie.service.vo.GoogleAuthInfoVO; -import me.zhengjie.utils.SecurityUtils; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; -import javax.validation.Valid; - -/** - *

- * Google Authenticator - *

- * - * @author: rch - * @since: 2020-08-25 - */ -@Validated -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/googleAuth") -public class GoogleAuthController { - - @Resource - private SettingSiteService settingSiteService; - @Resource - private UserService userService; - - private final String GoogleValue = "ConinUnion"; - -// /** -// * 验证身份验证码是否正确 -// * @param googleAuthCodeDTO -// * @return -// */ -// @Log(value = "验证身份验证码是否正确") -// @PostMapping(value = "/authcode") -// public Dto authcode(@Valid @RequestBody GoogleAuthCodeDTO googleAuthCodeDTO) { -// if (!settingSiteService.getGooleAuthSwitch()) { -// return Dto.returnResult(null); -// } -// return Dto.returnResult(GoogleAuthenticatorUtil.authcode(googleAuthCodeDTO.getCodes(), googleAuthCodeDTO.getSavedSecret())); -// } -// -// /** -// * 获取密钥 -// * @param googleAuthGenSecretDTO -// * @return -// */ -// @Log(value = "获取密钥") -// @PostMapping(value = "/genSecret") -// public Dto genSecret(@Valid @RequestBody GoogleAuthGenSecretDTO googleAuthGenSecretDTO, HttpServletRequest request) { -// if (!settingSiteService.getGooleAuthSwitch() || ObjectUtil.isEmpty(userService.findByName(googleAuthGenSecretDTO.getUserName()))) { -// return Dto.returnResult(null); -// } -// // redis 一个用户对应 一次匹配配置的SEED 对应唯一秘钥 -// return Dto.returnResult(GoogleAuthenticatorUtil.genSecret(googleAuthGenSecretDTO.getUserName(), request.getRemoteHost())); -// } - - /** - * 获取二维码图片URL - * @param googleAuthQrBarCodeUrlDTO - * @return - */ - @Log(value = "获取二维码图片URL") - @PostMapping(value = "/getQRBarcodeURL") - public Dto getQRBarcodeURL(@Valid @RequestBody GoogleAuthQrBarCodeUrlDTO googleAuthQrBarCodeUrlDTO, HttpServletRequest request) { - if (ObjectUtil.isEmpty(userService.findByName(googleAuthQrBarCodeUrlDTO.getUserName()))) { - return Dto.returnResult(null); - } - // 没有秘钥会生成一个存储在 redis中 一个用户对应 一次匹配配置的SEED 对应唯一秘钥 - GoogleAuthInfoVO googleAuthInfoVO = new GoogleAuthInfoVO(); - String secretValue = GoogleAuthenticatorUtil.genSecret(googleAuthQrBarCodeUrlDTO.getUserName(), request.getRemoteHost()); - googleAuthInfoVO.setSecret(secretValue); - googleAuthInfoVO.setUserName(googleAuthQrBarCodeUrlDTO.getUserName()); - googleAuthInfoVO.setQrBarCodeUrl(GoogleAuthenticatorUtil.getQRBarcodeURL(googleAuthQrBarCodeUrlDTO.getUserName(), GoogleValue, secretValue)); - return Dto.returnResult(googleAuthInfoVO); - } - - /** - * 判断GoogleAuth 是否开启 - * @return - */ - @Log(value = "判断GoogleAuth 是否开启") - @PostMapping(value = "/getOpenUse") - public Dto getOpenUse(HttpServletRequest request) { - - // 获取admin 信息 - AdminGoogleAuthInfoVO adminGoogleAuthInfoVO = new AdminGoogleAuthInfoVO(); - UserDetails userDetails = SecurityUtils.getCurrentUser(); - if (ObjectUtil.isEmpty(userDetails) || ObjectUtil.isEmpty(userDetails.getUsername())) { - return Dto.getInstance(ErrorCodeEnum.BAD_CREDENTIALS); - } - - String secretValue = GoogleAuthenticatorUtil.genSecret(userDetails.getUsername(), request.getRemoteHost()); - adminGoogleAuthInfoVO.setSecret(secretValue); - adminGoogleAuthInfoVO.setUserName(userDetails.getUsername()); - adminGoogleAuthInfoVO.setQrBarCodeUrl(GoogleAuthenticatorUtil.getQRBarcodeURL(userDetails.getUsername(), GoogleValue, secretValue)); - adminGoogleAuthInfoVO.setGogoleAuthSwitch(settingSiteService.getGooleAuthSwitch()); - - return Dto.returnResult(adminGoogleAuthInfoVO); - } - - - @Log(value = "修改Google开关", type = LogActionType.UPDATE) - @PostMapping(value = "/updateOpenUse") - public Dto updateOpenUse(@Valid @RequestBody UpdateGoogleAuthDTO updateGoogleAuthDTO) { - - Integer value = updateGoogleAuthDTO.getIsOpen(); - CtSettingSite ctSettingSite = new CtSettingSite(); - ctSettingSite.setSettingValue(String.valueOf(value)); - - QueryWrapper ctSettingSiteQuery = new QueryWrapper(); - ctSettingSiteQuery.eq("setting_key", "googleAuth"); - - return Dto.returnResult(settingSiteService.update(ctSettingSite, ctSettingSiteQuery)); - } - - - @Log(value = "获取Google开关") - @GetMapping(value = "/getGoogleSwitch") - @AnonymousAccess - public Dto getGoogleSwitch() { - - return Dto.returnResult(settingSiteService.getGooleAuthSwitch()); - }} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/capital/controller/LoginIpController.java b/wjcy-system/src/main/java/me/zhengjie/modules/capital/controller/LoginIpController.java deleted file mode 100644 index a50fe80..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/capital/controller/LoginIpController.java +++ /dev/null @@ -1,68 +0,0 @@ -package me.zhengjie.modules.capital.controller; - -import lombok.RequiredArgsConstructor; -import me.zhengjie.annotation.Log; -import me.zhengjie.annotation.type.LogActionType; -import me.zhengjie.dto.Dto; -import me.zhengjie.dto.PageDTO; -import me.zhengjie.error.ErrorCodeEnum; -import me.zhengjie.modules.capital.dto.AddLoginIpDTO; -import me.zhengjie.modules.capital.dto.EditLoginIpDTO; -import me.zhengjie.modules.capital.dto.IdDTO; -import me.zhengjie.service.LoginIpService; -import me.zhengjie.utils.PageUtils; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import javax.validation.Valid; - -/* - * - * @Description ip限制 - * @Date 2022/3/21 - * @Author zeng - */ -@Validated -@RestController -@RequestMapping("/api/ip") -@RequiredArgsConstructor -public class LoginIpController { - - final LoginIpService loginIpService; - - @PostMapping("/list") - public Dto list(@RequestBody @Valid PageDTO pageDTO) { - PageUtils pageUtils = loginIpService.getList(pageDTO.getiPage()); - return Dto.returnResult(pageUtils); - } - - @Log(type = LogActionType.ADD,value = "添加ip限制") - @PostMapping("/add") - public Dto addIp(@RequestBody @Valid AddLoginIpDTO dto) { - if (!dto.pass()) { - return Dto.getInstance(ErrorCodeEnum.LOGIN_IP_FORMAT_ERROR); - } - return Dto.returnResult(loginIpService.addIp(dto.getLoginIp())); - } - - @Log(type = LogActionType.UPDATE,value = "修改ip限制") - @PostMapping("/edit") - public Dto editIp(@RequestBody @Valid EditLoginIpDTO dto){ - if (!dto.pass()) { - return Dto.getInstance(ErrorCodeEnum.LOGIN_IP_FORMAT_ERROR); - } - return Dto.returnResult(loginIpService.updateIp(dto.getLoginIp())); - } - - @PostMapping("/getById") - public Dto getIp(@Valid @RequestBody IdDTO idDTO) { - return Dto.returnResult(loginIpService.getById(idDTO.getId())); - } - - @Log(type = LogActionType.DELETE,value = "删除ip限制") - @PostMapping("/del") - public Dto delIp(@Valid @RequestBody IdDTO idDTO) { - return Dto.returnResult(loginIpService.deleteIp(idDTO.getId().intValue())); - } - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/capital/controller/SettingSiteController.java b/wjcy-system/src/main/java/me/zhengjie/modules/capital/controller/SettingSiteController.java deleted file mode 100644 index 65d4498..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/capital/controller/SettingSiteController.java +++ /dev/null @@ -1,140 +0,0 @@ -package me.zhengjie.modules.capital.controller; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.map.MapUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.json.JSONObject; -import cn.hutool.json.JSONUtil; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.annotation.FormSubmission; -import me.zhengjie.annotation.Log; -import me.zhengjie.annotation.type.LogActionType; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.CtSettingSite; -import me.zhengjie.modules.capital.dto.SettingSiteDTO; -import me.zhengjie.service.SettingSiteService; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; -import javax.validation.Valid; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * 全局配置 控制类 - * - * @author rch - * @date 2020-07-29 - */ -@Validated -@RestController -@RequiredArgsConstructor -@RequestMapping("api/settingSite") -@Slf4j -public class SettingSiteController { - - @Resource - private SettingSiteService settingSiteService; - - - /** - * 获取全局配置 - * - * @return - */ - @Log("获取全局配置") - @PostMapping("/list") - public Dto list() { - List ctSettingSiteList = settingSiteService.list(); - List list = new ArrayList(); - for (CtSettingSite settingSite : ctSettingSiteList) { - Map map = BeanUtil.beanToMap(settingSite); - map.put("settingValue", getSettingValue(settingSite)); - list.add(map); - } - return Dto.returnResult(list); - } - - /** - * 配置全局配置 - * - * @param settingsiteDtoList - * @return - */ - @Log(value = "配置全局配置", type = LogActionType.ADD, trueList = true) - @PostMapping(value = "/save") - @FormSubmission - public Dto save(@Valid @RequestBody List settingsiteDtoList) { - - List updateCtSettingSiteList = new ArrayList<>(); - for (SettingSiteDTO settingSiteDTO : settingsiteDtoList) { - CtSettingSite site = new CtSettingSite(); - BeanUtil.copyProperties(settingSiteDTO, site); - - // 个别设置 可以只修改部分的内容 - switch (settingSiteDTO.getSettingKey()) { - case "shareholderCurrencySettings": { - String value = settingSiteService.getValue("shareholderCurrencySettings"); - JSONObject oldValue = JSONUtil.parseObj(value); - JSONObject updateValue = JSONUtil.parseObj(settingSiteDTO.getSettingValue()); - oldValue.putAll(updateValue); - site.setSettingValue(oldValue.toString()); - } - } - - updateCtSettingSiteList.add(site); - } - if (ObjectUtil.isEmpty(updateCtSettingSiteList)) { - return Dto.returnErrorResult(" Empty List! "); - } - - // 执行批量更新操作 - return Dto.returnResult(settingSiteService.updateBatchById(updateCtSettingSiteList)); - } - - - private Object getSettingValue(CtSettingSite settingSite) { - Object settingValue = settingSite.getSettingValue(); - switch (settingSite.getSettingKey()) { - case "currencyTemplateSettings": { - JSONObject jsonObject = JSONUtil.parseObj(settingSite.getSettingValue()); - List list = new ArrayList(); - for (String key : jsonObject.keySet()) { - JSONObject value = jsonObject.get(key, JSONObject.class); - value.putOpt("currencyName", key); - list.add(value); - } - return list; - } - case "shareholderPoolPublicSettings": { - JSONObject jsonObject = JSONUtil.parseObj(settingSite.getSettingValue()); - return jsonObject; - } - case "shareholderCurrencySettings": { - JSONObject jsonObject = JSONUtil.parseObj(settingSite.getSettingValue()); - List list = new ArrayList(); - for (String key : jsonObject.keySet()) { - Map blockChain = MapUtil.of("passType", key); - JSONObject currencys = jsonObject.get(key, JSONObject.class); - List currencyList = new ArrayList(); - for (String k : currencys.keySet()) { - JSONObject currency = currencys.get(k, JSONObject.class); - currency.putOpt("currencyName", k); - currencyList.add(currency); - } - blockChain.put("currency", currencyList); - list.add(blockChain); - } - - return list; - } - } - return settingValue; - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/capital/dto/AddLoginIpDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/capital/dto/AddLoginIpDTO.java deleted file mode 100644 index 632652f..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/capital/dto/AddLoginIpDTO.java +++ /dev/null @@ -1,50 +0,0 @@ -package me.zhengjie.modules.capital.dto; - -import cn.hutool.core.util.ObjectUtil; -import lombok.Data; -import me.zhengjie.annotation.DateTime; -import me.zhengjie.entity.LoginIp; -import me.zhengjie.utils.LoginIpUtil; - -import javax.validation.constraints.NotBlank; - -/* - * - * @Description - * @Date 2022/3/21 - * @Author zeng - */ -@Data -public class AddLoginIpDTO { - - /** 开始IP */ - @NotBlank - private String ipStart; - /** 结束IP */ - private String ipEnd; - /** 备注 */ - private String remark; - /** 有效截至时间 */ - @DateTime - private String vaildTime; - - public boolean pass() { - if (!LoginIpUtil.isIP(ipStart)) { - return false; - } - if (ObjectUtil.isNotEmpty(ipEnd) && !LoginIpUtil.isIP(ipEnd)) { - return false; - } - return true; - } - - public LoginIp getLoginIp() { - LoginIp ip = new LoginIp(); - ip.setIpStart(ipStart); - ip.setIpEnd(ipEnd); - ip.setRemark(remark); - ip.setVaildTime(vaildTime); - return ip; - } - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/capital/dto/EditLoginIpDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/capital/dto/EditLoginIpDTO.java deleted file mode 100644 index 7a493dd..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/capital/dto/EditLoginIpDTO.java +++ /dev/null @@ -1,26 +0,0 @@ -package me.zhengjie.modules.capital.dto; - -import lombok.Data; -import me.zhengjie.entity.LoginIp; - -import javax.validation.constraints.NotNull; - -/* - * - * @Description - * @Date 2022/3/21 - * @Author zeng - */ -@Data -public class EditLoginIpDTO extends AddLoginIpDTO{ - - @NotNull - private Integer id; - - @Override - public LoginIp getLoginIp() { - LoginIp loginIp = super.getLoginIp(); - loginIp.setId(id); - return loginIp; - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/capital/dto/IdDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/capital/dto/IdDTO.java deleted file mode 100644 index aee0b34..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/capital/dto/IdDTO.java +++ /dev/null @@ -1,17 +0,0 @@ -package me.zhengjie.modules.capital.dto; - -import lombok.Data; - -import javax.validation.constraints.NotNull; - -/* - * - * @Description IdDTO - * @Date 2021/11/30 - * @Author zeng - */ -@Data -public class IdDTO { - @NotNull - private Long id; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/capital/dto/RelSettingSiteDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/capital/dto/RelSettingSiteDTO.java deleted file mode 100644 index 108c95c..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/capital/dto/RelSettingSiteDTO.java +++ /dev/null @@ -1,27 +0,0 @@ -package me.zhengjie.modules.capital.dto; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.Valid; -import javax.validation.constraints.NotNull; -import java.util.List; - -/** - * 全局配置(SettingSiteDTO)表实体类 - * - * @author rch - * @since 2020-07-29 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class RelSettingSiteDTO { - - @NotNull(message = "id不能为空") - private Long id; - - @Valid - List settingSiteList; -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/capital/dto/SettingSiteDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/capital/dto/SettingSiteDTO.java deleted file mode 100644 index 8c9229c..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/capital/dto/SettingSiteDTO.java +++ /dev/null @@ -1,33 +0,0 @@ -package me.zhengjie.modules.capital.dto; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import lombok.extern.slf4j.Slf4j; - -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; - -/** - * 全局配置(SettingSiteDTO)表实体类 - * - * @author rch - * @since 2020-07-29 - */ -@Slf4j -@Data -@AllArgsConstructor -@NoArgsConstructor -public class SettingSiteDTO { - - @NotNull(message = "id不能为空") - private Long id; - - /** 设置KEY */ - @NotBlank(message = "设置KEY") - private String settingKey; - - /** 设置value */ - @NotBlank - private String settingValue; -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtApplyController.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtApplyController.java deleted file mode 100644 index aced8ee..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtApplyController.java +++ /dev/null @@ -1,187 +0,0 @@ -package me.zhengjie.modules.group.controller.base; - - -import cn.hutool.core.bean.BeanUtil; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import me.zhengjie.annotation.FormSubmission; -import me.zhengjie.annotation.Log; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.CtApply; -import me.zhengjie.enums.TaskInfoEnum; -import me.zhengjie.error.ErrorCodeEnum; -import me.zhengjie.modules.group.dto.CtApplyAddDTO; -import me.zhengjie.modules.group.dto.CtApplyListDTO; -import me.zhengjie.modules.group.dto.CtApplyUpdateDTO; -import me.zhengjie.modules.group.dto.IdDTO; -import me.zhengjie.service.CtApplyService; -import me.zhengjie.service.vo.CtApplyListVO; -import me.zhengjie.utils.PageUtils; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import javax.annotation.Resource; -import javax.validation.Valid; -import java.util.List; -import java.util.stream.Collectors; - -/** - * Author: zhw - * Data: 2022-07-23 - * Description 应用管理控制层——CtApply - */ -@Validated -@RequestMapping("/api/ctApply") -@RestController -@Api(tags = "业务:应用管理") -public class CtApplyController { - - @Resource - private CtApplyService ctApplyService; - - /** - * 分页查询 - */ - @ApiOperation("分页查询应用数据") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("分页查询应用数据") - @PostMapping("/list") - public Dto getApplyList(@Valid @RequestBody CtApplyListDTO dto){ - PageUtils pageUtils = ctApplyService.searchPageList(dto.getiPage(),dto.getWrapper()); - return Dto.returnResult(pageUtils); - } - - - /** - * 新增应用信息 - * @param dto - * @return Dto - */ - @ApiOperation("新增应用信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 4200, message = "应用ID存在重复!"), - @ApiResponse(code = 4201, message = "不存在对应方法名称!") - }) - @Log("新增应用信息") - @PostMapping("/add") - @FormSubmission - public Dto addCtApply(@Valid @RequestBody CtApplyAddDTO dto){ - - List applyList = ctApplyService.list(); - List applyIdList = applyList.stream().map(CtApply::getRobotUuid).collect(Collectors.toList()); - if(applyIdList.contains(dto.getRobotUuid())){ - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_REPEAT_ID); - } - - CtApply ctApply = new CtApply(); - BeanUtil.copyProperties(dto, ctApply); - //任务名首字母小写 - char[] taskNameChars = dto.getTaskName().toCharArray(); - taskNameChars[0] = Character.toLowerCase(taskNameChars[0]); - String taskName = new String(taskNameChars); - String methodName = TaskInfoEnum.getMethodNameByTaskName(taskName); - if(methodName == null || methodName.length() == 0){ - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_METHOD_NAME); - } - ctApply.setTaskName(taskName); - ctApply.setMethodName(methodName); - return Dto.returnResult(ctApplyService.save(ctApply)); - } - - /** - * 根据ID删除应用信息 - * @param idDTO - * @return Dto - */ - @ApiOperation("根据ID删除应用信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("根据ID删除应用信息") - @PostMapping("/delete") - public Dto delCtApplyById(@Valid @RequestBody IdDTO idDTO){ - return Dto.returnResult(ctApplyService.removeById(idDTO.getId())); - } - - /** - * 根据ID 修改应用信息 - * @param dto - * @return Dto - */ - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 4200, message = "应用ID存在重复!"), - @ApiResponse(code = 4201, message = "不存在对应方法名称!") - }) - @ApiOperation("修改应用信息") - @Log("根据ID修改应用信息") - @PostMapping("/edit") - @FormSubmission - public Dto editCtApplyById(@Valid @RequestBody CtApplyUpdateDTO dto){ - CtApply ctApplyIsExist = ctApplyService.getById(dto.getId()); - if(ctApplyIsExist == null){ - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_APPLY); - } - CtApply updateCtApply = new CtApply(); - BeanUtil.copyProperties(dto,updateCtApply); - //更新校验 - List applyList = ctApplyService.list(); - List applyIdList = applyList.stream().map(CtApply::getRobotUuid).collect(Collectors.toList()); - if(applyIdList.contains(dto.getRobotUuid()) && !dto.getRobotUuid().equals(ctApplyIsExist.getRobotUuid())){ - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_REPEAT_ID); - } - - //任务名首字母小写 - char[] taskNameChars = dto.getTaskName().toCharArray(); - taskNameChars[0] = Character.toLowerCase(taskNameChars[0]); - String taskName = new String(taskNameChars); - String methodName = TaskInfoEnum.getMethodNameByTaskName(taskName); - //判断是否存在对应方法名称 - if(methodName == null || methodName.length() == 0){ - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_METHOD_NAME); - } - updateCtApply.setTaskName(taskName); - updateCtApply.setMethodName(methodName); - return Dto.returnResult(ctApplyService.updateById(updateCtApply)); - } - - /** - * 根据ID 查询应用信息 - * @param idDTO - * @return Dto - */ - @ApiOperation("查询应用信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("根据ID查询应用信息") - @PostMapping("getById") - public Dto getById(@Valid @RequestBody IdDTO idDTO){ - return Dto.returnResult(ctApplyService.getById(idDTO.getId())); - } - - /** - * 获取所有应用信息 - * @return Dto - */ - @ApiOperation("查找所有应用名称") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("查找所有应用名称") - @GetMapping("getAll") - public Dto getAllApply(){ - return Dto.returnResult(ctApplyService.getAllApplyName()); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtBrowseController.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtBrowseController.java deleted file mode 100644 index f22c5bd..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtBrowseController.java +++ /dev/null @@ -1,148 +0,0 @@ -package me.zhengjie.modules.group.controller.base; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.util.ObjectUtil; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import lombok.RequiredArgsConstructor; -import me.zhengjie.annotation.FormSubmission; -import me.zhengjie.annotation.Log; -import me.zhengjie.annotation.type.LogActionType; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.CtBrowse; -import me.zhengjie.enums.ClickBrowseStatusEnum; -import me.zhengjie.error.ErrorCodeEnum; -import me.zhengjie.modules.group.dto.CtBrowseAddDTO; -import me.zhengjie.modules.group.dto.CtBrowseListDTO; -import me.zhengjie.modules.group.dto.CtBrowseUpdateDTO; -import me.zhengjie.modules.group.dto.IdDTO; -import me.zhengjie.service.CtBrowseService; -import me.zhengjie.service.vo.CtBrowseDetailVO; -import me.zhengjie.service.vo.CtBrowseListVO; -import me.zhengjie.utils.PageUtils; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; -import javax.validation.Valid; - - -/** - * - * @Description 浏览收藏 控制类 - * @Date 2022-11-04 - * @Author rch - */ -@Validated -@RequestMapping("/api/ctBrowse") -@RestController -@RequiredArgsConstructor -@Api(tags = "业务:收藏浏览管理") -public class CtBrowseController { - - @Resource - private CtBrowseService ctBrowseService; - - /** - * 分页查询浏览收藏信息 - */ - @ApiOperation("分页查询浏览收藏数据") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("分页查询浏览收藏信息") - @PostMapping("/list") - public Dto getBrowseList(@Valid @RequestBody CtBrowseListDTO dto) { - PageUtils pageUtilsResult = ctBrowseService.searchPageList(dto.getiPage(), dto.getWrapper()); - return Dto.returnResult(pageUtilsResult); - } - - /** - * 新增浏览收藏信息 - */ - @ApiOperation("新增浏览收藏") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log(value = "新增浏览收藏信息",type = LogActionType.ADD) - @PostMapping("/add") - @FormSubmission - public Dto addBrowse(@Valid @RequestBody CtBrowseAddDTO dto) { - - CtBrowse ctBrowse = new CtBrowse(); - BeanUtil.copyProperties(dto, ctBrowse); - return Dto.returnResult(ctBrowseService.save(ctBrowse)); - } - - /** - * 根据Id获取浏览收藏详情 - */ - @ApiOperation("根据Id获取浏览收藏详情") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - - @Log("根据Id获取浏览收藏详情") - @PostMapping("/getById") - public Dto getBrowseById(@Valid @RequestBody IdDTO idDTO) { - return Dto.returnResult(ctBrowseService.getBrowseDetailById(idDTO.getId())); - } - - - /** - * 根据id删除 - * @author: rch - */ - @ApiOperation("根据id删除") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 3300, message = "浏览信息不存在!") - }) - @Log(value = "根据id删除信息",type = LogActionType.DELETE) - @PostMapping("/delete") - public Dto delete(@Valid @RequestBody IdDTO idDTO) { - - // 先查询 - CtBrowse ctBrowse = ctBrowseService.getById(idDTO.getId()); - if (ObjectUtil.isEmpty(ctBrowse) - || !ClickBrowseStatusEnum.TOBE_EXECUTION.eqValue(ctBrowse.getStatus())) { - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_BROWSE); - } - return Dto.returnResult(ctBrowseService.removeById(idDTO.getId())); - } - - /** - * 编辑浏览收藏信息 - */ - @ApiOperation("编辑浏览收藏信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 3301, message = "浏览收藏信息不存在!") - }) - @Log(value = "编辑浏览收藏信息",type = LogActionType.UPDATE) - @PostMapping("/edit") - @FormSubmission - public Dto editBrowse(@Valid @RequestBody CtBrowseUpdateDTO dto) { - - // 根据id 判断是否存在 - CtBrowse ctBrowse = ctBrowseService.getById(dto.getId()); - if (ObjectUtil.isEmpty(ctBrowse)) { - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_BROWSE); - } - - CtBrowse updateCtBrowse = new CtBrowse(); - BeanUtil.copyProperties(dto, updateCtBrowse); - - return Dto.returnResult(ctBrowseService.updateById(updateCtBrowse)); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtBuyerController.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtBuyerController.java deleted file mode 100644 index 6ef64e9..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtBuyerController.java +++ /dev/null @@ -1,391 +0,0 @@ -package me.zhengjie.modules.group.controller.base; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.lang.Snowflake; -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import io.swagger.annotations.*; -import lombok.RequiredArgsConstructor; -import me.zhengjie.annotation.AnonymousAccess; -import me.zhengjie.annotation.FormSubmission; -import me.zhengjie.annotation.Log; -import me.zhengjie.annotation.type.LogActionType; -import me.zhengjie.config.PropertiesConfig; -import me.zhengjie.config.SystemConfig; -import me.zhengjie.constant.PublicConstant; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.*; -import me.zhengjie.enums.BuyerStatusEnum; -import me.zhengjie.enums.PlatTypeEnum; -import me.zhengjie.error.ErrorCodeEnum; -import me.zhengjie.modules.group.dto.CtBuyerAddDTO; -import me.zhengjie.modules.group.dto.CtBuyerListDTO; -import me.zhengjie.modules.group.dto.CtBuyerUpdateDTO; -import me.zhengjie.modules.group.dto.IdDTO; -import me.zhengjie.service.*; -import me.zhengjie.service.vo.CtBuyerDetailVO; -import me.zhengjie.service.vo.CtBuyerListVO; -import me.zhengjie.utils.PageUtils; -import me.zhengjie.utils.excel.ExcelUtils; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletResponse; -import javax.validation.Valid; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - - -/** - * - * @Description 群控管理-买家 控制类 - * @Date 2022-06-22 - * @Author rch - */ -@Validated -@RequestMapping("/api/ctBuyer") -@RestController -@RequiredArgsConstructor -@Api(tags = "业务:买家管理") -public class CtBuyerController { - - @Resource - private CtBuyerService ctBuyerService; - @Resource - private CtOrderService ctOrderService; - @Resource - private CtCompanyService ctCompanyService; - @Resource - private CtVpnService ctVpnService; - @Resource - private CtCardService ctCardService; - @Resource - private PropertiesConfig propertiesConfig; - @Resource - private Snowflake snowflake; - - /** - * 分页查询买家信息 - */ - @ApiOperation("分页查询买家数据") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("分页查询买家信息") - @PostMapping("/list") - public Dto getBuyerList(@Valid @RequestBody CtBuyerListDTO dto) { - PageUtils pageUtilsResult = ctBuyerService.searchPageList(dto.getiPage(), dto.getWrapper()); - return Dto.returnResult(pageUtilsResult); - } - - /** - * 新增买家信息 - */ - @ApiOperation("新增买家信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 3200, message = "平台信息不存在!") - }) - @Log(value = "新增买家信息", type = LogActionType.ADD) - @PostMapping("/add") - @FormSubmission - public Dto addBuyer(@Valid @RequestBody CtBuyerAddDTO dto) { - // 检验 - Dto returnDto = addCheck(dto); - if (ObjectUtil.isNotEmpty(returnDto)) { - return returnDto; - } - - CtBuyer ctBuyer = new CtBuyer(); - BeanUtil.copyProperties(dto, ctBuyer); - return Dto.returnResult(ctBuyerService.save(ctBuyer)); - } - - /** - * 根据id买家信息详情详情 - */ - @ApiOperation("根据id查询买家详情信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("根据id查询买家详情信息") - @PostMapping("/getById") - public Dto getBuyerById(@Valid @RequestBody IdDTO idDTO) { - return Dto.returnResult(ctBuyerService.getDetailById(idDTO.getId())); - } - - /** - * 编辑买家信息 - */ - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 3000, message = "买家信息不存在!"), - @ApiResponse(code = 3200, message = "平台信息不存在!") - }) - @ApiOperation("编辑买家信息") - @Log(value = "编辑买家信息", type = LogActionType.UPDATE) - @PostMapping("/edit") - @FormSubmission - public Dto editBuyer(@Valid @RequestBody CtBuyerUpdateDTO dto) { - - // 根据id 判断是否存在 - CtBuyer ctBuyer = ctBuyerService.getById(dto.getId()); - if (ObjectUtil.isEmpty(ctBuyer)) { - Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_BUYER_USER); - } - - // 如果修改平台平台信息 以及修改 密码信息 需要判断是否有关联的订单信息 存在则不允许修改 - Dto returnDto = equalsUpdateBuyerInfo(dto, ctBuyer); - if (ObjectUtil.isNotEmpty(returnDto)) { - return returnDto; - } - CtBuyer updateCtBuyer = new CtBuyer(); - BeanUtil.copyProperties(dto, updateCtBuyer); - return Dto.returnResult(ctBuyerService.updateById(updateCtBuyer)); - } - - /** - * 根据id删除买家信息 - * - * @author: rch - */ - @ApiOperation("根据ID删除买家信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log(value = "根据id删除买家信息", type = LogActionType.DELETE) - @PostMapping("/delete") - public Dto delBuyer(@Valid @RequestBody IdDTO idDTO) { - -// QueryWrapper queryWrapper = new QueryWrapper<>(); -// queryWrapper.eq("buyer_id", idDTO); -// Integer count = ctOrderService.count(queryWrapper); -// if (ObjectUtil.isNotEmpty(count) && count > 0) { -// Dto.getInstance(ErrorCodeEnum.ERROR_NOT_DEL_EXIST_ORDER_BUYER_USER); -// } - - CtBuyer updateCtBuyer = new CtBuyer(); - updateCtBuyer.setId(idDTO.getId()); - updateCtBuyer.setStatus(BuyerStatusEnum.DEL.value()); - - return Dto.returnResult(ctBuyerService.updateById(updateCtBuyer)); - } - - /** - * 新增逻辑 检验 - * - * @param dto - * @return - */ - public Dto addCheck(CtBuyerAddDTO dto) { - // 检验公司是否存在 - if (!ObjectUtil.isNotEmpty(ctCompanyService.getById(dto.getCompanyId()))) { - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_COMPANY); - } - - // 检验平台是否正确 - String value = PlatTypeEnum.getDescByType(dto.getPlatformId()); - if (ObjectUtil.isEmpty(value)) { - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_PLAT_USER); - } - -// // 判断token是否重复 -// QueryWrapper queryWrapper = new QueryWrapper<>(); -// queryWrapper.eq("pwd", dto.getPwd()); -// Integer count = ctBuyerService.count(queryWrapper); -// if (ObjectUtil.isNotEmpty(count) && count > 1) { -// return Dto.getInstance(ErrorCodeEnum.ERROR_EXIST_FIND_BUYER_USER); -// } - return null; - } - - /** - * 检验是否是允许修改 - * - * @param dto - * @param ctBuyer - * @return - */ - public Dto equalsUpdateBuyerInfo(CtBuyerUpdateDTO dto, CtBuyer ctBuyer) { - Boolean canUpdate = false; - if (ObjectUtil.isNotEmpty(dto.getPwd()) && !dto.getPwd().equals(ctBuyer.getPwd())) { - canUpdate = true; - } - if (ObjectUtil.isNotEmpty(dto.getPlatformId()) && !dto.getPlatformId().equals(ctBuyer.getPlatformId())) { - canUpdate = true; - } - if (ObjectUtil.isNotEmpty(dto.getPlatformId()) && !dto.getPlatformId().equals(ctBuyer.getPlatformId())) { - canUpdate = true; - } - - if (canUpdate) { - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.eq("buyer_id", dto.getId()); - Integer count = ctOrderService.count(queryWrapper); - if (ObjectUtil.isNotEmpty(count) && count > 1) { - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_UPDATE_EXIST_ORDER_BUYER_USER); - } - } - - // 检验公司是否存在 - if (!ObjectUtil.isNotEmpty(ctCompanyService.getById(dto.getCompanyId()))) { - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_COMPANY); - } - -// // 判断token是否重复 -// QueryWrapper queryWrapper = new QueryWrapper<>(); -// queryWrapper.eq("pwd", dto.getPwd()); -// Integer count = ctBuyerService.count(queryWrapper); -// if (ObjectUtil.isNotEmpty(count) && count > 1) { -// return Dto.getInstance(ErrorCodeEnum.ERROR_EXIST_FIND_BUYER_USER); -// } - return null; - } - - /** - * 从Excel导入买家信息 - */ - @ApiOperation("从Excel导入买家信息") - @ApiImplicitParams({ - @ApiImplicitParam(value = "上传文件", name = "file", dataType = "__file", required = true) - }) - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log(value = "Excel买家信息", type = LogActionType.ADD) - @PostMapping("import") - public Dto importBuyer(@RequestPart("file") MultipartFile file, HttpServletResponse response) throws Exception { - List ctBuyerImportList = ExcelUtils.readMultipartFile(file, CtBuyerImport.class); - //当excel表导入为空 - if (ObjectUtil.isEmpty(ctBuyerImportList)) { - return Dto.returnResult(false); - } - - List allBuyerAccount = ctBuyerService.getAllAccount(); - List companyInfoList = new ArrayList<>(); - //根据excel表中公司名称导出表中存在公司信息,自动过滤不存在的 - List buyerCompanyNameList = ctBuyerImportList.stream().map(CtBuyerImport::getCompanyName).collect(Collectors.toList()).stream().distinct().collect(Collectors.toList()); - if (ObjectUtil.isNotEmpty(buyerCompanyNameList)) { - companyInfoList = ctCompanyService.getByNmae(buyerCompanyNameList); - } - //获取VPN列表 - List vpnInfoList = new ArrayList<>(); - List buyerVpnIpList = ctBuyerImportList.stream().map(CtBuyerImport::getVpnIp).collect(Collectors.toList()).stream().distinct().collect(Collectors.toList());; - if (ObjectUtil.isNotEmpty(buyerVpnIpList)) { - vpnInfoList = ctVpnService.getVpnInfoByIp(buyerVpnIpList); - } - //获取信用卡列表 - List cardInfoList = new ArrayList<>(); - List buyerCardNubList = ctBuyerImportList.stream().map(CtBuyerImport::getCardNumber).collect(Collectors.toList()).stream().distinct().collect(Collectors.toList());; - if (ObjectUtil.isNotEmpty(buyerCardNubList)) { - cardInfoList = ctCardService.getCardInfoByNumber(buyerCardNubList); - } - - //批量新增的买家 - List addCtBuyerList = new ArrayList<>(); - //导出异常的买家信息 - List ctBuyerExportList = new ArrayList<>(); - - //循环判断异常 - for (CtBuyerImport ctBuyerImport : ctBuyerImportList) { - //定义一个异常买家实体 - CtBuyerExport ctBuyerExport = new CtBuyerExport(); - BeanUtil.copyProperties(ctBuyerImport, ctBuyerExport); - - StringBuffer errorStrBuf = new StringBuffer(); - //错误信息 - String rowTips = ctBuyerImport.getRowTips(); - if (ObjectUtil.isNotEmpty(rowTips)) { - errorStrBuf.append(rowTips); - errorStrBuf.append(";"); - } - - if (allBuyerAccount.contains(ctBuyerImport.getAccount())) { - errorStrBuf.append("已存在该账号对应的买家信息"); - errorStrBuf.append(";"); - } - //判断是否存在该公司 - if (ObjectUtil.isEmpty(companyInfoList) || companyInfoList.stream().filter(i -> i.getName().equals(ctBuyerExport.getCompanyName())).count() < 1) { - errorStrBuf.append("公司名称不存在!"); - errorStrBuf.append(";"); - } - if (ObjectUtil.isEmpty(vpnInfoList) || vpnInfoList.stream().filter(i -> i.getIpAddress().equals(ctBuyerExport.getVpnIp())).count() < 1) { - errorStrBuf.append("VpnIP信息不存在!"); - errorStrBuf.append(";"); - } - // 敦煌的不需要检验信用卡 - if (!"敦煌".equals(ctBuyerImport.getPlatformName())) { - if (ObjectUtil.isEmpty(cardInfoList) || cardInfoList.stream().filter(i -> i.getNumber().equals(ctBuyerExport.getCardNumber())).count() < 1) { - errorStrBuf.append("信用卡卡号信息不存在!"); - errorStrBuf.append(";"); - } - } - - // 平台 - Integer platId = PlatTypeEnum.getValueByDesc(ctBuyerImport.getPlatformName()); - if (ObjectUtil.isEmpty(platId)) { - errorStrBuf.append("平台信息不存在!"); - errorStrBuf.append(";"); - } - - if (ObjectUtil.isNotEmpty(errorStrBuf)) { - ctBuyerExport.setError(errorStrBuf.toString()); - ctBuyerExportList.add(ctBuyerExport); - } else { - CtBuyer ctBuyer = new CtBuyer(); - BeanUtil.copyProperties(ctBuyerImport, ctBuyer); - //平台ID - ctBuyer.setPlatformId(platId); - //公司ID - Optional ctCompanyInfo = companyInfoList.stream().filter(c -> c.getName().equals(ctBuyerImport.getCompanyName())).findFirst(); - ctBuyer.setCompanyId(ctCompanyInfo.get().getId()); - //VPNiD - Optional ctVpnInfo = vpnInfoList.stream().filter(c -> c.getIpAddress().equals(ctBuyerImport.getVpnIp())).findFirst(); - ctBuyer.setVpnId(ctVpnInfo.get().getId()); - //信用卡ID - Optional ctCardInfo = cardInfoList.stream().filter(c -> c.getNumber().equals(ctBuyerImport.getCardNumber())).findFirst(); - ctBuyer.setCardId(ctCardInfo.get().getId()); - addCtBuyerList.add(ctBuyer); - } - } - String returnDataStr = null; - String filePath = propertiesConfig.getUploadImgPath().get(PublicConstant.EXPORT_EXCEL_FILE_TYPE); - String fileName = "买家导入异常信息表-" + snowflake.nextIdStr(); - if (ObjectUtil.isNotEmpty(ctBuyerExportList)) { - ExcelUtils.exportFile(SystemConfig.IMG_PATH + filePath, fileName, ctBuyerExportList); - returnDataStr = SystemConfig.FILE_VISIT_ADDR + filePath + fileName + ".xlsx"; - // returnDataStr = "http://localhost:8008/file" + filePath + fileName + ".xlsx"; - } - - if (ObjectUtil.isNotEmpty(addCtBuyerList)) { - ctBuyerService.saveBatch(addCtBuyerList); - } - - return Dto.returnResult(ObjectUtil.isEmpty(returnDataStr) ? true : returnDataStr); - } - - /** - * ExcelVpn信息模板导出 - */ - @ApiOperation("买家信息Excel模版导出") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log(value = "买家信息Excel模版导出") - @GetMapping("/exportTemp") - @AnonymousAccess - public void exportBuyer(HttpServletResponse response) { - ExcelUtils.exportTemplate(response, "买家导入模板", CtBuyerExportTemple.class); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtCardController.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtCardController.java deleted file mode 100644 index e7d0888..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtCardController.java +++ /dev/null @@ -1,307 +0,0 @@ -package me.zhengjie.modules.group.controller.base; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.date.DateUtil; -import cn.hutool.core.lang.Snowflake; -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.metadata.IPage; -import io.swagger.annotations.*; -import lombok.RequiredArgsConstructor; -import me.zhengjie.annotation.AnonymousAccess; -import me.zhengjie.annotation.FormSubmission; -import me.zhengjie.annotation.Log; -import me.zhengjie.annotation.type.LogActionType; -import me.zhengjie.config.PropertiesConfig; -import me.zhengjie.config.SystemConfig; -import me.zhengjie.constant.PublicConstant; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.CtCard; -import me.zhengjie.entity.CtCardExport; -import me.zhengjie.entity.CtCardExportTemple; -import me.zhengjie.entity.CtCardImport; -import me.zhengjie.enums.CardStatusEnum; -import me.zhengjie.error.ErrorCodeEnum; -import me.zhengjie.modules.group.dto.CtCardAddDTO; -import me.zhengjie.modules.group.dto.CtCardListDTO; -import me.zhengjie.modules.group.dto.CtCardUpdateDTO; -import me.zhengjie.modules.group.dto.IdDTO; -import me.zhengjie.service.CtCardService; -import me.zhengjie.service.vo.CtCardDetailVO; -import me.zhengjie.service.vo.CtCardListVO; -import me.zhengjie.utils.PageUtils; -import me.zhengjie.utils.excel.ExcelUtils; -import org.springframework.beans.BeanUtils; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletResponse; -import javax.validation.Valid; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - - -/** - * - * @Description 群控管理-信用卡 控制类 - * @Date 2022-06-22 - * @Author rch - */ -@Validated -@RequestMapping("/api/ctCard") -@RestController -@RequiredArgsConstructor -@Api(tags = "业务:信用卡管理") -public class CtCardController { - - @Resource - private CtCardService ctCardService; - @Resource - private PropertiesConfig propertiesConfig; - @Resource - private Snowflake snowflake; - - /** - * 分页查询信用卡信息 - */ - @ApiOperation("分页查询信用卡数据") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("分页查询信用卡信息") - @PostMapping("/list") - public Dto getCardList(@Valid @RequestBody CtCardListDTO dto) { - IPage page= ctCardService.page(dto.getiPage(), dto.getWrapper()); - List list = new ArrayList<>(); - for (CtCard record : page.getRecords()) { - CtCardListVO vo = new CtCardListVO(); - BeanUtil.copyProperties(record, vo); - list.add(vo); - } - - PageUtils pageUtils = new PageUtils(page.getTotal(),list); - return Dto.returnResult(pageUtils); - } - - /** - * 新增信用卡信息 - */ - @ApiOperation("新增信用卡") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log(value = "新增信用卡信息",type = LogActionType.ADD) - @PostMapping("/add") - @FormSubmission - public Dto addCard(@Valid @RequestBody CtCardAddDTO dto) { - - CtCard ctCard = new CtCard(); - BeanUtil.copyProperties(dto, ctCard); - return Dto.returnResult(ctCardService.save(ctCard)); - } - - /** - * 根据Id获取信用卡详情 - */ - @ApiOperation("根据Id获取信用卡详情") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("根据Id获取信用卡详情") - @PostMapping("/getById") - public Dto getCardById(@Valid @RequestBody IdDTO idDTO) { - return Dto.returnResult(ctCardService.getById(idDTO.getId())); - } - - - /** - * 根据id删除信用卡信息 - * @author: rch - */ - @ApiOperation("根据id删除信用卡信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 3300, message = "信用卡信息不存在,或者已删除或异常!") - }) - @Log(value = "根据id删除信用卡信息",type = LogActionType.DELETE) - @PostMapping("/delete") - public Dto delCard(@Valid @RequestBody IdDTO idDTO) { - - // 先查询 - CtCard ctCard = ctCardService.getById(idDTO.getId()); - if (ObjectUtil.isEmpty(ctCard) || CardStatusEnum.DEL.eqValue(ctCard.getStatus())) { - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_CARD_INFO); - } - - CtCard updateCtCard = new CtCard(); - updateCtCard.setId(idDTO.getId()); - updateCtCard.setStatus(CardStatusEnum.DEL.value()); - - return Dto.returnResult(ctCardService.updateById(updateCtCard)); - } - - - /** - * 根据id修改信用卡状态异常 - * @author: rch - */ - @ApiOperation("根据id修改信用卡状态异常") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 3300, message = "信用卡信息不存在,或者已删除或异常!") - }) - @Log(value = "根据id修改信用卡状态异常",type = LogActionType.UPDATE) - @PostMapping("/abMormal") - public Dto abMormal(@Valid @RequestBody IdDTO idDTO) { - - // 先查询 - CtCard ctCard = ctCardService.getById(idDTO.getId()); - if (ObjectUtil.isEmpty(ctCard) || CardStatusEnum.AB_NORMAL.eqValue(ctCard.getStatus())) { - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_CARD_INFO); - } - - CtCard updateCtCard = new CtCard(); - updateCtCard.setId(idDTO.getId()); - updateCtCard.setStatus(CardStatusEnum.AB_NORMAL.value()); - - return Dto.returnResult(ctCardService.updateById(updateCtCard)); - } - - - /** - * 编辑信用卡信息 - */ - @ApiOperation("编辑信用卡信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 3301, message = "信用卡信息不存在!") - }) - @Log(value = "编辑信用卡信息",type = LogActionType.UPDATE) - @PostMapping("/edit") - @FormSubmission - public Dto editCard(@Valid @RequestBody CtCardUpdateDTO dto) { - - // 根据id 判断是否存在 - CtCard ctCard = ctCardService.getById(dto.getId()); - if (ObjectUtil.isEmpty(ctCard)) { - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_CARD); - } - - CtCard updateCard = new CtCard(); - BeanUtil.copyProperties(dto, updateCard); - - return Dto.returnResult(ctCardService.updateById(updateCard)); - } - - /** - * Excel导入信用卡信息 - * @param file - * @param response - * @return - * @throws Exception - */ - @ApiOperation("Excel导入信用卡信息") - @ApiImplicitParams({ - @ApiImplicitParam(value = "上传文件", name = "file", dataType = "__file", required = true) - }) - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log(value = "Excel导入信用卡信息",type = LogActionType.ADD) - @PostMapping("/import") - public Dto importCard(@RequestPart("file")MultipartFile file, HttpServletResponse response) throws Exception { - - // TODO 对Excel 信息进行检测 如果不符合要求的 最终要导出错误Excel提示 - List ctCardImportList = ExcelUtils.readMultipartFile(file, CtCardImport.class); - if (ObjectUtil.isEmpty(ctCardImportList)) { - return Dto.returnResult(true); - } - - List addCtCardList = new ArrayList<>(); - List numberValueList = ctCardService.getNumberList(); - List ctCardExportList = new ArrayList<>(); - for (CtCardImport ctCardImport:ctCardImportList) { - CtCardExport ctCardExport = new CtCardExport(); - BeanUtil.copyProperties(ctCardImport, ctCardExport); - - StringBuffer errorStrBuf = new StringBuffer(); - String rowTips = ctCardImport.getRowTips(); - if (ObjectUtil.isNotEmpty(rowTips)) { - errorStrBuf.append(rowTips); - errorStrBuf.append(";"); - } - if (numberValueList.contains(ctCardImport.getNumber())) { - errorStrBuf.append("平台已经存在改卡号对应的信用卡信息!"); - errorStrBuf.append(";"); - } - // 判断日期格式是否正确 - String termOfValidity = ctCardImport.getTermOfValidity(); - String datePattern = "\\d{4}-\\d{1,2}-\\d{1,2}"; - if (!termOfValidity.matches(datePattern)) { - errorStrBuf.append("时间格式错误(yyyy-MM-dd)!"); - errorStrBuf.append(";"); - } - if (ObjectUtil.isNotEmpty(errorStrBuf)) { - ctCardExport.setError(errorStrBuf.toString()); - ctCardExportList.add(ctCardExport); - } else { - CtCard ctCard = new CtCard(); - BeanUtils.copyProperties(ctCardImport, ctCard); - addCtCardList.add(ctCard); - } - } - - String returnDataStr = null; - String filePath = propertiesConfig.getUploadImgPath().get(PublicConstant.EXPORT_EXCEL_FILE_TYPE); - String fileName = "信用卡导入异常信息表-" + snowflake.nextIdStr(); - if (ObjectUtil.isNotEmpty(ctCardExportList)) { - ExcelUtils.exportFile(SystemConfig.IMG_PATH + filePath, fileName, ctCardExportList); - returnDataStr = SystemConfig.FILE_VISIT_ADDR + filePath + fileName + ".xlsx"; -// returnDataStr = "http://localhost:8008/file" + filePath + fileName + ".xlsx"; - } - - if (ObjectUtil.isNotEmpty(addCtCardList)) { - ctCardService.saveBatch(addCtCardList); - } - - return Dto.returnResult(returnDataStr); - -// // 剔除已经有的了 -// List numberList = ctCardList.stream().map(CtCard::getNumber).collect(Collectors.toList()); -// if (ObjectUtil.isEmpty(numberValueList)) { -// return Dto.returnResult(true); -// } -// List finalNumberList = (List) CollectionUtils.subtract(numberList, numberValueList); -// if (ObjectUtil.isEmpty(finalNumberList)) { -// return Dto.returnResult(true); -// } -// ctCardList = ctCardList.stream().filter(c-> finalNumberList.contains(c.getNumber())).collect(Collectors.toList()); - - } - - - /** - * Excel信用卡信息模版导出 - * @param response - */ - @ApiOperation("Excel信用卡信息模版导出") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log(value = "Excel信用卡信息模版导出") - @GetMapping("/exportTemp") - @AnonymousAccess - public void importCard(HttpServletResponse response) { - ExcelUtils.exportTemplate(response, "信用卡模版", CtCardExportTemple.class); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtClickFarmingController.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtClickFarmingController.java deleted file mode 100644 index 3e481cc..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtClickFarmingController.java +++ /dev/null @@ -1,301 +0,0 @@ -package me.zhengjie.modules.group.controller.base; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.lang.Snowflake; -import cn.hutool.core.util.ObjectUtil; -import io.swagger.annotations.*; -import lombok.RequiredArgsConstructor; -import me.zhengjie.annotation.AnonymousAccess; -import me.zhengjie.annotation.FormSubmission; -import me.zhengjie.annotation.Log; -import me.zhengjie.annotation.type.LogActionType; -import me.zhengjie.config.PropertiesConfig; -import me.zhengjie.config.SystemConfig; -import me.zhengjie.constant.PublicConstant; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.*; -import me.zhengjie.enums.ClickFarmingStatusEnum; -import me.zhengjie.enums.ParamsTypeEnum; -import me.zhengjie.error.ErrorCodeEnum; -import me.zhengjie.modules.group.dto.CtClickFarmingAddDTO; -import me.zhengjie.modules.group.dto.CtClickFarmingDTO; -import me.zhengjie.modules.group.dto.CtClickFarmingEditDTO; -import me.zhengjie.modules.group.dto.IdDTO; -import me.zhengjie.service.CtBuyerService; -import me.zhengjie.service.CtClickFarmingService; -import me.zhengjie.service.vo.CtClickFarmEditDetailVO; -import me.zhengjie.service.vo.CtClickFarmingDetailVO; -import me.zhengjie.service.vo.CtClickFarmingVO; -import me.zhengjie.utils.PageUtils; -import me.zhengjie.utils.excel.ExcelUtils; -import org.springframework.beans.BeanUtils; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletResponse; -import javax.validation.Valid; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -/** - * - * @Description 群控管理-刷单信息 控制类 - * @Date 2022-06-22 - * @Author rch - */ -@Validated -@RequestMapping("/api/clickFarming") -@RestController -@RequiredArgsConstructor -@Api(tags = "业务:刷单信息管理") -public class CtClickFarmingController { - - @Resource - private CtClickFarmingService ctClickFarmingService; - @Resource - private PropertiesConfig propertiesConfig; - @Resource - private CtBuyerService ctBuyerService; - @Resource - private Snowflake snowflake; - - /** - * 分页查询刷单信息 - */ - @ApiOperation("分页查询刷单数据") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("分页查询刷单信息") - @PostMapping("/list") - public Dto getClickFarmingList(@Valid @RequestBody CtClickFarmingDTO dto) { - PageUtils pageUtilsResult = ctClickFarmingService.searchPageList(dto.getiPage(), dto.getWrapper()); - return Dto.returnResult(pageUtilsResult); - } - - /** - * 新增刷单信息 - */ - @ApiOperation("新增刷单信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log(value = "新增刷单信息",type = LogActionType.ADD) - @PostMapping("/add") - @FormSubmission - public Dto addClickFarming(@Valid @RequestBody CtClickFarmingAddDTO dto) { - - CtClickFarming ctClickFarming = new CtClickFarming(); - BeanUtil.copyProperties(dto, ctClickFarming); - return Dto.returnResult(ctClickFarmingService.save(ctClickFarming)); - } - - /** - * 根据id获取刷单信息 - */ - @ApiOperation("根据id获取刷单信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("根据id获取刷单信息") - @PostMapping("/getById") - public Dto getById(@Valid @RequestBody IdDTO idDTO) { - return Dto.returnResult(ctClickFarmingService.getDetailById(idDTO.getId())); - } - - /** - * 根据id获取修改回显信息 - */ - @ApiOperation("根据id获取修改回显信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("根据id获取修改回显信息") - @PostMapping("/getEditDetailById") - public Dto getEditDetailById(@Valid @RequestBody IdDTO idDTO) { - return Dto.returnResult(ctClickFarmingService.getEditDetailById(idDTO.getId())); - } - - /** - * 根据id删除刷单信息 - * @author: rch - */ - @ApiOperation("根据id删除刷单信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 3300, message = "信用卡信息不存在,或者已删除或异常!"), - @ApiResponse(code = 3901, message = "只有待执行的刷单信息才允许删除!") - }) - @Log(value = "根据id删除刷单信息",type = LogActionType.DELETE) - @PostMapping("/delete") - public Dto delClickFarming(@Valid @RequestBody IdDTO idDTO) { - - // 先查询 - CtClickFarming ctClickFarming = ctClickFarmingService.getById(idDTO.getId()); - if (ObjectUtil.isEmpty(ctClickFarming)) { - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_CARD_INFO); - } - - if (!ClickFarmingStatusEnum.TOBE_EXECUTION.eqValue(ctClickFarming.getStatus())) { - return Dto.getInstance(ErrorCodeEnum.ERROR_DEL_CLICKFARMING_INFO); - } - - return Dto.returnResult(ctClickFarmingService.removeById(idDTO.getId())); - } - - /** - * 编辑刷单信息 - */ - @ApiOperation("编辑刷单信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 3900, message ="刷单信息不存在!") - }) - @Log(value = "编辑刷单信息",type = LogActionType.UPDATE) - @PostMapping("/edit") - @FormSubmission - public Dto editClickFarming(@Valid @RequestBody CtClickFarmingEditDTO dto) { - // 判断状态 只有待执行状态太允许修改 - CtClickFarming ctClickFarming = ctClickFarmingService.getByIdLock(dto.getId()); - if (ObjectUtil.isEmpty(ctClickFarming)) { - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_CLICKFARMING_INFO); - } - - CtClickFarming updateCtClickFarming = new CtClickFarming(); - BeanUtil.copyProperties(dto, updateCtClickFarming); - - return Dto.returnResult(ctClickFarmingService.updateById(updateCtClickFarming)); - } - - /** - * - * @param file - * @param response - * @return - * @throws Exception - */ - @ApiOperation("Excel刷单信息导入") - @ApiImplicitParams({ - @ApiImplicitParam(value = "上传文件", name = "file", dataType = "__file", required = true) - }) - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log(value = "Excel刷单信息导入",type = LogActionType.ADD) - @PostMapping("/import") - public Dto importClickFarming(@RequestPart("file")MultipartFile file, HttpServletResponse response) throws Exception { - - // TODO 对Excel 信息进行检测 如果不符合要求的 最终要导出错误Excel提示 - List ctClickFarmingImportList = ExcelUtils.readMultipartFile(file, CtClickFarmingImport.class); - if (ObjectUtil.isEmpty(ctClickFarmingImportList)) { - return Dto.returnResult(true); - } - - List addCtClickFarmingList = new ArrayList<>(); - List ctClickFarmingExportList = new ArrayList<>(); - - // 买家id - List buyerAccountList = ctClickFarmingImportList.stream().map(c->c.getAccount()).collect(Collectors.toList()); - Map buyerMap = ctBuyerService.getBuyerList(buyerAccountList); - - for (CtClickFarmingImport ctClickFarmingImport:ctClickFarmingImportList) { - CtClickFarmingExport ctClickFarmingExport = new CtClickFarmingExport(); - BeanUtil.copyProperties(ctClickFarmingImport, ctClickFarmingExport); - - StringBuffer errorStrBuf = new StringBuffer(); - String rowTips = ctClickFarmingImport.getRowTips(); - if (ObjectUtil.isNotEmpty(rowTips)) { - errorStrBuf.append(rowTips); - errorStrBuf.append(";"); - } - - if (ObjectUtil.isEmpty(ctClickFarmingImport.getSpecification())) { - errorStrBuf.append("规格-必填!"); - errorStrBuf.append(";"); - } - if (ObjectUtil.isEmpty(ctClickFarmingImport.getColor())) { - errorStrBuf.append("颜色-必填!"); - errorStrBuf.append(";"); - } - if (ObjectUtil.isEmpty(ctClickFarmingImport.getExchange())) { - errorStrBuf.append("优惠劵-必填!"); - errorStrBuf.append(";"); - } - - // 判断类型 - if (ParamsTypeEnum.KEY_WORD.eqValue(ctClickFarmingImport.getParamsType())) { - if (ObjectUtil.isEmpty(ctClickFarmingImport.getKeyWord())) { - errorStrBuf.append("关键词-必填!"); - errorStrBuf.append(";"); - } - if (ObjectUtil.isEmpty(ctClickFarmingImport.getTitle())) { - errorStrBuf.append("标题-必填!"); - errorStrBuf.append(";"); - } - if (ObjectUtil.isEmpty(ctClickFarmingImport.getItem())) { - errorStrBuf.append("item-必填!"); - errorStrBuf.append(";"); - } - } else { - if (ObjectUtil.isEmpty(ctClickFarmingImport.getLink())) { - errorStrBuf.append("链接-必填!"); - errorStrBuf.append(";"); - } - } - - if (ObjectUtil.isEmpty(buyerMap) || !buyerMap.containsKey(ctClickFarmingImport.getAccount())) { - errorStrBuf.append("买家信息不存在!"); - errorStrBuf.append(";"); - } else { - Long buyerId = buyerMap.entrySet().stream().collect(Collectors.toMap(entity -> entity.getKey(), entity -> entity.getValue())).get(ctClickFarmingImport.getAccount()).getId(); - ctClickFarmingImport.setBuyerId(buyerId); - } - if (ObjectUtil.isNotEmpty(errorStrBuf)) { - ctClickFarmingExport.setError(errorStrBuf.toString()); - ctClickFarmingExportList.add(ctClickFarmingExport); - } else { - CtClickFarming ctClickFarming = new CtClickFarming(); - BeanUtils.copyProperties(ctClickFarmingImport, ctClickFarming); - addCtClickFarmingList.add(ctClickFarming); - } - } - - String returnDataStr = null; - String filePath = propertiesConfig.getUploadImgPath().get(PublicConstant.EXPORT_EXCEL_FILE_TYPE); - String fileName = "刷单信息导入异常信息表-" + snowflake.nextIdStr(); - if (ObjectUtil.isNotEmpty(ctClickFarmingExportList)) { - ExcelUtils.exportFile(SystemConfig.IMG_PATH + filePath, fileName, ctClickFarmingExportList); - returnDataStr = SystemConfig.FILE_VISIT_ADDR + filePath + fileName + ".xlsx"; -// returnDataStr = "http://localhost:8008/file" + filePath + fileName + ".xlsx"; - } - - if (ObjectUtil.isNotEmpty(addCtClickFarmingList)) { - ctClickFarmingService.saveBatch(addCtClickFarmingList); - } - - return Dto.returnResult(returnDataStr); - } - - @ApiOperation("Excel刷单信息模版导出") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log(value = "Excel刷单信息模版导出") - @GetMapping("/exportTemp") - @AnonymousAccess - public void importClickFarming(HttpServletResponse response) { - ExcelUtils.exportTemplate(response, "刷单信息模版", CtClickFarmingExportTemp.class); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtClickOrderController.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtClickOrderController.java deleted file mode 100644 index fadc5d1..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtClickOrderController.java +++ /dev/null @@ -1,330 +0,0 @@ -package me.zhengjie.modules.group.controller.base; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.lang.Snowflake; -import cn.hutool.core.util.ObjectUtil; -import io.swagger.annotations.*; -import lombok.RequiredArgsConstructor; -import me.zhengjie.annotation.AnonymousAccess; -import me.zhengjie.annotation.Log; -import me.zhengjie.annotation.rest.AnonymousPostMapping; -import me.zhengjie.annotation.type.LogActionType; -import me.zhengjie.config.PropertiesConfig; -import me.zhengjie.config.SystemConfig; -import me.zhengjie.constant.Constants; -import me.zhengjie.constant.PublicConstant; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.*; -import me.zhengjie.enums.ClickFarmingStatusEnum; -import me.zhengjie.enums.OrderTypeEnum; -import me.zhengjie.error.ErrorCodeEnum; -import me.zhengjie.modules.group.dto.*; -import me.zhengjie.service.CtClickFarmingService; -import me.zhengjie.service.CtClickOrderService; -import me.zhengjie.service.CtCompanyService; -import me.zhengjie.service.vo.CtClickOrderDetailVO; -import me.zhengjie.service.vo.CtClickOrderListVO; -import me.zhengjie.utils.PageUtils; -import me.zhengjie.utils.excel.ExcelUtils; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.validation.Valid; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - - -/** - * - * @Description 群控管理-刷单信息订单 控制类 - * @Date 2022-06-22 - * @Author rch - */ -@Validated -@RequestMapping("/api/clickOrder") -@RestController -@RequiredArgsConstructor -@Api(tags = "业务:刷单订单管理") -public class CtClickOrderController { - - @Resource - private CtClickOrderService ctClickOrderService; - @Resource - private CtCompanyService ctCompanyService; - @Resource - private PropertiesConfig propertiesConfig; - @Resource - private CtClickFarmingService ctClickFarmingService; - @Resource - private Snowflake snowflake; - - /** - * 分页查询刷单订单信息 - */ - @ApiOperation("分页查询刷单订单信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("分页查询刷单订单信息") - @PostMapping("/list") - @AnonymousAccess - public Dto getClickOrderList(@Valid @RequestBody CtClickOrderListDTO dto) { - PageUtils pageUtilsResult = ctClickOrderService.searchPageList(dto.getiPage(), dto.getWrapper()); - return Dto.returnResult(pageUtilsResult); - } - - /** - * 开放刷单订单接口给到ERP - * @param dto - * @return - */ - @ApiOperation("开放刷单订单接口") - @ApiImplicitParam(value = "鉴权token", name = "erpToken", paramType = "header", dataType = "String", required = true) - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 4101, message = "鉴权信息不能为空!"), - @ApiResponse(code = 4102, message = "鉴权信息错误,请检查后重试!") - }) - @Log(value = "开放刷单订单接口") - @AnonymousPostMapping(value = "/searchClickOrder") - public Dto searchClickOrder(@Valid @RequestBody SearchOrderListDTO dto, HttpServletRequest request) { - - // 1.权限检验 - String erpToken = request.getHeader("erpToken"); - if (ObjectUtil.isEmpty(erpToken)) { - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_NULL_ERP_AUTH_TOKEN); - } - - if (!Constants.ERP_AUTH_TOKEN.equals(erpToken)) { - return Dto.getInstance(ErrorCodeEnum.ERROR_ERP_AUTH_TOKEN); - } - - // 2.根据请求条件查询记录并返回 - PageUtils pageUtilsResult = ctClickOrderService.searchPageList(dto.getiPage(), dto.getWrapper()); - return Dto.returnResult(pageUtilsResult); - } - - /** - * 根据id刷单信息详情详情 - */ - @ApiOperation("根据id刷单信息详情详情") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("根据id刷单信息详情详情") - @PostMapping("/getById") - public Dto getCardById(@Valid @RequestBody IdDTO idDTO) { - // 获取 - CtClickOrderDetailVO ctClickOrderDetailVO = ctClickOrderService.getClickOrderDetailById(idDTO.getId()); -// if (ObjectUtil.isNotEmpty(ctClickOrderDetailVO.getPaths())) { -// List pathStrList = new ArrayList<>(); -// List pathList = Arrays.asList(ctClickOrderDetailVO.getPaths().split(",")); -// for (String path:pathList) { -//// path = "http://localhost:8008/file" + path; -// path = SystemConfig.FILE_VISIT_ADDR + path; -// pathStrList.add(path); -// } -// ctClickOrderDetailVO.setPaths(pathStrList.stream().collect(Collectors.joining(","))); -// } - return Dto.returnResult(ctClickOrderDetailVO); - } - - - /** - * 新增订单评论信息 - */ - @ApiOperation("新增订单评论信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log(value = "新增订单评论信息") - @PostMapping("/add") - public Dto add(@Valid @RequestBody CtClickOrderAddDto ctClickOrderAddDto) { - - // 保证仅仅 下单成功并且支付失败状态才允许执行 - - CtClickOrder addCtClickOrder = new CtClickOrder(); - addCtClickOrder.setType(OrderTypeEnum.IMPORT.value()); - BeanUtil.copyProperties(ctClickOrderAddDto, addCtClickOrder); - return Dto.returnResult(ctClickOrderService.save(addCtClickOrder)); - } - - /** - * 刷单订单导入 - */ - @ApiOperation("Excel刷单订单导入") - @ApiImplicitParams({ - @ApiImplicitParam(value = "上传文件", name = "file", dataType = "__file", required = true) - }) - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log(value = "Excel刷单订单导入",type = LogActionType.ADD) - @PostMapping("import") - public Dto importOrder(@RequestPart("file") MultipartFile file, HttpServletResponse response)throws Exception{ - - //TODO 对Excel 信息进行检测 如果不符合要求的 最终要导出错误Excel提示 - List ctClickOrderImportList = ExcelUtils.readMultipartFile(file, CtClickOrderImport.class); - if(ObjectUtil.isEmpty(ctClickOrderImportList)){ - return Dto.returnResult(true); - } - - List addCtClickOrderList = new ArrayList<>(); - // 订单id 唯一 - List importOrderIdList = ctClickOrderImportList.stream().map(c->c.getOrderId()).collect(Collectors.toList()); - importOrderIdList = ctClickOrderService.getOrderId(importOrderIdList); - // 判断公司信息是否存在 - List companyNameList = ctClickOrderImportList.stream().map(c->c.getCompanyName()).collect(Collectors.toList()); - Map companyNameMap = ctCompanyService.getNameList(companyNameList); - - List ctClickOrderExportList = new ArrayList<>(); - for(CtClickOrderImport ctClickOrderImport : ctClickOrderImportList) { - CtClickOrderExport ctClickOrderExport = new CtClickOrderExport(); - BeanUtil.copyProperties(ctClickOrderImport, ctClickOrderExport); - - StringBuffer errorStrBuf = new StringBuffer(); - String rowTips = ctClickOrderImport.getRowTips(); - if (ObjectUtil.isNotEmpty((rowTips))) { - errorStrBuf.append(rowTips); - errorStrBuf.append(";"); - } - - String resultStr = checkImportInfo(importOrderIdList, companyNameMap, ctClickOrderImport); - if (ObjectUtil.isNotEmpty(resultStr)) { - errorStrBuf.append(resultStr); - errorStrBuf.append(";"); - } - - Long companyNameId = companyNameMap.entrySet().stream().collect(Collectors.toMap(entity -> entity.getValue(), entity -> entity.getKey())).get(ctClickOrderImport.getCompanyName()); - ctClickOrderImport.setCompanyId(companyNameId); - if (ObjectUtil.isNotEmpty(errorStrBuf)) { - ctClickOrderExport.setError(errorStrBuf.toString()); - ctClickOrderExportList.add(ctClickOrderExport); - } else { - CtClickOrder ctClickOrder = new CtClickOrder(); - BeanUtil.copyProperties(ctClickOrderImport, ctClickOrder); - ctClickOrder.setType(OrderTypeEnum.IMPORT.value()); - addCtClickOrderList.add(ctClickOrder); - } - } - - String returnDataStr = null; - String filePath = propertiesConfig.getUploadImgPath().get(PublicConstant.EXPORT_EXCEL_FILE_TYPE); - String fileName = "刷单订单导入异常信息表-" + snowflake.nextIdStr(); - if(ObjectUtil.isNotEmpty(ctClickOrderExportList)){ - ExcelUtils.exportFile(SystemConfig.IMG_PATH + filePath, fileName, ctClickOrderExportList); - returnDataStr = SystemConfig.FILE_VISIT_ADDR + filePath + fileName + ".xlsx"; - // returnDataStr = "http://localhost:8008/file" + filePath + fileName + ".xlsx"; - } - - if(ObjectUtil.isNotEmpty(addCtClickOrderList)){ - ctClickOrderService.saveBatch(addCtClickOrderList); - } - - return Dto.returnResult(returnDataStr); - } - - - - /** - * Excel订单模版导出 - */ - @ApiOperation("Excel订单模版导出") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log(value = "Excel订单模版导出") - @GetMapping("/exportTemp") - @AnonymousAccess - public void exportVpn(HttpServletResponse response) { - ExcelUtils.exportTemplate(response, "订单导入模板", CtClickOrderExportTemple.class, true); - } - - /** - * 补录订单信息 - * 仅仅 下单成功并且支付失败状态才允许执行此接口 - */ - @ApiOperation("补录订单信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 3900, message = "刷单信息不存在!"), - @ApiResponse(code = 3903, message = "仅支付成功失败状态才允许补录!") - }) - @Log(value = "补录订单信息") - @PostMapping("/supplement") - public Dto supplementOrder(@Valid @RequestBody CtClickOrderSupplementDto ctClickOrderSupplementDto) { - - // 保证仅仅 下单成功并且支付失败状态才允许执行 - Long clickFarmingId = ctClickOrderSupplementDto.getClickFarmingId(); - CtClickFarming ctClickFarming = ctClickFarmingService.getById(clickFarmingId); - if (ObjectUtil.isEmpty(ctClickFarming)) { - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_CLICKFARMING_INFO); - } - if (!ClickFarmingStatusEnum.PAY_OK_ERROR.value().equals(ctClickFarming.getStatus())) { - return Dto.getInstance(ErrorCodeEnum.ERROR_CLICKFARMING_NOT_SUPPLEMENT); - } - - CtClickOrder ctClickOrder = new CtClickOrder(); - BeanUtil.copyProperties(ctClickOrderSupplementDto, ctClickOrder); - // 补录订单信息 - return Dto.returnResult(ctClickOrderService.supplement(clickFarmingId, ctClickOrder)); - } - - - /** - * 新增评论信息 - */ - @ApiOperation("新增评论信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 4100, message = "订单信息不存在") - }) - @Log(value = "新增评论信息") - @PostMapping("/comment") - public Dto comment(@Valid @RequestBody CtClickOrderCommentDto ctClickOrderCommentDto) { - - // 保证仅仅 下单成功并且支付失败状态才允许执行 - CtClickOrder ctClickOrder = ctClickOrderService.getById(ctClickOrderCommentDto.getId()); - if (ObjectUtil.isEmpty(ctClickOrder)) { - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_CLICK_ORDER_INFO); - } - - CtClickOrder updateCtClickOrder = new CtClickOrder(); - BeanUtil.copyProperties(ctClickOrderCommentDto, updateCtClickOrder); - return Dto.returnResult(ctClickOrderService.updateById(updateCtClickOrder)); - } - - /** - * 导入数据内容检验 - * @param importOrderIdList - * @param companyNameMap - * @param ctClickOrderImport - * @return - */ - public String checkImportInfo(List importOrderIdList, Map companyNameMap, CtClickOrderImport ctClickOrderImport) { - if (ObjectUtil.isNotEmpty(companyNameMap)) { - if (!companyNameMap.containsValue(ctClickOrderImport.getCompanyName())) { - return "对应名称的公司不存在!"; - } - } else if(ObjectUtil.isNotEmpty(ctClickOrderImport)) { - if (importOrderIdList.contains(ctClickOrderImport.getOrderId())) { - return "该笔订单已存在!"; - } - } - return null; - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtCompanyController.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtCompanyController.java deleted file mode 100644 index 88fa0fb..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtCompanyController.java +++ /dev/null @@ -1,187 +0,0 @@ -package me.zhengjie.modules.group.controller.base; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import me.zhengjie.annotation.FormSubmission; -import me.zhengjie.annotation.Log; -import me.zhengjie.annotation.type.LogActionType; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.CtBuyer; -import me.zhengjie.entity.CtCompany; -import me.zhengjie.entity.CtOrder; -import me.zhengjie.error.ErrorCodeEnum; -import me.zhengjie.modules.group.dto.CtCompanyAddDTO; -import me.zhengjie.modules.group.dto.CtCompanyListDTO; -import me.zhengjie.modules.group.dto.CtCompanyUpdateDTO; -import me.zhengjie.modules.group.dto.IdDTO; -import me.zhengjie.service.CtCompanyService; -import me.zhengjie.service.CtOrderService; -import me.zhengjie.service.vo.CtCompanyInfoVO; -import me.zhengjie.service.vo.CtCompanyVO; -import me.zhengjie.utils.PageUtils; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import javax.annotation.Resource; -import javax.validation.Valid; -import java.util.ArrayList; -import java.util.List; - - -/** - * - * @Description 群控管理-公司 控制类 - * @Date 2022-06-23 - * @Author rch - */ -@Validated -@RequestMapping("/api/ctCompany") -@RestController -@Api(tags = "业务:公司信息管理") -public class CtCompanyController { - - @Resource - private CtCompanyService ctCompanyService; - @Resource - private CtOrderService ctOrderService; - - /** - * 分页查询公司信息 - */ - @ApiOperation("分页查询公司信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("分页查询公司信息") - @PostMapping("/list") - public Dto getCompanyList(@Valid @RequestBody CtCompanyListDTO dto) { - IPage page = ctCompanyService.page(dto.getiPage(), dto.getWrapper()); - List list = new ArrayList<>(); - for (CtCompany record : page.getRecords()) { - CtCompanyVO ctCompanyVO = new CtCompanyVO(); - BeanUtil.copyProperties(record, ctCompanyVO); - list.add(ctCompanyVO); - } - PageUtils pageUtils = new PageUtils(page.getTotal(),list); - return Dto.returnResult(pageUtils); - } - - /** - * 新增公司信息 - */ - @ApiOperation("新增公司信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log(value = "新增公司信息",type = LogActionType.ADD) - @PostMapping("/add") - @FormSubmission - public Dto addCompany(@Valid @RequestBody CtCompanyAddDTO dto) { - CtCompany ctCompany = new CtCompany(); - BeanUtil.copyProperties(dto, ctCompany); - - // TODO 商户码(公司调用api公司唯一标识) -按照一定规则生成 - ctCompany.setNumber("666666"); - // TODO 商户token(公司调用api公司token身份标识)-按照一定规则生成 - ctCompany.setToken("7777777"); - return Dto.returnResult(ctCompanyService.save(ctCompany)); - } - - /** - * 根据id公司信息详情 - */ - @ApiOperation("根据id公司信息详情") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("根据id公司信息详情详情") - @PostMapping("/getById") - public Dto getCompanyById(@Valid @RequestBody IdDTO idDTO) { - return Dto.returnResult(ctCompanyService.getById(idDTO.getId())); - } - - /** - * 编辑公司信息 - */ - @ApiOperation("编辑公司信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 3300, message = "公司信息不存在!") - }) - @Log(value = "编辑公司信息",type = LogActionType.UPDATE) - @PostMapping("/edit") - @FormSubmission - public Dto editCompany(@Valid @RequestBody CtCompanyUpdateDTO dto) { - - // TODO 检验平台ID和平台名称是否一致 - - // 根据id 判断是否存在 - CtCompany ctCompany = ctCompanyService.getById(dto.getId()); - if (ObjectUtil.isEmpty(ctCompany)) { - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_COMPANY); - } - - CtCompany updateCtCompany = new CtCompany(); - BeanUtil.copyProperties(dto, updateCtCompany); - return Dto.returnResult(ctCompanyService.updateById(updateCtCompany)); - } - - /** - * 根据id删除公司信息 - * @author: rch - */ - @ApiOperation("根据id删除公司信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 3201, message = "该公司下存在订单信息,不允许删除!") - }) - @Log(value = "根据id删除公司信息",type = LogActionType.DELETE) - @PostMapping("/delete") - public Dto delCompany(@Valid @RequestBody IdDTO idDTO) { - // 判断公司下存在订单信息则不允许删除 - QueryWrapper ctOrderQueryWrapper = new QueryWrapper<>(); - ctOrderQueryWrapper.eq("company_id", idDTO.getId()); - Integer count = ctOrderService.count(ctOrderQueryWrapper); - if (ObjectUtil.isNotEmpty(count) && count > 0) { - return Dto.getInstance(ErrorCodeEnum.ERROR_EXITS_CT_ORDER_INFO); - } - - return Dto.returnResult(ctCompanyService.removeById(idDTO.getId())); - } - - /** - * 获取所有公司信息 (公司id 公司名称) - * 为新增 公司提供公司所属公司服务 - * @return - */ - @ApiOperation("获取所有公司信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log(value = "获取所有公司信息") - @GetMapping("/getAll") - public Dto allCompany() { - List ctCompanyList = ctCompanyService.list(); - List ctCompanyInfoVOList = new ArrayList<>(); - if (ObjectUtil.isNotEmpty(ctCompanyList)) { - for (CtCompany ctCompany:ctCompanyList) { - CtCompanyInfoVO ctCompanyInfoVO = new CtCompanyInfoVO(); - BeanUtil.copyProperties(ctCompany, ctCompanyInfoVO); - ctCompanyInfoVOList.add(ctCompanyInfoVO); - } - } - return Dto.returnResult(ctCompanyInfoVOList); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtDhPayController.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtDhPayController.java deleted file mode 100644 index 1fbf0b9..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtDhPayController.java +++ /dev/null @@ -1,300 +0,0 @@ -package me.zhengjie.modules.group.controller.base; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.lang.Snowflake; -import cn.hutool.core.util.ObjectUtil; -import com.alibaba.fastjson.JSON; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.qiniu.util.Json; -import io.swagger.annotations.*; -import lombok.RequiredArgsConstructor; -import me.zhengjie.annotation.AnonymousAccess; -import me.zhengjie.annotation.FormSubmission; -import me.zhengjie.annotation.Log; -import me.zhengjie.annotation.type.LogActionType; -import me.zhengjie.config.PropertiesConfig; -import me.zhengjie.config.SystemConfig; -import me.zhengjie.constant.PublicConstant; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.CtDhPay; -import me.zhengjie.entity.CtDhPayExport; -import me.zhengjie.entity.CtDhPayExportTemple; -import me.zhengjie.entity.CtDhPayImport; -import me.zhengjie.enums.DhPayStatusEnum; -import me.zhengjie.error.ErrorCodeEnum; -import me.zhengjie.modules.group.dto.CtDhPayAddDTO; -import me.zhengjie.modules.group.dto.CtDhPayListDTO; -import me.zhengjie.modules.group.dto.IdDTO; -import me.zhengjie.service.CtDhPayService; -import me.zhengjie.service.vo.CtDhPayDetailVO; -import me.zhengjie.service.vo.CtDhPayListVO; -import me.zhengjie.utils.PageUtils; -import me.zhengjie.utils.excel.ExcelUtils; -import org.springframework.beans.BeanUtils; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletResponse; -import javax.validation.Valid; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - - -/** - * @Description 群控管理-敦煌支付 控制类 - * @Date 2022-06-22 - * @Author rch - */ -@Validated -@RequestMapping("/api/dhPay") -@RestController -@RequiredArgsConstructor -@Api(tags = "业务:敦煌支付管理") -public class CtDhPayController { - - @Resource - private PropertiesConfig propertiesConfig; - @Resource - private Snowflake snowflake; - @Resource - private CtDhPayService ctDhPayService; - - /** - * 分页查询敦煌支付信息 - */ - @ApiOperation("分页查询敦煌支付信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("分页查询敦煌支付信息") - @PostMapping("/list") - @AnonymousAccess - public Dto getDhPayList(@Valid @RequestBody CtDhPayListDTO dto) { - PageUtils pageUtilsResult = ctDhPayService.searchPageList(dto.getiPage(), dto.getWrapper()); - return Dto.returnResult(pageUtilsResult); - } - - /** - * 新增敦煌支付信息 - */ - @ApiOperation("新增敦煌支付信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log(value = "新增敦煌支付信息", type = LogActionType.ADD) - @PostMapping("/add") - @AnonymousAccess - @FormSubmission - public Dto addDhPay(@Valid @RequestBody CtDhPayAddDTO dto) { - List ctCardList = new ArrayList<>(); - List errCtDhPay = new ArrayList<>(); - String orderIdListStr = dto.getOrderId(); - String[] orderIdList = orderIdListStr.split(","); - List allCtDhPay = ctDhPayService.list(); - for (String orderId : orderIdList) { - CtDhPay ctDhPay = new CtDhPay(); - ctDhPay.setBuyerName(dto.getBuyerName()); - ctDhPay.setOrderId(orderId); - - // TODO 剔除已经存在的 同导入逻辑的检验 - List anyMatchList = allCtDhPay.stream().filter(d -> d.getBuyerName().equals(ctDhPay.getBuyerName()) && d.getOrderId().equals(ctDhPay.getOrderId())).collect(Collectors.toList()); - if (ObjectUtil.isNotEmpty(anyMatchList)) { - errCtDhPay.add(ctDhPay); - } else { - ctCardList.add(ctDhPay); - } - } - if (ObjectUtil.isNotEmpty(errCtDhPay)) { - StringBuffer errStrBuffer = new StringBuffer(); - errStrBuffer.append("该买家对应的订单编号"); - for (int i = 0; i < errCtDhPay.size(); i++) { - CtDhPay errPay = errCtDhPay.get(i); - if (i != 0) { - errStrBuffer.append("、"); - } - errStrBuffer.append(errPay.getOrderId()); - } - errStrBuffer.append("存在重复信息,新增失败"); - if (ObjectUtil.isNotEmpty(ctCardList)) { - ctDhPayService.saveBatch(ctCardList); - } - return Dto.returnErrorResult(errStrBuffer.toString()); - } else { - if (ObjectUtil.isNotEmpty(ctCardList)) { - return Dto.returnResult(ctDhPayService.saveBatch(ctCardList)); - } - } - return Dto.returnResult(true); - } - - /** - * 根据id敦煌支付信息 - */ - @ApiOperation("根据id敦煌支付信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("根据id敦煌支付信息") - @PostMapping("/getById") - @AnonymousAccess - public Dto getDhPayById(@Valid @RequestBody IdDTO idDTO) { - return Dto.returnResult(ctDhPayService.getById(idDTO.getId())); - } - - - /** - * 根据id删除敦煌支付信息 - * - * @author: rch - */ - @ApiOperation("根据id删除敦煌支付信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 3800, message = "敦煌支付信息不存在,或已删除!") - }) - @Log(value = "根据id删除敦煌支付信息", type = LogActionType.DELETE) - @PostMapping("/delete") - @AnonymousAccess - public Dto delDhPay(@Valid @RequestBody IdDTO idDTO) { - - // 先查询 - CtDhPay ctDhPay = ctDhPayService.getById(idDTO.getId()); - if (ObjectUtil.isEmpty(ctDhPay) || DhPayStatusEnum.DEL.eqValue(ctDhPay.getStatus())) { - return Dto.getInstance(ErrorCodeEnum.ERROR_DH_PAY_NOT_FIND_OR_SUCCESS); - } - - CtDhPay updateCtDhPay = new CtDhPay(); - updateCtDhPay.setId(idDTO.getId()); - updateCtDhPay.setStatus(DhPayStatusEnum.DEL.value()); - - return Dto.returnResult(ctDhPayService.updateById(updateCtDhPay)); - } - - - /** - * Excel敦煌支付信息导入 - * @param file - * @param response - * @return - * @throws Exception - */ - @ApiOperation("Excel敦煌支付信息导入") - @ApiImplicitParams({ - @ApiImplicitParam(value = "上传文件", name = "file", dataType = "__file", required = true) - }) - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log(value = "Excel敦煌支付信息导入", type = LogActionType.ADD) - @PostMapping("/import") - public Dto importCard(@RequestPart("file") MultipartFile file, HttpServletResponse response) throws Exception { - - // TODO 对Excel 信息进行检测 如果不符合要求的 最终要导出错误Excel提示 - List ctDhPayImportList = ExcelUtils.readMultipartFile(file, CtDhPayImport.class); - if (ObjectUtil.isEmpty(ctDhPayImportList)) { - return Dto.returnResult(true); - } - - List addCtDhPayList = new ArrayList<>(); - List errCtDhPayList = new ArrayList<>(); - List ctDhPayExportList = new ArrayList<>(); - - List buyerNameList = ctDhPayImportList.stream().map(CtDhPayImport::getBuyerName).collect(Collectors.toList()); - List orderIdList = ctDhPayImportList.stream().map(CtDhPayImport::getOrderId).collect(Collectors.toList()); - - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.in("buyer_name", buyerNameList); - queryWrapper.or(); - queryWrapper.in("order_id", orderIdList); - List queryCtDhPay = ctDhPayService.list(queryWrapper); - - for (CtDhPayImport ctDhPayImport : ctDhPayImportList) { - CtDhPayExport ctDhPayExport = new CtDhPayExport(); - BeanUtil.copyProperties(ctDhPayImport, ctDhPayExport); - StringBuffer errorStrBuf = new StringBuffer(); - String rowTips = ctDhPayImport.getRowTips(); - if (ObjectUtil.isNotEmpty(rowTips)) { - errorStrBuf.append(rowTips); - errorStrBuf.append(";"); - } - //判断订单号是否按照规格输入 - String regex = "^[0-9]+(,[0-9]+)*$"; - if (!Pattern.matches(regex, ctDhPayImport.getOrderId())) { - errorStrBuf.append("订单编号格式输入错误,请重新输入"); - } else { - String[] orderIdArr = ctDhPayImport.getOrderId().split(","); - for (String orderId : orderIdArr) { - CtDhPay ctDhPay = new CtDhPay(); - ctDhPay.setBuyerName(ctDhPayImport.getBuyerName()); - ctDhPay.setOrderId(orderId); - - List anyMatchList = queryCtDhPay.stream().filter(d -> d.getBuyerName().equals(ctDhPay.getBuyerName()) && d.getOrderId().equals(ctDhPay.getOrderId())).collect(Collectors.toList()); - if (ObjectUtil.isNotEmpty(anyMatchList)) { - errCtDhPayList.add(ctDhPay); - } else { - addCtDhPayList.add(ctDhPay); - } - } - if (ObjectUtil.isNotEmpty(errCtDhPayList)) { - errorStrBuf.append("该买家对应的订单编号"); - for (int i = 0; i < errCtDhPayList.size(); i++) { - CtDhPay errPay = errCtDhPayList.get(i); - if (i != 0) { - errorStrBuf.append("、"); - } - errorStrBuf.append(errPay.getOrderId()); - } - errorStrBuf.append("存在重复信息,新增失败"); - } - } - - if (ObjectUtil.isNotEmpty(errorStrBuf)) { - ctDhPayExport.setError(errorStrBuf.toString()); - ctDhPayExportList.add(ctDhPayExport); - } - } - - String returnDataStr = null; - String filePath = propertiesConfig.getUploadImgPath().get(PublicConstant.EXPORT_EXCEL_FILE_TYPE); - String fileName = "敦煌支付导入异常信息表-" + snowflake.nextIdStr(); - if (ObjectUtil.isNotEmpty(ctDhPayExportList)) { - ExcelUtils.exportFile(SystemConfig.IMG_PATH + filePath, fileName, ctDhPayExportList); - returnDataStr = SystemConfig.FILE_VISIT_ADDR + filePath + fileName + ".xlsx"; - //returnDataStr = "http://localhost:8008/file" + filePath + fileName + ".xlsx"; - } - - //拆分订单编号,分多条数据存入 - if (ObjectUtil.isNotEmpty(addCtDhPayList)) { - ctDhPayService.saveBatch(addCtDhPayList); - } - - return Dto.returnResult(returnDataStr); - } - - - /** - * Excel敦煌支付信息模版导出 - * @param response - */ - @ApiOperation("Excel敦煌支付信息模版导出") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log(value = "Excel敦煌支付信息模版导出") - @GetMapping("/exportTemp") - @AnonymousAccess - public void importCard(HttpServletResponse response) { - ExcelUtils.exportTemplate(response, "敦煌支付模版", CtDhPayExportTemple.class); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtExcelController.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtExcelController.java deleted file mode 100644 index eaf3575..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtExcelController.java +++ /dev/null @@ -1,157 +0,0 @@ -package me.zhengjie.modules.group.controller.base; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.metadata.IPage; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import me.zhengjie.annotation.AnonymousAccess; -import me.zhengjie.annotation.FormSubmission; -import me.zhengjie.annotation.Log; -import me.zhengjie.annotation.type.LogActionType; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.CtBuyer; -import me.zhengjie.entity.CtExcel; -import me.zhengjie.entity.CtExcelExportTemple; -import me.zhengjie.error.ErrorCodeEnum; -import me.zhengjie.modules.group.dto.CtExcelAddDTO; -import me.zhengjie.modules.group.dto.CtExcelListDTO; -import me.zhengjie.modules.group.dto.CtExcelUpdateDTO; -import me.zhengjie.modules.group.dto.IdDTO; -import me.zhengjie.service.CtExcelService; -import me.zhengjie.service.vo.CtExcelVO; -import me.zhengjie.utils.PageUtils; -import me.zhengjie.utils.excel.ExcelUtils; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletResponse; -import javax.validation.Valid; -import java.util.ArrayList; -import java.util.List; - - -/** - * - * @Description Excel相关操作 控制类 - * @Date 2022-06-22 - * @Author rch - */ -@Validated -@RequestMapping("/api/ctExcel") -@RestController -@Api(tags = "业务:Excel管理") -public class CtExcelController { - - @Resource - private CtExcelService ctExcelService; - - /** - * 分页查询Excel信息 - */ - @ApiOperation("分页查询Excel信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("分页查询Excel信息") - @PostMapping("/list") - public Dto getExcelList(@Valid @RequestBody CtExcelListDTO dto) { - IPage page = ctExcelService.page(dto.getiPage(), dto.getWrapper()); - List list = new ArrayList<>(); - for (CtExcel record : page.getRecords()) { - CtExcelVO ctExcelVO = new CtExcelVO(); - BeanUtil.copyProperties(record, ctExcelVO); - list.add(ctExcelVO); - } - PageUtils pageUtils = new PageUtils(page.getTotal(),list); - return Dto.returnResult(pageUtils); - } - - /** - * 新增Excel信息 - */ - @ApiOperation("新增Excel信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log(value = "新增导入Excel信息",type = LogActionType.ADD) - @PostMapping("/add") - @FormSubmission - public Dto addExcel(@Valid @RequestBody CtExcelAddDTO dto) { - CtExcel ctExcel = new CtExcel(); - BeanUtil.copyProperties(dto, ctExcel); - return Dto.returnResult(ctExcelService.save(ctExcel)); - } - - /** - * 根据id获取Excel信息 - */ - @ApiOperation("根据id获取Excel信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("根据id获取Excel信息") - @PostMapping("/getById") - public Dto getExcelById(@Valid @RequestBody IdDTO idDTO) { - return Dto.returnResult(ctExcelService.getById(idDTO.getId())); - } - - /** - * 编辑Excel信息 - */ - @ApiOperation("编辑Excel信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 3100, message = "卖家信息不存在!") - }) - @Log(value = "编辑Excel信息",type = LogActionType.UPDATE) - @PostMapping("/edit") - @FormSubmission - public Dto editExcel(@Valid @RequestBody CtExcelUpdateDTO dto) { - // 根据id 判断是否存在 - CtExcel ctExcel = ctExcelService.getById(dto.getId()); - if (ObjectUtil.isEmpty(ctExcel)) { - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_EXCEL_USER); - } - - CtExcel updateCtExcel = new CtExcel(); - BeanUtil.copyProperties(dto, updateCtExcel); - return Dto.returnResult(ctExcelService.updateById(updateCtExcel)); - } - - /** - * 根据id删除Excel信息 - * @author: rch - */ - @ApiOperation("根据id删除Excel信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log(value = "根据id删除Excel信息",type = LogActionType.DELETE) - @PostMapping("/delete") - public Dto delExcel(@Valid @RequestBody IdDTO idDTO) { - return Dto.returnResult(ctExcelService.removeById(idDTO.getId())); - } - - /** - * Excel模板下载 - */ - @ApiOperation("Excel模板下载") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log(value = "Excel模板下载") - @GetMapping("/exportTemp") - public void importExcel(HttpServletResponse response){ - ExcelUtils.exportTemplate(response, "Excel导入模板", CtExcelExportTemple.class); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtExcelInfoController.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtExcelInfoController.java deleted file mode 100644 index 9606354..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtExcelInfoController.java +++ /dev/null @@ -1,120 +0,0 @@ -package me.zhengjie.modules.group.controller.base; - -import cn.hutool.core.bean.BeanUtil; -import com.baomidou.mybatisplus.core.metadata.IPage; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import me.zhengjie.annotation.Log; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.CtBuyer; -import me.zhengjie.entity.CtExcelImportInfo; -import me.zhengjie.modules.group.dto.CtExcelImportInfoListDTO; -import me.zhengjie.modules.group.dto.IdDTO; -import me.zhengjie.service.CtExcelImportInfoService; -import me.zhengjie.service.vo.CtExcelImportInfoVO; -import me.zhengjie.utils.PageUtils; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; -import javax.validation.Valid; -import java.util.ArrayList; -import java.util.List; - - -/** - * - * @Description Excel导入信息相关操作 控制类 - * @Date 2022-06-22 - * @Author rch - */ -@Validated -@RequestMapping("/api/ctExcelInfo") -@RestController -@Api(tags = "业务:Excel导入信息管理") -public class CtExcelInfoController { - - @Resource - private CtExcelImportInfoService ctExcelImportInfoService; - - /** - * 分页查询ExcelInfo信息 - */ - @ApiOperation("分页查询ExcelInfo信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("分页查询ExcelInfo信息") - @PostMapping("/list") - public Dto getExcelInfoList(@Valid @RequestBody CtExcelImportInfoListDTO dto) { - IPage page = ctExcelImportInfoService.page(dto.getiPage(), dto.getWrapper()); - List list = new ArrayList<>(); - for (CtExcelImportInfo record : page.getRecords()) { - CtExcelImportInfoVO ctExcelImportInfoVO = new CtExcelImportInfoVO(); - BeanUtil.copyProperties(record, ctExcelImportInfoVO); - list.add(ctExcelImportInfoVO); - } - PageUtils pageUtils = new PageUtils(page.getTotal(),list); - return Dto.returnResult(pageUtils); - } - - - /** - * 根据id获取ExcelInfo信息 - */ - @ApiOperation("根据id获取ExcelInfo信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("根据id获取ExcelInfo信息") - @PostMapping("/getById") - public Dto getExcelInfoById(@Valid @RequestBody IdDTO idDTO) { - return Dto.returnResult(ctExcelImportInfoService.getById(idDTO.getId())); - } - -// /** -// * 新增Excel信息 -// */ -// @Log(value = "新增导入Excel信息",type = LogActionType.ADD) -// @PostMapping("/add") -// public Dto addExcelInfo(@Valid @RequestBody CtExcelAddDTO dto) { -// CtExcel ctExcel = new CtExcel(); -// BeanUtil.copyProperties(dto, ctExcel); -// return Dto.returnResult(ctExcelService.save(ctExcel)); -// } - - -// /** -// * 编辑Excel信息 -// */ -// @Log(value = "编辑Excel信息",type = LogActionType.UPDATE) -// @PostMapping("/edit") -// public Dto editExcelInfo(@Valid @RequestBody CtExcelUpdateDTO dto) { -// // 根据id 判断是否存在 -// CtExcel ctExcel = ctExcelService.getById(dto.getId()); -// if (ObjectUtil.isEmpty(ctExcel)) { -// Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_EXCEL_USER); -// } -// -// CtExcel updateCtExcel = new CtExcel(); -// BeanUtil.copyProperties(dto, updateCtExcel); -// return Dto.returnResult(ctExcelService.updateById(updateCtExcel)); -// } - -// /** -// * 根据id删除Excel信息 -// * @author: rch -// */ -// @Log(value = "根据id删除Excel信息",type = LogActionType.DELETE) -// @PostMapping("/delete") -// public Dto delExcelInfo(@Valid @RequestBody IdDTO idDTO) { -// return Dto.returnResult(ctExcelService.removeById(idDTO.getId())); -// } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtOrderController.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtOrderController.java deleted file mode 100644 index 26e7b31..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtOrderController.java +++ /dev/null @@ -1,165 +0,0 @@ -package me.zhengjie.modules.group.controller.base; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.json.JSONUtil; -import com.baomidou.mybatisplus.core.metadata.IPage; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import me.zhengjie.annotation.Log; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.*; -import me.zhengjie.modules.group.dto.CtOrderListDTO; -import me.zhengjie.modules.group.dto.IdDTO; -import me.zhengjie.service.CtOrderService; -import me.zhengjie.service.CtResponseOrderAddressService; -import me.zhengjie.service.CtResponseOrderProductService; -import me.zhengjie.service.CtResponseOrderService; -import me.zhengjie.service.vo.CtOrderVO; -import me.zhengjie.service.vo.OrderResponStatusVO; -import me.zhengjie.service.vo.PayOrderVO; -import me.zhengjie.utils.PageUtils; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; -import javax.validation.Valid; -import java.util.ArrayList; -import java.util.List; - - -/** - * - * @Description 群控管理- 敦煌下订单信息 控制类 - * @Date 2022-06-30 - * @Author rch - */ -@Validated -@RequestMapping("/api/dhOrder") -@RestController -@Api(tags = "业务:敦煌下单管理") -public class CtOrderController { - - @Resource - private CtOrderService ctOrderService; - @Resource - private CtResponseOrderService ctResponseOrderService; - @Resource - private CtResponseOrderAddressService ctResponseOrderAddressService; - @Resource - private CtResponseOrderProductService ctResponseOrderProductService; - - /** - * 分页查询敦煌下订单信息 - */ - @ApiOperation("分页查询敦煌下订单信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("分页查询敦煌下订单信息") - @PostMapping("/list") - public Dto getOrderList(@Valid @RequestBody CtOrderListDTO dto) { - IPage page = ctOrderService.page(dto.getiPage(), dto.getWrapper()); - List list = new ArrayList<>(); - for (CtOrder record : page.getRecords()) { - CtOrderVO ctOrderVO = new CtOrderVO(); - BeanUtil.copyProperties(record, ctOrderVO); - - // 下单状态转换 - OrderResponStatusVO orderResponStatusVO = JSONUtil.toBean(record.getOrderResponseStatus(), OrderResponStatusVO.class); - ctOrderVO.setOrderResponseStatus(orderResponStatusVO); - // 支付状态转换 - PayOrderVO payOrderVO = JSONUtil.toBean(record.getPayResponseStatus(), PayOrderVO.class); - ctOrderVO.setPayOrderVO(payOrderVO); - - list.add(ctOrderVO); - } - PageUtils pageUtils = new PageUtils(page.getTotal(),list); - return Dto.returnResult(pageUtils); - } - - /** - * 根据id获取敦煌下订单 - */ - @ApiOperation("根据id获取敦煌下订单") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("根据id获取敦煌下订单") - @PostMapping("/getById") - public Dto getOrderById(@Valid @RequestBody IdDTO idDTO) { - CtOrder ctOrder = ctOrderService.getById(idDTO.getId()); - if (ObjectUtil.isEmpty(ctOrder)) { - return Dto.returnResult(ctOrder); - } - CtOrderVO ctOrderVO = new CtOrderVO(); - BeanUtil.copyProperties(ctOrder, ctOrderVO); - - // 下单状态转换 - OrderResponStatusVO orderResponStatusVO = JSONUtil.toBean(ctOrder.getOrderResponseStatus(), OrderResponStatusVO.class); - ctOrderVO.setOrderResponseStatus(orderResponStatusVO); - // 支付状态转换 - PayOrderVO payOrderVO = JSONUtil.toBean(ctOrder.getPayResponseStatus(), PayOrderVO.class); - ctOrderVO.setPayOrderVO(payOrderVO); - - return Dto.returnResult(ctOrderVO); - } - - - - /** - * 根据id敦煌响应订单信息 - * @param idDTO - * @return - */ - @ApiOperation("根据id敦煌响应订单信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("根据id敦煌响应订单信息") - @PostMapping("/getOrderInfoById") - public Dto getOrderInfoById(@Valid @RequestBody IdDTO idDTO) { - return Dto.returnResult(ctResponseOrderService.getById(idDTO.getId())); - } - - - /** - * 根据id敦煌订单收件信息 - * @param idDTO - * @return - */ - @ApiOperation("根据id敦煌订单收件信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("根据id敦煌订单收件信息") - @PostMapping("/getOrderAddressById") - public Dto getOrderAddressById(@Valid @RequestBody IdDTO idDTO) { - return Dto.returnResult(ctResponseOrderAddressService.getById(idDTO.getId())); - } - - /** - * 根根据id敦煌订单产品信息 - * @param idDTO - * @return - */ - @ApiOperation("根据id敦煌订单产品信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("根据id敦煌订单产品信息") - @PostMapping("/getOrderProductById") - public Dto getOrderProductById(@Valid @RequestBody IdDTO idDTO) { - return Dto.returnResult(ctResponseOrderProductService.getById(idDTO.getId())); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtPlatformController.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtPlatformController.java deleted file mode 100644 index f78a278..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtPlatformController.java +++ /dev/null @@ -1,136 +0,0 @@ -//package me.zhengjie.modules.group.controller; -// -//import cn.hutool.core.bean.BeanUtil; -//import cn.hutool.core.util.ObjectUtil; -//import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -//import com.baomidou.mybatisplus.core.metadata.IPage; -//import me.zhengjie.annotation.Log; -//import me.zhengjie.annotation.type.LogActionType; -//import me.zhengjie.dto.Dto; -//import me.zhengjie.entity.CtBuyer; -//import me.zhengjie.entity.CtCompany; -//import me.zhengjie.entity.CtPlatform; -//import me.zhengjie.error.ErrorCodeEnum; -//import me.zhengjie.modules.group.dto.*; -//import me.zhengjie.service.CtCompanyService; -//import me.zhengjie.service.CtPlatformService; -//import me.zhengjie.service.vo.CtPlatformInfoVO; -//import me.zhengjie.service.vo.CtPlatformVO; -//import me.zhengjie.utils.PageUtils; -//import org.springframework.context.annotation.Bean; -//import org.springframework.validation.annotation.Validated; -//import org.springframework.web.bind.annotation.*; -// -//import javax.annotation.Resource; -//import javax.validation.Valid; -//import java.util.ArrayList; -//import java.util.List; -// -// -///** -// * -// * @Description 群控管理-平台 控制类 -// * @Date 2022-06-23 -// * @Author rch -// */ -//@Validated -//@RequestMapping("/api/ctPlatform") -//@RestController -//public class CtPlatformController { -// -// @Resource -// private CtPlatformService ctPlatformService; -// @Resource -// private CtCompanyService ctCompanyService; -// -// /** -// * 分页查询平台信息 -// */ -// @Log("分页查询平台信息") -// @PostMapping("/list") -// public Dto getPlatformList(@Valid @RequestBody CtPlatformListDTO dto) { -// IPage page = ctPlatformService.page(dto.getiPage(), dto.getWrapper()); -// List list = new ArrayList<>(); -// for (CtPlatform record : page.getRecords()) { -// CtPlatformVO ctPlatformVO = new CtPlatformVO(); -// BeanUtil.copyProperties(record, ctPlatformVO); -// list.add(ctPlatformVO); -// } -// PageUtils pageUtils = new PageUtils(page.getTotal(),list); -// return Dto.returnResult(pageUtils); -// } -// -// /** -// * 新增平台信息 -// */ -// @Log(value = "新增平台信息",type = LogActionType.ADD) -// @PostMapping("/add") -// public Dto addPlatform(@Valid @RequestBody CtPlatformAddDTO dto) { -// CtPlatform ctPlatform = new CtPlatform(); -// BeanUtil.copyProperties(dto, ctPlatform); -// return Dto.returnResult(ctPlatformService.save(ctPlatform)); -// } -// -// /** -// * 根据id平台信息详情详情 -// */ -// @Log("根据id平台信息详情详情") -// @PostMapping("/getById") -// public Dto getPlatformById(@Valid @RequestBody IdDTO idDTO) { -// return Dto.returnResult(ctPlatformService.getById(idDTO.getId())); -// } -// -// /** -// * 编辑平台信息 -// */ -// @Log(value = "编辑平台信息",type = LogActionType.UPDATE) -// @PostMapping("/edit") -// public Dto editPlatform(@Valid @RequestBody CtBuyerUpdateDTO dto) { -// // 根据id 判断是否存在 -// CtPlatform ctPlatform = ctPlatformService.getById(dto.getId()); -// if (ObjectUtil.isEmpty(ctPlatform)) { -// Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_BUYER_USER); -// } -// -// CtPlatform updateCtPlatform = new CtPlatform(); -// BeanUtil.copyProperties(dto, updateCtPlatform); -// return Dto.returnResult(ctPlatformService.updateById(updateCtPlatform)); -// } -// -// /** -// * 根据id删除平台信息 -// * @author: rch -// */ -// @Log(value = "根据id删除平台信息",type = LogActionType.DELETE) -// @PostMapping("/delete") -// public Dto delPlatform(@Valid @RequestBody IdDTO idDTO) { -// // 判断平台下有公司则不允许删除 -// QueryWrapper ctCompanyQueryWrapper = new QueryWrapper<>(); -// ctCompanyQueryWrapper.eq("platform_id", idDTO.getId()); -// Integer count = ctCompanyService.count(ctCompanyQueryWrapper); -// if (ObjectUtil.isNotEmpty(count) && count > 0) { -// Dto.getInstance(ErrorCodeEnum.ERROR_EXITS_COMPANY_INFO); -// } -// return Dto.returnResult(ctPlatformService.removeById(idDTO.getId())); -// } -// -// /** -// * 获取所有平台信息 (平台id 平台名称) -// * 为新增 公司提供公司所属平台服务 -// * @return -// */ -// @Log(value = "获取所有平台信息") -// @GetMapping("/getAll") -// public Dto allPlatform() { -// List ctPlatformList = ctPlatformService.list(); -// List ctPlatformInfoVOList = new ArrayList<>(); -// if (ObjectUtil.isNotEmpty(ctPlatformList)) { -// CtPlatformInfoVO ctPlatformInfoVO = new CtPlatformInfoVO(); -// for (CtPlatform ctPlatform:ctPlatformList) { -// BeanUtil.copyProperties(ctPlatform, ctPlatformInfoVO); -// ctPlatformInfoVOList.add(ctPlatformInfoVO); -// } -// } -// return Dto.returnResult(ctPlatformInfoVOList); -// } -//} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtRebotController.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtRebotController.java deleted file mode 100644 index 412e5b5..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtRebotController.java +++ /dev/null @@ -1,215 +0,0 @@ -package me.zhengjie.modules.group.controller.base; - -import cn.hutool.core.bean.BeanUtil; -import io.swagger.annotations.*; -import me.zhengjie.annotation.AnonymousAccess; -import me.zhengjie.annotation.FormSubmission; -import me.zhengjie.annotation.Log; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.CtRebot; -import me.zhengjie.entity.CtRebotExportTemple; -import me.zhengjie.error.ErrorCodeEnum; -import me.zhengjie.modules.group.dto.*; -import me.zhengjie.service.CtRebotService; -import me.zhengjie.service.vo.CtRebotListVO; -import me.zhengjie.utils.PageUtils; -import me.zhengjie.utils.excel.ExcelUtils; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletResponse; -import javax.validation.Valid; -import java.util.ArrayList; -import java.util.List; - -/** - * 影刀机器人(ct_rebot) 控制层 - * - * @Author zhw - * @Date 2022-07-23 - */ -@Validated -@RequestMapping("/api/ctRebot") -@RestController -@Api(tags = "业务:机器人管理") -public class CtRebotController { - - @Resource - private CtRebotService ctRebotService; - - - /** - * 分页查询 影刀机器人信息 - * @param dto - * @return Dto - */ - @ApiOperation("分页查询影刀机器人信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("分页查询影刀机器人信息") - @PostMapping("/list") - public Dto getRebotList(@Valid @RequestBody CtRebotListDTO dto){ - PageUtils pageUtils = ctRebotService.searchPageList(dto.getiPage(),dto.getWrapper()); - return Dto.returnResult(pageUtils); - } - - /** - * 分页查询未占有状态机器人信息 - */ - @ApiOperation("分页查询未占有状态机器人信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("分页查询未占有状态机器人信息") - @PostMapping("freeList") - public Dto getFreeRebotList(@Valid @RequestBody CtRebotListDTO dto){ - PageUtils pageUtils = ctRebotService.searchPageList(dto.getiPage(),dto.getWrapper()); - List allRebotList = pageUtils.getList(); - List freeRebotList = new ArrayList<>(); - long freeTotal = 0L; - for(CtRebotListVO record : allRebotList){ - if(record.getStatus()==0){ - freeTotal++; - freeRebotList.add(record); - } - } - PageUtils freePageUtils = new PageUtils<>(freeTotal, freeRebotList); - return Dto.returnResult(freePageUtils); - } - - /** - * 新增影刀机器人信息 - * @param dto - * @return Dto - */ - @ApiOperation("新增影刀机器人信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("新增影刀机器人信息") - @PostMapping("/add") - @FormSubmission - public Dto addCtRebot(@Valid @RequestBody CtRebotAddDTO dto){ - CtRebot ctRebot = new CtRebot(); - BeanUtil.copyProperties(dto,ctRebot); - return Dto.returnResult(ctRebotService.save(ctRebot)); - } - - /** - * 根据ID删除影刀机器人信息 - * @param idDTO - * @return Dto - */ - @ApiOperation("根据ID删除影刀机器人信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("根据ID删除影刀机器人信息") - @PostMapping("/delete") - public Dto delCtRebotById(@Valid @RequestBody IdDTO idDTO){ - return Dto.returnResult(ctRebotService.removeById(idDTO.getId())); - } - - /** - * 根据ID修改影刀机器人信息 - * @param dto - * @return Dto - */ - @ApiOperation("据ID修改影刀机器人信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("根据ID修改影刀机器人信息") - @PostMapping("/edit") - @FormSubmission - public Dto editCtRebotById(@Valid @RequestBody CtRebotUpdateDTO dto){ - CtRebot ctRebotIsExist = ctRebotService.getById(dto.getId()); - if(ctRebotIsExist == null){ - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_REBOT); - } - CtRebot updateCtRebot = new CtRebot(); - BeanUtil.copyProperties(dto,updateCtRebot); - return Dto.returnResult(ctRebotService.updateById(updateCtRebot)); - } - - /** - * 根据Id查找影刀机器人信息 - * @param iddto - * @return Dto - */ - @ApiOperation("根据Id查找影刀机器人信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("根据ID查找影刀机器人信息") - @PostMapping("getById") - public Dto getById(@Valid @RequestBody IdDTO iddto){ - return Dto.returnResult(ctRebotService.getById(iddto.getId())); - } - - - /** - * TODO 这里只是测试方便使用 - * @param dto - * @return Dto - */ - @ApiOperation("重置机器人状态") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("重置机器人状态") - @PostMapping("updateStatus") - public Dto updateStatus(@Valid @RequestBody CtRebotUpdateStatusDTO dto){ - CtRebot ctRebot = new CtRebot(); - ctRebot.setId(dto.getId()); - ctRebot.setStatus(0); - return Dto.returnResult(ctRebotService.updateById(ctRebot)); - } - - /** - * EXCEL导入机器人信息 - * @param file - * @param response - * @return Dto - * @throws Exception - */ - @ApiOperation("EXCEL导入机器人信息") - @ApiImplicitParams({ - @ApiImplicitParam(value = "上传文件", name = "file", dataType = "__file", required = true) - }) - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("EXCEL导入机器人信息") - @PostMapping("/import") - public Dto importRebot(@RequestPart("file") MultipartFile file, HttpServletResponse response)throws Exception{ - return ctRebotService.importRebot(file, response); - } - - /** - * EXCEL导出机器人导入模板 - */ - @ApiOperation("EXCEL导出机器人导入模板") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("EXCEL导出机器人导入模板") - @GetMapping("/exportTemp") - @AnonymousAccess - public void exportRebot(HttpServletResponse response){ - ExcelUtils.exportTemplate(response, "机器人导入模板", CtRebotExportTemple.class); - } - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtVpnController.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtVpnController.java deleted file mode 100644 index 9d9eab7..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/CtVpnController.java +++ /dev/null @@ -1,261 +0,0 @@ -package me.zhengjie.modules.group.controller.base; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.lang.Snowflake; -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.metadata.IPage; -import io.swagger.annotations.*; -import me.zhengjie.annotation.AnonymousAccess; -import me.zhengjie.annotation.FormSubmission; -import me.zhengjie.annotation.Log; -import me.zhengjie.annotation.type.LogActionType; -import me.zhengjie.config.PropertiesConfig; -import me.zhengjie.config.SystemConfig; -import me.zhengjie.constant.PublicConstant; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.CtVpn; -import me.zhengjie.entity.CtVpnExport; -import me.zhengjie.entity.CtVpnExportTemple; -import me.zhengjie.entity.CtVpnImport; -import me.zhengjie.enums.VpnStatusEnum; -import me.zhengjie.error.ErrorCodeEnum; -import me.zhengjie.modules.group.dto.CtVpnAddDTO; -import me.zhengjie.modules.group.dto.CtVpnListDTO; -import me.zhengjie.modules.group.dto.CtVpnUpdateDTO; -import me.zhengjie.modules.group.dto.IdDTO; -import me.zhengjie.service.CtVpnService; -import me.zhengjie.service.vo.CtVpnInfoVO; -import me.zhengjie.service.vo.CtVpnVO; -import me.zhengjie.utils.PageUtils; -import me.zhengjie.utils.excel.ExcelUtils; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletResponse; -import javax.validation.Valid; -import java.util.ArrayList; -import java.util.List; - -/** - * @Description - * @Date 2022/7/7 - * @Author zhw - */ -@Validated -@RequestMapping("/api/ctVpn") -@RestController -@Api(tags = "业务:Vpn管理") -public class CtVpnController { - - @Resource - private CtVpnService ctVpnService; - @Resource - private PropertiesConfig propertiesConfig; - @Resource - private Snowflake snowflake; - - /** - * 分页查询VPN信息 - */ - @ApiOperation("分页查询VPN信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("分页查询VPN信息") - @PostMapping("/list") - public Dto getVpnList(@Valid @RequestBody CtVpnListDTO dto){ - IPage page = ctVpnService.page(dto.getiPage(),dto.getWrapper()); - List list = new ArrayList<>(); - for(CtVpn record : page.getRecords()){ - CtVpnVO ctVpnVO = new CtVpnVO(); - BeanUtil.copyProperties(record, ctVpnVO); - list.add(ctVpnVO); - } - PageUtils pageUtils = new PageUtils(page.getTotal(),list); - return Dto.returnResult(pageUtils); - } - - /** - * 新增VPN信息 - */ - @ApiOperation("新增VPN信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log(value = "新增VPN信息",type = LogActionType.ADD) - @PostMapping("/add") - @FormSubmission - public Dto addVpn(@Valid @RequestBody CtVpnAddDTO dto){ - CtVpn ctVpn = new CtVpn(); - BeanUtil.copyProperties(dto,ctVpn); - ctVpn.setStatus(VpnStatusEnum.AVAILABLE.value()); - //新增规则 - return Dto.returnResult(ctVpnService.save(ctVpn)); - } - - /** - * 根据ID查VPN详情 - */ - @ApiOperation("根据ID查VPN详情") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("根据ID查询VPN详情") - @PostMapping("/getById") - public Dto getVpnById(@Valid @RequestBody IdDTO idDTO){ - return Dto.returnResult(ctVpnService.getById(idDTO.getId())); - } - - /** - * 编辑VPN信息 - */ - @ApiOperation("编辑VPN信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 2000, message = "VPN信息不存在,或者已删除!") - }) - @Log(value = "编辑VPN信息",type = LogActionType.UPDATE) - @PostMapping("/edit") - @FormSubmission - public Dto editVpn(@Valid @RequestBody CtVpnUpdateDTO dto){ - //编辑规则 - //根据ID判断是否存在 - CtVpn ctVpn = ctVpnService.getById(dto.getId()); - if(ObjectUtil.isEmpty(ctVpn)){ - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_VPN); - } - - CtVpn updataCtVpn = new CtVpn(); - BeanUtil.copyProperties(dto,updataCtVpn); - return Dto.returnResult(ctVpnService.updateById(updataCtVpn)); - } - - /** - * 根据ID删除VPN信息 - */ - @ApiOperation("根据ID删除VPN信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 2000, message = "VPN信息不存在,或者已删除!") - }) - @Log(value = "根据ID删除VPN信息",type = LogActionType.DELETE) - @PostMapping("/delete") - public Dto delVpn(@Valid @RequestBody IdDTO idDTO){ - //判断删除规则 - //根据ID判断是否存在 - CtVpn ctVpn = ctVpnService.getById(idDTO.getId()); - if(ObjectUtil.isEmpty(ctVpn)){ - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_VPN); - } - return Dto.returnResult(ctVpnService.removeById(idDTO.getId())); - } - - /** - * 获取所有VPN信息 (VPNid VPN名称) - */ - @ApiOperation("获取所有VPN信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log(value = "获取所有VPN信息") - @GetMapping("/getAll") - public Dto allVpn() { - List ctVpnList = ctVpnService.list(); - List ctVpnInfoVOList = new ArrayList<>(); - if (ObjectUtil.isNotEmpty(ctVpnList)) { - for (CtVpn ctvpn:ctVpnList) { - CtVpnInfoVO ctVpnInfoVO = new CtVpnInfoVO(); - BeanUtil.copyProperties(ctvpn, ctVpnInfoVO); - ctVpnInfoVOList.add(ctVpnInfoVO); - } - } - return Dto.returnResult(ctVpnInfoVOList); - } - - /** - * EXCEL导入VPN信息 - */ - @ApiOperation("EXCEL导入VPN信息") - @ApiImplicitParams({ - @ApiImplicitParam(value = "上传文件", name = "file", dataType = "__file", required = true) - }) - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log(value = "EXCEL导入VPN信息",type = LogActionType.ADD) - @PostMapping("import") - public Dto importVpn(@RequestPart("file") MultipartFile file, HttpServletResponse response)throws Exception{ - - //TODO 对Excel 信息进行检测 如果不符合要求的 最终要导出错误Excel提示 - List ctVpnImportList = ExcelUtils.readMultipartFile(file,CtVpnImport.class); - if(ObjectUtil.isEmpty(ctVpnImportList)){ - return Dto.returnResult(true); - } - - List addCtVpnList = new ArrayList<>(); - List ipValueList = ctVpnService.getIpList(); - List ctVpnExportList = new ArrayList<>(); - for(CtVpnImport ctVpnImport : ctVpnImportList) { - CtVpnExport ctVpnExport = new CtVpnExport(); - BeanUtil.copyProperties(ctVpnImport, ctVpnExport); - - StringBuffer errorStrBuf = new StringBuffer(); - String rowTips = ctVpnImport.getRowTips(); - if (ObjectUtil.isNotEmpty((rowTips))) { - errorStrBuf.append(rowTips); - errorStrBuf.append(";"); - } - if (ipValueList.contains(ctVpnImport.getIpAddress())) { - errorStrBuf.append("平台已经存在该IP地址对应的VPN信息"); - } - if (ObjectUtil.isNotEmpty(errorStrBuf)) { - ctVpnExport.setError(errorStrBuf.toString()); - ctVpnExportList.add(ctVpnExport); - } else { - CtVpn ctVpn = new CtVpn(); - ctVpn.setStatus(VpnStatusEnum.AVAILABLE.value()); - BeanUtil.copyProperties(ctVpnImport, ctVpn); - addCtVpnList.add(ctVpn); - } - } - - String returnDataStr = null; - String filePath = propertiesConfig.getUploadImgPath().get(PublicConstant.EXPORT_EXCEL_FILE_TYPE); - String fileName = "VPN导入异常信息表-" + snowflake.nextIdStr(); - if(ObjectUtil.isNotEmpty(ctVpnExportList)){ - ExcelUtils.exportFile(SystemConfig.IMG_PATH + filePath, fileName, ctVpnExportList); - returnDataStr = SystemConfig.FILE_VISIT_ADDR + filePath + fileName + ".xlsx"; -// returnDataStr = "http://localhost:8008/file" + filePath + fileName + ".xlsx"; - } - - if(ObjectUtil.isNotEmpty(addCtVpnList)){ - ctVpnService.saveBatch(addCtVpnList); - } - - return Dto.returnResult(returnDataStr); - } - - /** - * Excel导出VPN导入模板 - */ - @ApiOperation("Excel导出VPN导入模板") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log(value = "Excel导出VPN导入模板") - @GetMapping("/exportTemp") - @AnonymousAccess - public void exportVpn(HttpServletResponse response) { - ExcelUtils.exportTemplate(response, "VPN导入模板", CtVpnExportTemple.class, true); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/DhAddCarCatchController.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/DhAddCarCatchController.java deleted file mode 100644 index 224eb9b..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/DhAddCarCatchController.java +++ /dev/null @@ -1,409 +0,0 @@ -package me.zhengjie.modules.group.controller.base; - -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import lombok.RequiredArgsConstructor; -import me.zhengjie.annotation.Log; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.DhAddCarOrder; -import me.zhengjie.modules.group.dto.IdDTO; -import me.zhengjie.service.DhAddCarOrderService; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; -import javax.validation.Valid; - -/** - * - * @Description 群控管理-敦煌加购-抓单 控制类 - * @Date 2022-06-22 - * @Author rch - */ -@Validated -@RequestMapping("/api/dhAddCarCatch") -@RestController -@RequiredArgsConstructor -@Api(tags = "业务:敦煌加购-抓单管理") -public class DhAddCarCatchController { - - @Resource - private DhAddCarOrderService dhAddCarOrderService; - -// /** -// * 分页查询敦煌加购-抓单 -// */ -// @ApiOperation("分页查询敦煌加购-抓单") -// @ApiResponses(value = { -// @ApiResponse(code = 200, message = "响应成功"), -// @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") -// }) -// @Log("分页查询敦煌加购-抓单") -// @PostMapping("/list") -// public Dto getDhAddCardList(@Valid @RequestBody DhAddCarListDTO dto) { -// PageUtils pageUtilsResult = dhAddCarService.searchPageList(dto.getiPage(), dto.getWrapper()); -// return Dto.returnResult(pageUtilsResult); -// } - -// /** -// * 新增敦煌加购-抓单 -// */ -// @ApiOperation("新增敦煌加购-抓单") -// @ApiResponses(value = { -// @ApiResponse(code = 200, message = "响应成功"), -// @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") -// }) -// @Log(value = "新增敦煌加购-抓单",type = LogActionType.ADD) -// @PostMapping("/add") -// @FormSubmission -// public Dto addDhCar(@Valid @RequestBody DhAddCarAddDTO dto) { -// -// Integer paramsType = dto.getParamsType(); -// List dhCarGoodList = new ArrayList<>(); -// if (ParamsTypeEnum.KEY_WORD.eqValue(paramsType)) { -// List DhCarGoodKeyList = dto.getCarGoodKeys(); -// if (ObjectUtil.isEmpty(DhCarGoodKeyList)) { -// return Dto.getInstance(ErrorCodeEnum.ERROR_ADD_CAR_KEY_NULL); -// } else { -// for (DhCarGoodKeyAddDTO dhCarGoodKeyDTO:DhCarGoodKeyList) { -// DhCarGoods dhCarGoods = new DhCarGoods(); -// BeanUtil.copyProperties(dhCarGoodKeyDTO, dhCarGoods); -// dhCarGoodList.add(dhCarGoods); -// } -// } -// } else if (ParamsTypeEnum.LINK.eqValue(paramsType)) { -// List DhCarGoodLinkList = dto.getCarGoodLinks(); -// if (ObjectUtil.isEmpty(DhCarGoodLinkList)) { -// return Dto.getInstance(ErrorCodeEnum.ERROR_ADD_CAR_LINK_NULL); -// } else { -// for (DhCarGoodLinkAddDTO dhCarGoodLinkDTO:DhCarGoodLinkList) { -// DhCarGoods dhCarGoods = new DhCarGoods(); -// BeanUtil.copyProperties(dhCarGoodLinkDTO, dhCarGoods); -// dhCarGoodList.add(dhCarGoods); -// } -// } -// } else { -// return Dto.getInstance(ErrorCodeEnum.ERROR_ADD_CAR_GOODS_NULL); -// } -// -// // service 层 分别存储两个表信息 -// Boolean resultBoolean = dhCarGoodsService.saveBatch(dhCarGoodList); -// if (resultBoolean) { -// List goodsIdList = dhCarGoodList.stream().map(DhCarGoods::getId).collect(Collectors.toList()); -// -// DhAddCar dhAddCar = new DhAddCar(); -// BeanUtil.copyProperties(dto, dhAddCar); -// dhAddCar.setCarGoodIds(Joiner.on(",").join(goodsIdList)); -// resultBoolean = dhAddCarService.save(dhAddCar); -// } -// -// return Dto.returnResult(resultBoolean); -// } - - /** - * 根据id获取刷单信息 - */ - @ApiOperation("根据id获取刷单信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("根据id获取刷单信息") - @PostMapping("/getById") - public Dto getById(@Valid @RequestBody IdDTO idDTO) { - QueryWrapper queryWrapper = new QueryWrapper<>(); - queryWrapper.eq("add_car_id", idDTO.getId()); - return Dto.returnResult(dhAddCarOrderService.getOne(queryWrapper)); - } - -// /** -// * 根据id获取修改回显信息 -// */ -// @ApiOperation("根据id获取修改回显信息") -// @ApiResponses(value = { -// @ApiResponse(code = 200, message = "响应成功"), -// @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") -// }) -// @Log("根据id获取修改回显信息") -// @PostMapping("/getEditDetailById") -// public Dto getEditDetailById(@Valid @RequestBody IdDTO idDTO) { -// return Dto.returnResult(dhAddCarService.getDetailById(idDTO.getId())); -// } -// -// /** -// * 根据id删除刷单信息 -// * @author: rch -// */ -// @ApiOperation("根据id删除敦煌加购-抓单") -// @ApiResponses(value = { -// @ApiResponse(code = 200, message = "响应成功"), -// @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), -// @ApiResponse(code = 4404, message = "敦煌加购-抓单信息不存在,或者已删除或异常!"), -// @ApiResponse(code = 3901, message = "只有待执行的刷单信息才允许删除!") -// }) -// @Log(value = "根据id删除刷单信息",type = LogActionType.DELETE) -// @PostMapping("/delete") -// public Dto delClickFarming(@Valid @RequestBody IdDTO idDTO) { -// -// // 先查询 -// DhAddCar dhAddCar = dhAddCarService.getById(idDTO.getId()); -// if (ObjectUtil.isEmpty(dhAddCar)) { -// return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_ADD_CAR_INFO); -// } -// -// if (!DhAddCarStatusEnum.TOBE_EXECUTION.eqValue(dhAddCar.getStatus())) { -// return Dto.getInstance(ErrorCodeEnum.ERROR_DEL_ADD_CAR_INFO); -// } -// -// Boolean resultBoolean = false; -// if (dhAddCarService.removeById(idDTO.getId())) { -// String goodIds = dhAddCar.getCarGoodIds(); -// List goodIdList = new ArrayList<>(); -// if (goodIds.contains(",")){ -// goodIdList = Arrays.asList(goodIds.split(",")).stream().map(s -> Long.parseLong(s.trim())).collect(Collectors.toList()); -// }else { -// goodIdList.add(Long.valueOf(goodIds)); -// } -// resultBoolean = dhCarGoodsService.removeByIds(goodIdList); -// } -// -// return Dto.returnResult(resultBoolean); -// } -// -// /** -// * 编辑刷单信息 -// */ -// @ApiOperation("编辑敦煌加购-抓单") -// @ApiResponses(value = { -// @ApiResponse(code = 200, message = "响应成功"), -// @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), -// @ApiResponse(code = 4404, message ="敦煌加购-抓单信息不存在!") -// }) -// @Log(value = "编辑敦煌加购-抓单",type = LogActionType.UPDATE) -// @PostMapping("/edit") -// @FormSubmission -// public Dto editDhAddCar(@Valid @RequestBody DhAddCarEditDTO dto) { -// -// DhAddCar dhAddCar = dhAddCarService.getById(dto.getId()); -// if (ObjectUtil.isEmpty(dhAddCar)) { -// return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_ADD_CAR_INFO); -// } -// -// if (!DhAddCarStatusEnum.TOBE_EXECUTION.eqValue(dhAddCar.getStatus())) { -// return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_EDIT_ADD_CAR_INFO); -// } -// -// // 关键词 -// BeanUtil.copyProperties(dto, dhAddCar); -// List dhCarGoodList = new ArrayList<>(); -// Boolean result = false; -// if (ParamsTypeEnum.KEY_WORD.value().equals(dto.getParamsType())) { -// List carGoodKeys = dto.getCarGoodKeys(); -// for (DhCarGoodKeyEditDTO dhCarGoodKeyEditDTO:carGoodKeys) { -// DhCarGoods dhCarGoods = new DhCarGoods(); -// BeanUtil.copyProperties(dhCarGoodKeyEditDTO, dhCarGoods); -// dhCarGoodList.add(dhCarGoods); -// } -// } -// // 链接 -// if (ParamsTypeEnum.LINK.value().equals(dto.getParamsType())) { -// List carGoodLinks = dto.getCarGoodLinks(); -// for (DhCarGoodLinkEditDTO dhCarGoodLinkEditDTO:carGoodLinks) { -// DhCarGoods dhCarGoods = new DhCarGoods(); -// BeanUtil.copyProperties(dhCarGoodLinkEditDTO, dhCarGoods); -// dhCarGoodList.add(dhCarGoods); -// } -// } -// if (ObjectUtil.isNotEmpty(dhCarGoodList)) { -// if (dhCarGoodsService.saveOrUpdateBatch(dhCarGoodList)) { -// String dhCarGoodIdStr = Joiner.on(",").join(dhCarGoodList.stream().map(DhCarGoods::getId).collect(Collectors.toList())); -// dhAddCar.setCarGoodIds(dhCarGoodIdStr); -// result = dhAddCarService.updateById(dhAddCar); -// } -// } -// -// return Dto.returnResult(result); -// } -// -// -// /** -// * 下单成功(加购-抓单成功状态 手动转下单成功) -// * @param idDTO -// * @return -// */ -// @ApiOperation("下单成功") -// @ApiResponses(value = { -// @ApiResponse(code = 200, message = "响应成功"), -// @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), -// @ApiResponse(code = 4404, message ="敦煌加购-抓单信息不存在!") -// }) -// @Log(value = "下单成功",type = LogActionType.UPDATE) -// @PostMapping("/orderSuccess") -// @FormSubmission -// public Dto orderSuccess(@Valid @RequestBody IdDTO idDTO) { -// DhAddCar dhAddCar = dhAddCarService.getByIdLock(idDTO.getId()); -// if (ObjectUtil.isEmpty(dhAddCar)) { -// return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_ADD_CAR_INFO); -// } -// -// DhAddCar updateDhAddCar = new DhAddCar(); -// updateDhAddCar.setId(dhAddCar.getId()); -// updateDhAddCar.setStatus(DhAddCarStatusEnum.ORDER_SUCCESS.value()); -// return Dto.returnResult(dhAddCarService.updateById(updateDhAddCar)); -// } -// -// /** -// * 支付成功(下单成功状态 手动转支付成功) -// * @param idDTO -// * @return -// */ -// @ApiOperation("支付成功") -// @ApiResponses(value = { -// @ApiResponse(code = 200, message = "响应成功"), -// @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), -// @ApiResponse(code = 4404, message ="敦煌加购-抓单信息不存在!") -// }) -// @Log(value = "支付成功",type = LogActionType.UPDATE) -// @PostMapping("/toBeCatch") -// @FormSubmission -// public Dto toBeCatch(@Valid @RequestBody IdDTO idDTO) { -// DhAddCar dhAddCar = dhAddCarService.getByIdLock(idDTO.getId()); -// if (ObjectUtil.isEmpty(dhAddCar)) { -// return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_ADD_CAR_INFO); -// } -// -// DhAddCar updateDhAddCar = new DhAddCar(); -// updateDhAddCar.setId(dhAddCar.getId()); -// updateDhAddCar.setStatus(DhAddCarStatusEnum.TO_BE_CATCH_ORDER.value()); -// return Dto.returnResult(dhAddCarService.updateById(updateDhAddCar)); -// } - -// -// /** -// * -// * @param file -// * @param response -// * @return -// * @throws Exception -// */ -// @ApiOperation("Excel刷单信息导入") -// @ApiImplicitParams({ -// @ApiImplicitParam(value = "上传文件", name = "file", dataType = "__file", required = true) -// }) -// @ApiResponses(value = { -// @ApiResponse(code = 200, message = "响应成功"), -// @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") -// }) -// @Log(value = "Excel刷单信息导入",type = LogActionType.ADD) -// @PostMapping("/import") -// public Dto importClickFarming(@RequestPart("file")MultipartFile file, HttpServletResponse response) throws Exception { -// -// // TODO 对Excel 信息进行检测 如果不符合要求的 最终要导出错误Excel提示 -// List ctClickFarmingImportList = ExcelUtils.readMultipartFile(file, CtClickFarmingImport.class); -// if (ObjectUtil.isEmpty(ctClickFarmingImportList)) { -// return Dto.returnResult(true); -// } -// -// List addCtClickFarmingList = new ArrayList<>(); -// List ctClickFarmingExportList = new ArrayList<>(); -// -// // 买家id -// List buyerAccountList = ctClickFarmingImportList.stream().map(c->c.getAccount()).collect(Collectors.toList()); -// Map buyerMap = ctBuyerService.getBuyerList(buyerAccountList); -// -// for (CtClickFarmingImport ctClickFarmingImport:ctClickFarmingImportList) { -// CtClickFarmingExport ctClickFarmingExport = new CtClickFarmingExport(); -// BeanUtil.copyProperties(ctClickFarmingImport, ctClickFarmingExport); -// -// StringBuffer errorStrBuf = new StringBuffer(); -// String rowTips = ctClickFarmingImport.getRowTips(); -// if (ObjectUtil.isNotEmpty(rowTips)) { -// errorStrBuf.append(rowTips); -// errorStrBuf.append(";"); -// } -// -// if (ObjectUtil.isEmpty(ctClickFarmingImport.getSpecification())) { -// errorStrBuf.append("规格-必填!"); -// errorStrBuf.append(";"); -// } -// if (ObjectUtil.isEmpty(ctClickFarmingImport.getColor())) { -// errorStrBuf.append("颜色-必填!"); -// errorStrBuf.append(";"); -// } -// if (ObjectUtil.isEmpty(ctClickFarmingImport.getExchange())) { -// errorStrBuf.append("优惠劵-必填!"); -// errorStrBuf.append(";"); -// } -// -// // 判断类型 -// if (ParamsTypeEnum.KEY_WORD.eqValue(ctClickFarmingImport.getParamsType())) { -// if (ObjectUtil.isEmpty(ctClickFarmingImport.getKeyWord())) { -// errorStrBuf.append("关键词-必填!"); -// errorStrBuf.append(";"); -// } -// if (ObjectUtil.isEmpty(ctClickFarmingImport.getTitle())) { -// errorStrBuf.append("标题-必填!"); -// errorStrBuf.append(";"); -// } -// if (ObjectUtil.isEmpty(ctClickFarmingImport.getItem())) { -// errorStrBuf.append("item-必填!"); -// errorStrBuf.append(";"); -// } -// } else { -// if (ObjectUtil.isEmpty(ctClickFarmingImport.getLink())) { -// errorStrBuf.append("链接-必填!"); -// errorStrBuf.append(";"); -// } -// } -// -// if (ObjectUtil.isEmpty(buyerMap) || !buyerMap.containsKey(ctClickFarmingImport.getAccount())) { -// errorStrBuf.append("买家信息不存在!"); -// errorStrBuf.append(";"); -// } else { -// Long buyerId = buyerMap.entrySet().stream().collect(Collectors.toMap(entity -> entity.getKey(), entity -> entity.getValue())).get(ctClickFarmingImport.getAccount()).getId(); -// ctClickFarmingImport.setBuyerId(buyerId); -// } -// if (ObjectUtil.isNotEmpty(errorStrBuf)) { -// ctClickFarmingExport.setError(errorStrBuf.toString()); -// ctClickFarmingExportList.add(ctClickFarmingExport); -// } else { -// CtClickFarming ctClickFarming = new CtClickFarming(); -// BeanUtils.copyProperties(ctClickFarmingImport, ctClickFarming); -// addCtClickFarmingList.add(ctClickFarming); -// } -// } -// -// String returnDataStr = null; -// String filePath = propertiesConfig.getUploadImgPath().get(PublicConstant.EXPORT_EXCEL_FILE_TYPE); -// String fileName = "刷单信息导入异常信息表-" + snowflake.nextIdStr(); -// if (ObjectUtil.isNotEmpty(ctClickFarmingExportList)) { -// ExcelUtils.exportFile(SystemConfig.IMG_PATH + filePath, fileName, ctClickFarmingExportList); -// returnDataStr = SystemConfig.FILE_VISIT_ADDR + filePath + fileName + ".xlsx"; -//// returnDataStr = "http://localhost:8008/file" + filePath + fileName + ".xlsx"; -// } -// -// if (ObjectUtil.isNotEmpty(addCtClickFarmingList)) { -// ctClickFarmingService.saveBatch(addCtClickFarmingList); -// } -// -// return Dto.returnResult(returnDataStr); -// } -// -// @ApiOperation("Excel刷单信息模版导出") -// @ApiResponses(value = { -// @ApiResponse(code = 200, message = "响应成功"), -// @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") -// }) -// @Log(value = "Excel刷单信息模版导出") -// @GetMapping("/exportTemp") -// @AnonymousAccess -// public void importClickFarming(HttpServletResponse response) { -// ExcelUtils.exportTemplate(response, "刷单信息模版", CtClickFarmingExportTemp.class); -// } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/DhAddCarController.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/DhAddCarController.java deleted file mode 100644 index dfc9a72..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/DhAddCarController.java +++ /dev/null @@ -1,466 +0,0 @@ -package me.zhengjie.modules.group.controller.base; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.util.ObjectUtil; -import com.google.common.base.Joiner; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import lombok.RequiredArgsConstructor; -import me.zhengjie.annotation.FormSubmission; -import me.zhengjie.annotation.Log; -import me.zhengjie.annotation.type.LogActionType; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.DhAddCar; -import me.zhengjie.entity.DhCarGoods; -import me.zhengjie.enums.DhAddCarStatusEnum; -import me.zhengjie.enums.ParamsTypeEnum; -import me.zhengjie.error.ErrorCodeEnum; -import me.zhengjie.modules.group.dto.DhCarWellReceivedDTO; -import me.zhengjie.modules.group.dto.IdDTO; -import me.zhengjie.modules.group.dto.DhCarGoodWellReceivedDTO; -import me.zhengjie.modules.group.dto.dhaddcar.DhAddCarAddDTO; -import me.zhengjie.modules.group.dto.dhaddcar.DhAddCarEditDTO; -import me.zhengjie.modules.group.dto.dhaddcar.DhAddCarListDTO; -import me.zhengjie.modules.group.dto.dhcargood.*; -import me.zhengjie.service.DhAddCarService; -import me.zhengjie.service.DhCarGoodsService; -import me.zhengjie.service.vo.dhaddcar.DhAddCarListVO; -import me.zhengjie.service.vo.dhaddcar.DhAddCarVO; -import me.zhengjie.utils.PageUtils; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; -import javax.validation.Valid; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -/** - * - * @Description 群控管理-敦煌加购 控制类 - * @Date 2022-06-22 - * @Author rch - */ -@Validated -@RequestMapping("/api/dhAddCar") -@RestController -@RequiredArgsConstructor -@Api(tags = "业务:敦煌加购管理") -public class DhAddCarController { - - @Resource - private DhCarGoodsService dhCarGoodsService; - @Resource - private DhAddCarService dhAddCarService; - - /** - * 分页查询敦煌加购 - */ - @ApiOperation("分页查询敦煌加购") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("分页查询敦煌加购") - @PostMapping("/list") - public Dto getDhAddCardList(@Valid @RequestBody DhAddCarListDTO dto) { - PageUtils pageUtilsResult = dhAddCarService.searchPageList(dto.getiPage(), dto.getWrapper()); - return Dto.returnResult(pageUtilsResult); - } - - /** - * 新增敦煌加购 - */ - @ApiOperation("新增敦煌加购") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log(value = "新增敦煌加购",type = LogActionType.ADD) - @PostMapping("/add") - @FormSubmission - public Dto addDhCar(@Valid @RequestBody DhAddCarAddDTO dto) { - - Integer paramsType = dto.getParamsType(); - List dhCarGoodList = new ArrayList<>(); - if (ParamsTypeEnum.KEY_WORD.eqValue(paramsType)) { - List DhCarGoodKeyList = dto.getCarGoodKeys(); - if (ObjectUtil.isEmpty(DhCarGoodKeyList)) { - return Dto.getInstance(ErrorCodeEnum.ERROR_ADD_CAR_KEY_NULL); - } else { - for (DhCarGoodKeyAddDTO dhCarGoodKeyDTO:DhCarGoodKeyList) { - DhCarGoods dhCarGoods = new DhCarGoods(); - BeanUtil.copyProperties(dhCarGoodKeyDTO, dhCarGoods); - dhCarGoodList.add(dhCarGoods); - } - } - } else if (ParamsTypeEnum.LINK.eqValue(paramsType)) { - List DhCarGoodLinkList = dto.getCarGoodLinks(); - if (ObjectUtil.isEmpty(DhCarGoodLinkList)) { - return Dto.getInstance(ErrorCodeEnum.ERROR_ADD_CAR_LINK_NULL); - } else { - for (DhCarGoodLinkAddDTO dhCarGoodLinkDTO:DhCarGoodLinkList) { - DhCarGoods dhCarGoods = new DhCarGoods(); - BeanUtil.copyProperties(dhCarGoodLinkDTO, dhCarGoods); - dhCarGoodList.add(dhCarGoods); - } - } - } else { - return Dto.getInstance(ErrorCodeEnum.ERROR_ADD_CAR_GOODS_NULL); - } - - // service 层 分别存储两个表信息 - Boolean resultBoolean = dhCarGoodsService.saveBatch(dhCarGoodList); - if (resultBoolean) { - List goodsIdList = dhCarGoodList.stream().map(DhCarGoods::getId).collect(Collectors.toList()); - - DhAddCar dhAddCar = new DhAddCar(); - BeanUtil.copyProperties(dto, dhAddCar); - dhAddCar.setCarGoodIds(Joiner.on(",").join(goodsIdList)); - resultBoolean = dhAddCarService.save(dhAddCar); - } - - return Dto.returnResult(resultBoolean); - } - -// /** -// * 根据id获取刷单信息 -// */ -// @ApiOperation("根据id获取刷单信息") -// @ApiResponses(value = { -// @ApiResponse(code = 200, message = "响应成功"), -// @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") -// }) -// @Log("根据id获取刷单信息") -// @PostMapping("/getById") -// public Dto getById(@Valid @RequestBody IdDTO idDTO) { -// return Dto.returnResult(ctClickFarmingService.getDetailById(idDTO.getId())); -// } -// - /** - * 根据id获取修改回显信息 - */ - @ApiOperation("根据id获取修改回显信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("根据id获取修改回显信息") - @PostMapping("/getEditDetailById") - public Dto getEditDetailById(@Valid @RequestBody IdDTO idDTO) { - return Dto.returnResult(dhAddCarService.getDetailById(idDTO.getId())); - } - - /** - * 根据id删除刷单信息 - * @author: rch - */ - @ApiOperation("根据id删除敦煌加购") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 4404, message = "敦煌加购信息不存在,或者已删除或异常!"), - @ApiResponse(code = 3901, message = "只有待执行的刷单信息才允许删除!") - }) - @Log(value = "根据id删除刷单信息",type = LogActionType.DELETE) - @PostMapping("/delete") - public Dto delClickFarming(@Valid @RequestBody IdDTO idDTO) { - - // 先查询 - DhAddCar dhAddCar = dhAddCarService.getById(idDTO.getId()); - if (ObjectUtil.isEmpty(dhAddCar)) { - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_ADD_CAR_INFO); - } - - if (!DhAddCarStatusEnum.TOBE_EXECUTION.eqValue(dhAddCar.getStatus())) { - return Dto.getInstance(ErrorCodeEnum.ERROR_DEL_ADD_CAR_INFO); - } - - Boolean resultBoolean = false; - if (dhAddCarService.removeById(idDTO.getId())) { - String goodIds = dhAddCar.getCarGoodIds(); - List goodIdList = new ArrayList<>(); - if (goodIds.contains(",")){ - goodIdList = Arrays.asList(goodIds.split(",")).stream().map(s -> Long.parseLong(s.trim())).collect(Collectors.toList()); - }else { - goodIdList.add(Long.valueOf(goodIds)); - } - resultBoolean = dhCarGoodsService.removeByIds(goodIdList); - } - - return Dto.returnResult(resultBoolean); - } - - /** - * 编辑刷单信息 - */ - @ApiOperation("编辑敦煌加购") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 4404, message ="敦煌加购信息不存在!") - }) - @Log(value = "编辑敦煌加购",type = LogActionType.UPDATE) - @PostMapping("/edit") - @FormSubmission - public Dto editDhAddCar(@Valid @RequestBody DhAddCarEditDTO dto) { - - DhAddCar dhAddCar = dhAddCarService.getById(dto.getId()); - if (ObjectUtil.isEmpty(dhAddCar)) { - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_ADD_CAR_INFO); - } - - if (!DhAddCarStatusEnum.TOBE_EXECUTION.eqValue(dhAddCar.getStatus())) { - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_EDIT_ADD_CAR_INFO); - } - - // 关键词 - BeanUtil.copyProperties(dto, dhAddCar); - List dhCarGoodList = new ArrayList<>(); - Boolean result = false; - if (ParamsTypeEnum.KEY_WORD.value().equals(dto.getParamsType())) { - List carGoodKeys = dto.getCarGoodKeys(); - for (DhCarGoodKeyEditDTO dhCarGoodKeyEditDTO:carGoodKeys) { - DhCarGoods dhCarGoods = new DhCarGoods(); - BeanUtil.copyProperties(dhCarGoodKeyEditDTO, dhCarGoods); - dhCarGoodList.add(dhCarGoods); - } - } - // 链接 - if (ParamsTypeEnum.LINK.value().equals(dto.getParamsType())) { - List carGoodLinks = dto.getCarGoodLinks(); - for (DhCarGoodLinkEditDTO dhCarGoodLinkEditDTO:carGoodLinks) { - DhCarGoods dhCarGoods = new DhCarGoods(); - BeanUtil.copyProperties(dhCarGoodLinkEditDTO, dhCarGoods); - dhCarGoodList.add(dhCarGoods); - } - } - if (ObjectUtil.isNotEmpty(dhCarGoodList)) { - if (dhCarGoodsService.saveOrUpdateBatch(dhCarGoodList)) { - String dhCarGoodIdStr = Joiner.on(",").join(dhCarGoodList.stream().map(DhCarGoods::getId).collect(Collectors.toList())); - dhAddCar.setCarGoodIds(dhCarGoodIdStr); - result = dhAddCarService.updateById(dhAddCar); - } - } - - return Dto.returnResult(result); - } - - - /** - * 下单成功(加购成功状态 手动转下单成功) - * @param idDTO - * @return - */ - @ApiOperation("下单成功") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 4404, message ="敦煌加购信息不存在!") - }) - @Log(value = "下单成功",type = LogActionType.UPDATE) - @PostMapping("/orderSuccess") - @FormSubmission - public Dto orderSuccess(@Valid @RequestBody IdDTO idDTO) { - DhAddCar dhAddCar = dhAddCarService.getByIdLock(idDTO.getId()); - if (ObjectUtil.isEmpty(dhAddCar)) { - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_ADD_CAR_INFO); - } - - DhAddCar updateDhAddCar = new DhAddCar(); - updateDhAddCar.setId(dhAddCar.getId()); - updateDhAddCar.setStatus(DhAddCarStatusEnum.ORDER_SUCCESS.value()); - return Dto.returnResult(dhAddCarService.updateById(updateDhAddCar)); - } - - /** - * 支付成功(下单成功状态 手动转支付成功) - * @param idDTO - * @return - */ - @ApiOperation("支付成功") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 4404, message ="敦煌加购信息不存在!") - }) - @Log(value = "支付成功",type = LogActionType.UPDATE) - @PostMapping("/toBeCatch") - @FormSubmission - public Dto toBeCatch(@Valid @RequestBody IdDTO idDTO) { - DhAddCar dhAddCar = dhAddCarService.getByIdLock(idDTO.getId()); - if (ObjectUtil.isEmpty(dhAddCar)) { - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_ADD_CAR_INFO); - } - - DhAddCar updateDhAddCar = new DhAddCar(); - updateDhAddCar.setId(dhAddCar.getId()); - updateDhAddCar.setStatus(DhAddCarStatusEnum.TO_BE_CATCH_ORDER.value()); - return Dto.returnResult(dhAddCarService.updateById(updateDhAddCar)); - } - - /** - * 好评 - * @param dto - * @return - */ - @ApiOperation("好评") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 4404, message ="敦煌加购信息不存在!") - }) - @Log(value = "好评",type = LogActionType.UPDATE) - @PostMapping("/wellReceive") - @FormSubmission - public Dto wellReceived(@Valid @RequestBody DhCarWellReceivedDTO dto) { - - - DhAddCar dhAddCar = dhAddCarService.getByIdLock(dto.getId()); - if (ObjectUtil.isEmpty(dhAddCar)) { - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_ADD_CAR_INFO); - } - - if (!DhAddCarStatusEnum.CATCH_ORDER_SUCCESS.eqValue(dhAddCar.getStatus())) { - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_WELL_RECEIVED_ADD_CAR_INFO); - } - - List goods = dto.getDialogWellReceivedGoods(); - List dhCarGoodsList = new ArrayList<>(); - for (DhCarGoodWellReceivedDTO good :goods) { - DhCarGoods dhCarGoods = new DhCarGoods(); - BeanUtil.copyProperties(good, dhCarGoods); - dhCarGoodsList.add(dhCarGoods); - } - return Dto.returnResult(dhCarGoodsService.updateBatchById(dhCarGoodsList)); - } -// -// /** -// * -// * @param file -// * @param response -// * @return -// * @throws Exception -// */ -// @ApiOperation("Excel刷单信息导入") -// @ApiImplicitParams({ -// @ApiImplicitParam(value = "上传文件", name = "file", dataType = "__file", required = true) -// }) -// @ApiResponses(value = { -// @ApiResponse(code = 200, message = "响应成功"), -// @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") -// }) -// @Log(value = "Excel刷单信息导入",type = LogActionType.ADD) -// @PostMapping("/import") -// public Dto importClickFarming(@RequestPart("file")MultipartFile file, HttpServletResponse response) throws Exception { -// -// // TODO 对Excel 信息进行检测 如果不符合要求的 最终要导出错误Excel提示 -// List ctClickFarmingImportList = ExcelUtils.readMultipartFile(file, CtClickFarmingImport.class); -// if (ObjectUtil.isEmpty(ctClickFarmingImportList)) { -// return Dto.returnResult(true); -// } -// -// List addCtClickFarmingList = new ArrayList<>(); -// List ctClickFarmingExportList = new ArrayList<>(); -// -// // 买家id -// List buyerAccountList = ctClickFarmingImportList.stream().map(c->c.getAccount()).collect(Collectors.toList()); -// Map buyerMap = ctBuyerService.getBuyerList(buyerAccountList); -// -// for (CtClickFarmingImport ctClickFarmingImport:ctClickFarmingImportList) { -// CtClickFarmingExport ctClickFarmingExport = new CtClickFarmingExport(); -// BeanUtil.copyProperties(ctClickFarmingImport, ctClickFarmingExport); -// -// StringBuffer errorStrBuf = new StringBuffer(); -// String rowTips = ctClickFarmingImport.getRowTips(); -// if (ObjectUtil.isNotEmpty(rowTips)) { -// errorStrBuf.append(rowTips); -// errorStrBuf.append(";"); -// } -// -// if (ObjectUtil.isEmpty(ctClickFarmingImport.getSpecification())) { -// errorStrBuf.append("规格-必填!"); -// errorStrBuf.append(";"); -// } -// if (ObjectUtil.isEmpty(ctClickFarmingImport.getColor())) { -// errorStrBuf.append("颜色-必填!"); -// errorStrBuf.append(";"); -// } -// if (ObjectUtil.isEmpty(ctClickFarmingImport.getExchange())) { -// errorStrBuf.append("优惠劵-必填!"); -// errorStrBuf.append(";"); -// } -// -// // 判断类型 -// if (ParamsTypeEnum.KEY_WORD.eqValue(ctClickFarmingImport.getParamsType())) { -// if (ObjectUtil.isEmpty(ctClickFarmingImport.getKeyWord())) { -// errorStrBuf.append("关键词-必填!"); -// errorStrBuf.append(";"); -// } -// if (ObjectUtil.isEmpty(ctClickFarmingImport.getTitle())) { -// errorStrBuf.append("标题-必填!"); -// errorStrBuf.append(";"); -// } -// if (ObjectUtil.isEmpty(ctClickFarmingImport.getItem())) { -// errorStrBuf.append("item-必填!"); -// errorStrBuf.append(";"); -// } -// } else { -// if (ObjectUtil.isEmpty(ctClickFarmingImport.getLink())) { -// errorStrBuf.append("链接-必填!"); -// errorStrBuf.append(";"); -// } -// } -// -// if (ObjectUtil.isEmpty(buyerMap) || !buyerMap.containsKey(ctClickFarmingImport.getAccount())) { -// errorStrBuf.append("买家信息不存在!"); -// errorStrBuf.append(";"); -// } else { -// Long buyerId = buyerMap.entrySet().stream().collect(Collectors.toMap(entity -> entity.getKey(), entity -> entity.getValue())).get(ctClickFarmingImport.getAccount()).getId(); -// ctClickFarmingImport.setBuyerId(buyerId); -// } -// if (ObjectUtil.isNotEmpty(errorStrBuf)) { -// ctClickFarmingExport.setError(errorStrBuf.toString()); -// ctClickFarmingExportList.add(ctClickFarmingExport); -// } else { -// CtClickFarming ctClickFarming = new CtClickFarming(); -// BeanUtils.copyProperties(ctClickFarmingImport, ctClickFarming); -// addCtClickFarmingList.add(ctClickFarming); -// } -// } -// -// String returnDataStr = null; -// String filePath = propertiesConfig.getUploadImgPath().get(PublicConstant.EXPORT_EXCEL_FILE_TYPE); -// String fileName = "刷单信息导入异常信息表-" + snowflake.nextIdStr(); -// if (ObjectUtil.isNotEmpty(ctClickFarmingExportList)) { -// ExcelUtils.exportFile(SystemConfig.IMG_PATH + filePath, fileName, ctClickFarmingExportList); -// returnDataStr = SystemConfig.FILE_VISIT_ADDR + filePath + fileName + ".xlsx"; -//// returnDataStr = "http://localhost:8008/file" + filePath + fileName + ".xlsx"; -// } -// -// if (ObjectUtil.isNotEmpty(addCtClickFarmingList)) { -// ctClickFarmingService.saveBatch(addCtClickFarmingList); -// } -// -// return Dto.returnResult(returnDataStr); -// } -// -// @ApiOperation("Excel刷单信息模版导出") -// @ApiResponses(value = { -// @ApiResponse(code = 200, message = "响应成功"), -// @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") -// }) -// @Log(value = "Excel刷单信息模版导出") -// @GetMapping("/exportTemp") -// @AnonymousAccess -// public void importClickFarming(HttpServletResponse response) { -// ExcelUtils.exportTemplate(response, "刷单信息模版", CtClickFarmingExportTemp.class); -// } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/DhAddCarOrderController.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/DhAddCarOrderController.java deleted file mode 100644 index 0617e82..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/DhAddCarOrderController.java +++ /dev/null @@ -1,57 +0,0 @@ -package me.zhengjie.modules.group.controller.base; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import lombok.RequiredArgsConstructor; -import me.zhengjie.annotation.Log; -import me.zhengjie.dto.Dto; -import me.zhengjie.modules.group.dto.dhaddcar.DhAddCarListDTO; -import me.zhengjie.modules.group.dto.dhcarorder.DhAddCarOrderListDTO; -import me.zhengjie.service.DhAddCarOrderService; -import me.zhengjie.service.DhAddCarService; -import me.zhengjie.service.DhCarGoodsService; -import me.zhengjie.service.vo.dhaddcar.DhAddCarListVO; -import me.zhengjie.service.vo.dhcarorder.DhAddCarOrderListVO; -import me.zhengjie.utils.PageUtils; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; -import javax.validation.Valid; - -/** - * - * @Description 群控管理-敦煌加购-订单 控制类 - * @Date 2022-06-22 - * @Author rch - */ -@Validated -@RequestMapping("/api/dhAddCarOrder") -@RestController -@RequiredArgsConstructor -@Api(tags = "业务:敦煌加购订单管理") -public class DhAddCarOrderController { - - @Resource - private DhAddCarOrderService dhAddCarOrderService; - - /** - * 分页查询敦煌加购 - */ - @ApiOperation("分页查询敦煌加购") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("分页查询敦煌加购") - @PostMapping("/list") - public Dto getDhAddCardList(@Valid @RequestBody DhAddCarOrderListDTO dto) { - PageUtils pageUtilsResult = dhAddCarOrderService.searchPageList(dto.getiPage(), dto.getWrapper()); - return Dto.returnResult(pageUtilsResult); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/QuartzLogController.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/QuartzLogController.java deleted file mode 100644 index 5f3ed6c..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/QuartzLogController.java +++ /dev/null @@ -1,55 +0,0 @@ -package me.zhengjie.modules.group.controller.base; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import lombok.RequiredArgsConstructor; -import me.zhengjie.annotation.AnonymousAccess; -import me.zhengjie.annotation.Log; -import me.zhengjie.dto.Dto; -import me.zhengjie.modules.group.dto.SysQuartzLogListDTO; -import me.zhengjie.service.SysQuartzLogService; -import me.zhengjie.service.vo.SysQuartzLogListVO; -import me.zhengjie.utils.PageUtils; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; -import javax.validation.Valid; - - -/** - * - * @Description 群控管理-影刀定时器-日志模块 - * @Date 2022-07-20 - * @Author rch - */ -@Validated -@RequestMapping("/api/quartzLog") -@RestController -@RequiredArgsConstructor -@Api(tags = "业务:影刀定时任务日志管理") -public class QuartzLogController { - - @Resource - private SysQuartzLogService sysQuartzLogService; - /** - * 分页查询影刀日志信息 - */ - @ApiOperation("分页查询影刀日志信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("分页查询影刀任务信息") - @AnonymousAccess - @PostMapping("/list") - public Dto getLogsList(@Valid @RequestBody SysQuartzLogListDTO dto) { - PageUtils pageUtilsResult= sysQuartzLogService.searchPageList(dto.getiPage(), dto.getWrapper()); - return Dto.returnResult(pageUtilsResult); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/SdsController.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/SdsController.java deleted file mode 100644 index 83943bf..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/SdsController.java +++ /dev/null @@ -1,320 +0,0 @@ -package me.zhengjie.modules.group.controller.base; - - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import me.zhengjie.annotation.AnonymousAccess; -import me.zhengjie.annotation.Log; -import me.zhengjie.dto.Dto; -import me.zhengjie.service.vo.CtApplyListVO; -import me.zhengjie.utils.HttpClientUtil; -import me.zhengjie.utils.MD5Util; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import javax.validation.Valid; -import java.util.HashMap; -import java.util.Map; -import java.util.TreeMap; - -/** - * Author: rch - * Data: 2022-11-21 - * Description SDS验签 - */ -@Validated -@RequestMapping("/api/sds") -@RestController -@Api(tags = "业务:SDS验签") -public class SdsController { - - String sdsUrlPro = "https://merchantapi.sdspod.com"; - String sdsUrlTest = "https://merchantapitest.sdspod.com"; - String appId = "LPE3NKxile1dr0TGW5hOyFzfc8S4tBUR"; - String appsecret = "DNZlt9UYOAcwCx3evHEM7nr8kuz1XRGsWjJyQpKFq5SdPf0oabBm46hVgiT2LIHViRkIFojPUV7O4FM5SQZsivJ734X7YgPBuYgyH85OUoGzbzj9Wa1Smd1AYC4GyUHA"; - - // 上传图片接口 -// @ApiOperation("上传图片接口") -// @Log("上传图片接口") -// @PostMapping("/url") -// @AnonymousAccess -// public Dto url(@Valid @RequestBody ImageUrlDTO dto){ -// -// return Dto.returnErrorResult("true"); -// } - - @ApiOperation("获取可设计产品的信息") - @Log("获取可设计产品的信息") - @GetMapping("/products") - @AnonymousAccess - public Dto products(@RequestParam(value = "page") Integer page, - @RequestParam(value = "size") Integer size){ - - // sdsUrlTest - Long millisTime = System.currentTimeMillis(); - String url = "/gateway/products/design_infos"; - Map map = new HashMap<>(); - map.put("page", page); - map.put("size", size); - map.put("_timestamp", millisTime); - - String sign = getSign(map); - System.out.println("生成sign的url:" + sign); - String md5Sign = MD5Util.md5(sign); - System.out.println("生成的sign:" + md5Sign); - map.clear(); - map.put("_appid", appId); - map.put("_timestamp", millisTime); - map.put("_sign", md5Sign); - map.put("page", page); - map.put("size", size); - - String realStrUrl = sdsUrlPro + url; - String returnStr = HttpClientUtil.getHttp(realStrUrl, map); - System.out.println("获取可设计产品的信息:" + returnStr); - return Dto.returnErrorResult(returnStr); - } - - @ApiOperation("获取产品详情") - @Log("获取产品详情") - @GetMapping("/productsDetail") - @AnonymousAccess - public Dto products(@RequestParam Integer id){ - - // sdsUrlTest - Long millisTime = System.currentTimeMillis(); - String url = "/gateway/products/" + id; - Map map = new HashMap<>(); - map.put("_timestamp", millisTime); - - String sign = getSign(map); - System.out.println("生成sign的url:" + sign); - String md5Sign = MD5Util.md5(sign); - System.out.println("生成的sign:" + md5Sign); - map.clear(); - map.put("_sign", md5Sign); - map.put("_timestamp", millisTime); - map.put("_appid", appId); - - String realStrUrl = sdsUrlPro + url; - String returnStr = HttpClientUtil.getHttp(realStrUrl, map); - System.out.println("获取产品详情:" + returnStr); - return Dto.returnErrorResult(returnStr); - } - - - @ApiOperation("获取成品列表") - @Log("获取成品列表") - @GetMapping("/endproducts") - @AnonymousAccess - public Dto endproducts(@RequestParam(value = "page") Integer page, - @RequestParam(value = "size") Integer size, - @RequestParam(value = "userId", required = false) Long userId, - @RequestParam(value = "designProductType", required = false) String designProductType){ - - // sdsUrlTest - Long millisTime = System.currentTimeMillis(); - String url = "/gateway/endproducts"; - Map map = new HashMap<>(); - map.put("page", page); - map.put("size", size); - map.put("_timestamp", millisTime); -// map.put("userId", page); -// map.put("designProductType", "SINGLE"); - - String sign = getSign(map); - System.out.println("生成sign的url:" + sign); - String md5Sign = MD5Util.md5(sign); - System.out.println("生成的sign:" + md5Sign); - map.clear(); - map.put("_appid", appId); - map.put("_timestamp", millisTime); - map.put("_sign", md5Sign); - map.put("page", page); - map.put("size", size); -// map.put("designProductType", "SINGLE"); - - String realStrUrl = sdsUrlPro + url; - String returnStr = HttpClientUtil.getHttp(realStrUrl, map); - System.out.println("获取成品列表响应:" + returnStr); - return Dto.returnErrorResult(returnStr); - } - - - // url getUrlHttp - @ApiOperation("获取成品列表Url") - @Log("获取成品列表Url") - @GetMapping("/endproductsUrl") - @AnonymousAccess - public Dto endproductsUrl(@RequestParam(value = "page") Integer page, - @RequestParam(value = "size") Integer size, - @RequestParam(value = "userId", required = false) Long userId, - @RequestParam(value = "designProductType", required = false) String designProductType){ - - // sdsUrlTest - Long millisTime = System.currentTimeMillis(); - String url = "/gateway/endproducts"; - Map map = new HashMap<>(); - map.put("page", page); - map.put("size", size); - map.put("_timestamp", millisTime); -// map.put("userId", page); -// map.put("designProductType", "SINGLE"); - - String sign = getSign(map); - System.out.println("生成sign的url:" + sign); - String md5Sign = MD5Util.md5(sign); - System.out.println("生成的sign:" + md5Sign); - map.clear(); - - map.put("_appid", appId); - map.put("_timestamp", millisTime); - map.put("_sign", md5Sign); - map.put("page", page); - map.put("size", size); -// map.put("designProductType", "SINGLE"); - - String realStrUrl = sdsUrlPro + url + "?page=" + page + "&size=" + size + "&_appid=" + appId + "&_sign=" + md5Sign + "&_timestamp=" + millisTime; - System.out.println("realStrUrl:" + realStrUrl); - String returnStr = HttpClientUtil.getUrlHttp(realStrUrl); - System.out.println("获取成品列表响应:" + returnStr); - return Dto.returnErrorResult(returnStr); - } - - @ApiOperation("根据成品ID获取成品信息") - @Log("根据成品ID获取成品信息") - @GetMapping("/endproductsById") - @AnonymousAccess - public Dto endproductsById(@RequestParam(value = "id") String id){ - // sdsUrlTest - Long millisTime = System.currentTimeMillis(); - String url = "/gateway/endproducts/" + id; - Map map = new HashMap<>(); - map.put("_timestamp", millisTime); - - String sign = getSign(map); - System.out.println("生成sign的url:" + sign); - String md5Sign = MD5Util.md5(sign); - System.out.println("生成的sign:" + md5Sign); - map.clear(); - map.put("_sign", md5Sign); - map.put("_timestamp", millisTime); - map.put("_appid", appId); - - String realStrUrl = sdsUrlPro + url; - String returnStr = HttpClientUtil.getHttp(realStrUrl, map); - System.out.println("根据成品ID获取成品信息:" + returnStr); - return Dto.returnErrorResult(returnStr); - } - - - @ApiOperation("根据成品ID获取成品详细信息包含产品详细信息") - @Log("根据成品ID获取成品详细信息包含产品详细信息") - @GetMapping("/endproductsDetailById") - @AnonymousAccess - public Dto endproductsDetailById(@RequestParam(value = "id") String id){ - // sdsUrlTest - Long millisTime = System.currentTimeMillis(); - String url = "/gateway/endproducts/" + id + "/huajuDetail"; - Map map = new HashMap<>(); - map.put("_timestamp", millisTime); - - String sign = getSign(map); - System.out.println("生成sign的url:" + sign); - String md5Sign = MD5Util.md5(sign); - System.out.println("生成的sign:" + md5Sign); - map.clear(); - map.put("_sign", md5Sign); - map.put("_timestamp", millisTime); - map.put("_appid", appId); - - String realStrUrl = sdsUrlPro + url; - String returnStr = HttpClientUtil.getHttp(realStrUrl, map); - System.out.println("根据成品ID获取成品详细信息包含产品详细信息:" + returnStr); - return Dto.returnErrorResult(returnStr); - } - - - @ApiOperation("地址") - @Log("地址") - @GetMapping("/areas") - @AnonymousAccess - public Dto areas(@RequestParam(value = "area_code", required = false) Long areaCode){ - - // sdsUrlTest - Long millisTime = System.currentTimeMillis(); - String url = "/gateway/areas/" + areaCode + "/items"; - Map map = new HashMap<>(); -// map.put("area_code", areaCode); - map.put("_timestamp", millisTime); - String sign = getSign(map); - String md5Sign = MD5Util.md5(sign); - map.clear(); - map.put("_sign", md5Sign); - map.put("_timestamp", millisTime); - map.put("_appid", appId); - - String realStrUrl = sdsUrlPro + url; - String returnStr = HttpClientUtil.getHttp(realStrUrl, map); - System.out.println("地址:" + returnStr); - return Dto.returnErrorResult(returnStr); - } - - - @ApiOperation("素材") - @Log("素材") - @GetMapping("/gateway/materials") - @AnonymousAccess - public Dto materials(@RequestParam(value = "page") Integer page, - @RequestParam(value = "size") Integer size, - @RequestParam(value = "userId", required = false) Long userId){ - - // sdsUrlTest - Long millisTime = System.currentTimeMillis(); - String url = "/gateway/materials"; - Map map = new HashMap<>(); - map.put("page", page); - map.put("size", size); - map.put("_timestamp", millisTime); -// map.put("userId", page); -// map.put("designProductType", "SINGLE"); - - String sign = getSign(map); - System.out.println("生成sign的url:" + sign); - String md5Sign = MD5Util.md5(sign); - System.out.println("生成的sign:" + md5Sign); - map.clear(); - - map.put("_appid", appId); - map.put("_timestamp", millisTime); - map.put("_sign", md5Sign); - map.put("page", page); - map.put("size", size); -// map.put("designProductType", "SINGLE"); - - String realStrUrl = sdsUrlPro + url + "?page=" + page + "&size=" + size + "&_appid=" + appId + "&_sign=" + md5Sign + "&_timestamp=" + millisTime; - System.out.println("realStrUrl:" + realStrUrl); - String returnStr = HttpClientUtil.getUrlHttp(realStrUrl); - System.out.println("获取成品列表响应:" + returnStr); - return Dto.returnErrorResult(returnStr); - } - - // Get验签 - public String getSign(Map map) { - - map.put("_appid", appId); - map.put("_appsecret", appsecret); - - - TreeMap params = new TreeMap(); - params.putAll(map); - - StringBuilder strBuilder = new StringBuilder(); - for (String key : params.keySet()) { - strBuilder.append(key).append("=").append(params.get(key)).append("&"); - } - strBuilder.deleteCharAt(strBuilder.length() - 1); - System.out.println(strBuilder); - return strBuilder.toString(); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/SysQuartzJobController.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/SysQuartzJobController.java deleted file mode 100644 index 7e5a4d3..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/SysQuartzJobController.java +++ /dev/null @@ -1,206 +0,0 @@ -package me.zhengjie.modules.group.controller.base; - - -import cn.hutool.core.lang.Snowflake; -import cn.hutool.core.util.ObjectUtil; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import me.zhengjie.annotation.AnonymousAccess; -import me.zhengjie.annotation.FormSubmission; -import me.zhengjie.annotation.Log; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.CtApply; -import me.zhengjie.entity.SysQuartzJob; -import me.zhengjie.error.ErrorCodeEnum; -import me.zhengjie.modules.group.dto.IdDTO; -import me.zhengjie.modules.group.dto.SysQuartzJobAddDTO; -import me.zhengjie.modules.group.dto.SysQuartzJobListDTO; -import me.zhengjie.modules.group.dto.SysQuartzJobUpdateDTO; -import me.zhengjie.modules.quartz.service.SysQuartzJobService; -import me.zhengjie.service.CtApplyService; -import me.zhengjie.utils.StringUtils; -import me.zhengjie.utils.YdParamsCheck; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; -import javax.validation.Valid; - -/** - * @Description 群控管理-影刀定时任务 - * @Date 2022/7/21 - * @Author zhw - */ -@Validated -@RequestMapping("/api/quartzJob") -@RestController -@Api(tags = "业务:影刀定时任务管理") -public class SysQuartzJobController { - @Resource - private SysQuartzJobService sysQuartzJobService; - @Resource - private CtApplyService ctApplyService; - @Resource - private Snowflake snowflake; - - - /** - * 分页查询影刀任务信息 - */ - @ApiOperation("分页查询影刀任务信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("分页查询影刀任务信息") - @AnonymousAccess - @PostMapping("/list") - public Dto getQuartzJobList(@Valid @RequestBody SysQuartzJobListDTO dto) { - return Dto.returnResult(sysQuartzJobService.searchPageList(dto.getiPage(), dto.getWrapper())); - } - - /** - * 新增影刀任务信息 - */ - @ApiOperation("新增影刀任务信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 3401, message = "影刀应用信息异常, 请检查后重试!") - }) - @Log("新增影刀任务信息") - @AnonymousAccess - @PostMapping("/add") - @FormSubmission - @Transactional(rollbackFor = Exception.class) - public Dto addQuartzJob(@Valid @RequestBody SysQuartzJobAddDTO dto) { - - // TODO 应用已后台添加的枚举 TaskInfoEnum 为准 根据 taskName 区分应用 逻辑 匹配params - CtApply ctApply = ctApplyService.getById(dto.getApplyId()); - if (ObjectUtil.isEmpty(ctApply)) { - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_TASK); - } - - String taskName = ctApply.getTaskName(); - String params = dto.getParams(); - Long taskNum = snowflake.nextId(); - dto.setTaskNum(taskNum); - // TODO 客户端处理 走 param模式还是 回显模式 这里先设置未null - if (!YdParamsCheck.paramIsJson(params)) { - // 测试的第一个应用 刷单 拼装params - String assemblyParams = sysQuartzJobService.assemblyParamAccordingToItem(params, taskName, taskNum); - if (StringUtils.isEmpty(assemblyParams)) { - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_TASK); - } else { - dto.setParams(assemblyParams); - } - } - - return sysQuartzJobService.addQuartzJob(dto); - } - - /** - * 根据ID删除影刀任务信息 - */ - @ApiOperation("根据ID删除影刀任务信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("根据ID删除影刀任务信息") - @PostMapping("/delete") - public Dto deleteQuartzJob(@Valid @RequestBody IdDTO idDTO) { - return Dto.returnResult(sysQuartzJobService.deleteQuartzJobById(idDTO.getId())); - } - - /** - * 编辑影刀任务信息 - */ - @ApiOperation("编辑影刀任务信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 3401, message = "影刀应用信息异常, 请检查后重试!") - }) - @Log("编辑影刀任务信息") - @PostMapping("/edit") - @FormSubmission - public Dto updateQuartzJob(@Valid @RequestBody SysQuartzJobUpdateDTO dto) { - CtApply ctApply = ctApplyService.getById(dto.getApplyId()); - if (ObjectUtil.isEmpty(ctApply)) { - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_TASK); - } - String taskName = ctApply.getTaskName(); - String params = dto.getParams(); - // TODO 客户端处理 走 param模式还是 回显模式 这里先设置未null - if (!YdParamsCheck.paramIsJson(params)) { - // TODO 先这样吧,先不回头去调整了。先能弄不考虑其他 - SysQuartzJob sysQuartzJob = sysQuartzJobService.getById(dto.getJobId()); - // 测试的第一个应用 刷单 拼装params - String assemblyParams = sysQuartzJobService.assemblyParamAccordingToItem(params, taskName, sysQuartzJob.getTaskNum()); - if (StringUtils.isEmpty(assemblyParams)) { - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_TASK); - } else { - dto.setParams(assemblyParams); - } - } - return sysQuartzJobService.updateQuartzJobById(dto); - } - - /** - * 根据ID查询影刀任务信息 - */ - @ApiOperation("根据ID查询影刀任务信息") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("根据ID查询影刀任务信息") - @PostMapping("/getById") - public Dto getQuartzJobById(@Valid @RequestBody IdDTO idDTO) { - return Dto.returnResult(sysQuartzJobService.getById(idDTO.getId())); - } - - /** - * 根据ID修改任务状态 - * @param idDTO - * @return - */ - @ApiOperation("根据ID修改任务状态") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("根据ID修改任务状态") - @PostMapping("/modifyStatus") - public Dto modifyJobStatus(@Valid @RequestBody IdDTO idDTO) { - return Dto.returnResult(sysQuartzJobService.modifyJobStatus(idDTO.getId())); - } - - /** - * 执行影刀任务 - * - * - * @param idDTO - * @return Dto - */ - @ApiOperation("执行影刀任务") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!") - }) - @Log("执行定时任务") - @PostMapping("/exec") - public Dto execution(@Valid @RequestBody IdDTO idDTO) { - Boolean one = true; - one = !one; - return Dto.returnResult(sysQuartzJobService.executionById(idDTO.getId())); - } - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/YdCallBackController.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/YdCallBackController.java deleted file mode 100644 index d3c4589..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/base/YdCallBackController.java +++ /dev/null @@ -1,122 +0,0 @@ -package me.zhengjie.modules.group.controller.base; - -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.json.JSONObject; -import cn.hutool.json.JSONUtil; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.annotation.AnonymousAccess; -import me.zhengjie.annotation.Log; -import me.zhengjie.config.YdApiProperties; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.CtRebot; -import me.zhengjie.entity.ReturnObje; -import me.zhengjie.entity.YdSign; -import me.zhengjie.enums.YesOrNoEnum; -import me.zhengjie.error.ErrorCodeEnum; -import me.zhengjie.service.CtRebotService; -import me.zhengjie.utils.YdSignUtil; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; -import javax.validation.Valid; -import java.util.Map; - -/** - * @Description - * @Date 2022/7/23 - * @Author rch - */ -@Slf4j -@Validated -@RequestMapping("/api/yd") -@RestController -@Api(tags = "业务:影刀回调管理Demo") -public class YdCallBackController { - - @Resource - private CtRebotService ctRebotService; - /** - * 影刀回调Demo - */ - @ApiOperation("影刀回调Demo") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 3700, message = "影刀回调参数空值异常!"), - @ApiResponse(code = 3701, message = "影刀回调鉴权异常!") - }) - @Log(value = "影刀回调") - @PostMapping("/callback") - @AnonymousAccess - public Dto callback(@Valid @RequestBody String data, HttpServletRequest httpServletRequest){ - log.info("=======影刀回调=======callback"); - String requestUrl = httpServletRequest.getRequestURI(); - Map map = httpServletRequest.getParameterMap(); - if (ObjectUtil.isEmpty(map.get("sign"))) { - return Dto.getInstance(ErrorCodeEnum.ERROR_PARAM_NULL); - } - - String getSign = map.get("sign")[0]; - JSONObject jsonObject = JSONUtil.parseObj(data); - String accessKeyId = YdApiProperties.ACCESS_KEY_ID; - String accessKeySecret = YdApiProperties.ACCESS_KEY_SECRET; - if (ObjectUtil.isEmpty(getSign) - || ObjectUtil.isEmpty(jsonObject) - || ObjectUtil.isEmpty(accessKeyId) - || ObjectUtil.isEmpty(accessKeySecret)) { - return Dto.getInstance(ErrorCodeEnum.ERROR_PARAM_NULL); - } - - // 根据task枚举获取 应用信息 取出 accessKey 和 accessKeySecret 用于鉴权 - - - // 鉴权 - YdSign ydSign = new YdSign(); - ydSign.setTimestamp(Long.valueOf(map.get("timestamp")[0])); - ydSign.setAccessKeyId(accessKeyId); - ydSign.setAccessKeySecret(accessKeySecret); - ydSign.setBodyMd5(map.get("bodyMd5")[0]); - - log.info("-------map:{}" , JSONUtil.toJsonStr(map)); - log.info("====ydSign====={}", JSONUtil.toJsonStr(ydSign)); - String sign = YdSignUtil.getSign(ydSign); - log.info("====sign:{} ---getSign:{}", sign, getSign); - if (ObjectUtil.isEmpty(sign) || !getSign.equals(sign)) { - return Dto.getInstance(ErrorCodeEnum.ERROR_CALLBACK_SIGN_NULL); - } - - System.out.println("===================data:" + data); - - - // TODO 拿到返回信息 根据回调知道是那个应用的业务场景 这里算是刷单系统的 - // 1.得到结果 根据结果修改 刷单信息状态 以及响应信息 - - - // TODO 获取设备id 然后修改设备状态是未占用 - ReturnObje returnObje = JSONUtil.toBean(data, ReturnObje.class); - String rebotClientName = returnObje.getRobotClientName(); - CtRebot ctRebot = ctRebotService.getByAccountNameLock(rebotClientName); - if (ObjectUtil.isEmpty(ctRebot) || !YesOrNoEnum.YES.eqValue(ctRebot.getStatus())) { - // 有问题 不执行 - System.out.println("===========设备有问题==========="); - return Dto.returnResult(true); - } else { - // 修改机器人状态 不管是什么状态,执行完成之后在我们平台就是修改为 待占用即可 - CtRebot updateCtRebot = new CtRebot(); - updateCtRebot.setId(ctRebot.getId()); - updateCtRebot.setStatus(YesOrNoEnum.NO.value()); - Boolean resultBoolean = ctRebotService.updateById(updateCtRebot); - return Dto.returnResult(resultBoolean); - } - } - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/BossTaskCallBackController.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/BossTaskCallBackController.java deleted file mode 100644 index ce0894e..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/BossTaskCallBackController.java +++ /dev/null @@ -1,84 +0,0 @@ -package me.zhengjie.modules.group.controller.callbcak; - -import cn.hutool.json.JSONUtil; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.annotation.AnonymousAccess; -import me.zhengjie.annotation.Log; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.CtApply; -import me.zhengjie.entity.ReturnObje; -import me.zhengjie.entity.quartz.JobQueryByUuidReturn; -import me.zhengjie.enums.TaskInfoEnum; -import me.zhengjie.service.CtApplyService; -import me.zhengjie.service.YdQuartzService; -import me.zhengjie.utils.YdCallBackUtil; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; -import javax.validation.Valid; - -/** - * @Description - * @Date 2022/7/23 - * @Author rch - */ -@Slf4j -@Validated -@RequestMapping("/api/bossTask") -@RestController -@Api(tags = "回调:Boss-职位查询采集-影刀回调") -public class BossTaskCallBackController { - - @Resource - private CtApplyService ctApplyService; - @Resource - private YdQuartzService ydQuartzService; - /** - * Boss-职位查询采集-影刀回调 - */ - @ApiOperation("Boss-职位查询采集-影刀回调") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 3700, message = "影刀回调参数空值异常!"), - @ApiResponse(code = 3701, message = "影刀回调鉴权异常!") - }) - @Log(value = "Boss-职位查询采集-影刀回调") - @PostMapping("/callback") - @AnonymousAccess - public Dto callback(@Valid @RequestBody String data, HttpServletRequest httpServletRequest){ - // 根据task枚举获取 应用信息 取出 accessKey 和 accessKeySecret 用于鉴权 - YdCallBackUtil ydCallBackUtil = new YdCallBackUtil(); - CtApply ctApply = ctApplyService.getApplyByTaskAndMethod(TaskInfoEnum.BOSS_TASK.getTaskName(), TaskInfoEnum.BOSS_TASK.getMethodName()); - Dto dto = ydCallBackUtil.callback(httpServletRequest, ctApply, data); - if (!dto.success(dto)) { - return dto; - } - - // 执行自己的业务逻辑 - log.info("============bossTask 回调鉴权完成 开始执行对应的定时业务逻辑================begin="); - // 获取自己想要的数据 - ReturnObje returnObje = JSONUtil.toBean(data, ReturnObje.class); - log.info("====returnObje====:{}", JSONUtil.toJsonStr(returnObje)); - // 获取应用名称 获取机器人名称 - // 执行自己的业务逻辑 - log.info("============刷单回调鉴权完成 开始执行对应的定时业务逻辑================begin="); - log.info("回调======data:" + data); - // 获取自己想要的数据 - JobQueryByUuidReturn jobQueryByUuidReturn = ydQuartzService.queryJobUuid(returnObje.getJobUuid(), ctApply.getAccessKeyId(), ctApply.getAccessKeySecret()); - log.info("====jobQueryByUuidReturn====:{}", JSONUtil.toJsonStr(jobQueryByUuidReturn)); - - log.info("============bossTask 回调鉴权完成 开始执行对应的定时业务逻辑================end==="); - return dto; - } - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/ClickFarmingCallBackController.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/ClickFarmingCallBackController.java deleted file mode 100644 index 3887c5d..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/ClickFarmingCallBackController.java +++ /dev/null @@ -1,432 +0,0 @@ -package me.zhengjie.modules.group.controller.callbcak; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.date.DateUtil; -import cn.hutool.core.lang.Snowflake; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.json.JSONUtil; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.annotation.AnonymousAccess; -import me.zhengjie.annotation.Log; -import me.zhengjie.constant.PublicConstant; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.*; -import me.zhengjie.entity.quartz.Boss; -import me.zhengjie.entity.quartz.JobQueryByUuidReturn; -import me.zhengjie.entity.quartz.Param; -import me.zhengjie.enums.*; -import me.zhengjie.modules.quartz.service.SysQuartzJobService; -import me.zhengjie.service.*; -import me.zhengjie.service.vo.CtBuyerDetailVO; -import me.zhengjie.utils.CronUtils; -import me.zhengjie.utils.RedisUtils; -import me.zhengjie.utils.YdCallBackUtil; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; -import javax.validation.Valid; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.stream.Collectors; - -/** - * @Description - * 刷单定时任务回调逻辑 - * 回调需要鉴权,鉴权是根据 accesskey accessKeySrect - * 我们应用确认之后 accesskey 和 Srect是确定的 - * - * @Date 2022-8-23 - * @Author rch - */ -@Slf4j -@Validated -@RequestMapping("/api/clickFarming") -@RestController -@Api(tags = "回调:速卖通刷单-影刀回调") -public class ClickFarmingCallBackController { - - @Resource - private CtApplyService ctApplyService; - @Resource - private YdQuartzService ydQuartzService; - @Resource - private CtClickFarmingService ctClickFarmingService; - @Resource - private CtClickOrderService ctClickOrderService; - @Resource - private RedisUtils redisUtils; - @Resource - private CtBuyerService ctBuyerService; - @Resource - private SysQuartzJobService sysQuartzJobService; - @Resource - private Snowflake snowflake; - @Resource - private SettingSiteService settingSiteService; - - private final String STAET_MODULAR = "】任务失败,在【"; - private final String END_MODULAR = "】中第"; - private final String END_LINE_NUMBER = "行:出错"; - private final Integer START_TASK_TIME = 20; - private final String RE_EXECTE_KEY = "reExecuteKey"; - /** - * 速卖通刷单-影刀回调 - */ - @ApiOperation("速卖通刷单-影刀回调") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 3700, message = "影刀回调参数空值异常!"), - @ApiResponse(code = 3701, message = "影刀回调鉴权异常!") - }) - @Log(value = "速卖通刷单-影刀回调") - @PostMapping("/callback") - @AnonymousAccess - @Transactional(rollbackFor = Exception.class) - public Dto callback(@Valid @RequestBody String data, HttpServletRequest httpServletRequest){ - - // 根据task枚举获取 应用信息 取出 accessKey 和 accessKeySecret 用于鉴权 - YdCallBackUtil ydCallBackUtil = new YdCallBackUtil(); - CtApply ctApply = ctApplyService.getApplyByTaskAndMethod(TaskInfoEnum.CLICK_FARMING.getTaskName(), TaskInfoEnum.CLICK_FARMING.getMethodName()); - Dto dto = ydCallBackUtil.callback(httpServletRequest, ctApply, data); - if (!dto.success(dto)) { - return dto; - } - - // 执行自己的业务逻辑 - log.info("============刷单回调鉴权完成 开始执行对应的定时业务逻辑================begin="); - log.info("回调======data:" + data); - // 获取自己想要的数据 - ReturnObje returnObje = JSONUtil.toBean(data, ReturnObje.class); - // job ID - String jobUuid = returnObje.getJobUuid(); - - // TODO 回调会重试 这里注意保证幂等 - // TODO 所以需要对接方在业务层面保障幂等(可以根据jobUuid或者taskUuid进行幂等保障,视startJob时是指定应用和机器人模式还是指定任务模式) - String keyJobUuid = PublicConstant.getJobUuidKeyPrefix(jobUuid); - if (!redisUtils.setIfAbsent(keyJobUuid, DateUtil.now())) { - log.info("-刷单回调接口-幂等性:keyJobUuid:" + keyJobUuid); - return Dto.returnResult(true); - } - - log.info("====returnObje====:{}", JSONUtil.toJsonStr(returnObje)); - JobQueryByUuidReturn jobQueryByUuidReturn = ydQuartzService.queryJobUuid(returnObje.getJobUuid(), ctApply.getAccessKeyId(), ctApply.getAccessKeySecret()); - log.info("====jobQueryByUuidReturn====:{}", JSONUtil.toJsonStr(jobQueryByUuidReturn)); - List inputsList = jobQueryByUuidReturn.getData().getRobotParams().getInputs(); - // 获取id - String id = null; - String buyerName = null; - String taskNum = null; - for (ResultObj resultObj:inputsList) { - if ("id".equals(resultObj.getName())) { - id = resultObj.getValue(); - } - - if ("account".equals(resultObj.getName())) { - buyerName = resultObj.getValue(); - } - - if ("taskNum".equals(resultObj.getName())) { - taskNum = resultObj.getValue(); - } - } - - Integer status = ClickFarmingStatusEnum.EXECUTION_FAILE.value(); - if ("finish".equals(jobQueryByUuidReturn.getData().getStatus())) { - status = ClickFarmingStatusEnum.EXECUTION_SUCCESS.value(); - } - - // 执行失败 - Boolean resultBoolean = false; - if (ObjectUtil.isNotEmpty(id)) { - CtClickFarming ctClickFarming = new CtClickFarming(); - ctClickFarming.setId(Long.valueOf(id)); - - // 获取买家信息并修改买家信息 - CtBuyer ctBuyer = ctBuyerService.getBuyerOccupyStatusLock(buyerName); - if (ObjectUtil.isNotEmpty(ctBuyer) && BuyerOccupyStatusEnum.OCCUPIED.value().equals(ctBuyer.getOccupyStatus())) { - ctBuyer.setOccupyStatus(BuyerOccupyStatusEnum.UN_OCCUPIED.value()); - resultBoolean = ctBuyerService.updateById(ctBuyer); - } - - // TODO 需要更新的字段 从这里获取影刀返回的 然后接着设置到 对应的 基础信息里 - List outputsList = jobQueryByUuidReturn.getData().getRobotParams().getOutputs(); - if (resultBoolean && ObjectUtil.isNotEmpty(outputsList)) { - Map resultObjMap = outputsList.stream().collect(Collectors.toMap(ResultObj::getName, ResultObj::getValue)); - CtClickOrder ctClickOrder = BeanUtil.mapToBean(resultObjMap, CtClickOrder.class, false); - if (ObjectUtil.isNotEmpty(ctClickOrder)) { - if (ObjectUtil.isNotEmpty(ctClickOrder.getPaymentResults()) && "Awaiting payment".equals(ctClickOrder.getPaymentResults())) { - status = ClickFarmingStatusEnum.AWAITING_PAYMENT.value(); - } - // 设置订单 公司 平台信息 - ctClickOrder.setCompanyId(ctBuyer.getCompanyId()); - ctClickOrder.setType(OrderTypeEnum.CLICK_FARMING.value()); - if (ctClickOrderService.save(ctClickOrder)) { - ctClickFarming.setCtClickOrderId(ctClickOrder.getId()); - } - } - } else { - // 解析json 返回错误类型 - status = analysisReturnJson(jobQueryByUuidReturn.getData().getRemark()); - } - - ctClickFarming.setStatus(status); - if (ClickFarmingStatusEnum.EXECUTION_FAILE.value().equals(status) || ClickFarmingStatusEnum.PAY_OK_ERROR.value().equals(status) || ClickFarmingStatusEnum.AWAITING_PAYMENT.value().equals(status)) { - ctClickFarming.setResponse(jobQueryByUuidReturn.getData().getRemark()); - }else { - ctClickFarming.setResponse(jobQueryByUuidReturn.getData().getStatusName()); - } - resultBoolean = ctClickFarmingService.updateById(ctClickFarming); - // TODO 判断状态 如果是执行失败 (未下单成功 未支付的则直接重新创建任务重新执行-(换个买家)) - /** - * 1.根据买家规则返回买家信息 - * 2.用新买家信息 创建新的定时任务 - */ - // 查询刷单信息 默认不执行 只有设置1才执行 - String reExecuteValue = settingSiteService.getValue(RE_EXECTE_KEY); - if (ObjectUtil.isNotEmpty(reExecuteValue) && "1".equals(reExecuteValue)) { - CtClickFarming ctClickFarmingOld = ctClickFarmingService.getById(id); - if (ClickFarmingStatusEnum.EXECUTION_FAILE.value().equals(status)) { - SysQuartzJob sysQuartzJob = sysQuartzJobService.getByTaskNum(taskNum); - if (ObjectUtil.isEmpty(sysQuartzJob)) { - return Dto.returnResult(false); - } - resultBoolean = reExecuteTask(sysQuartzJob, ctClickFarmingOld); - } - } - } - - log.info("============刷单回调鉴权完成 开始执行对应的定时业务逻辑================end==="); - return Dto.returnResult(resultBoolean); - } - - /** - * 执行失败-重新创建定时任务 - * @param sysQuartzJob - * @return - */ - private Boolean reExecuteTask(SysQuartzJob sysQuartzJob, CtClickFarming ctClickFarming) { - // TODO 根据规则 修改 param 参数信息 以及 - log.info("刷单任务-执行失败-重新创建定时任务--sysQuartzJob:{} --ctClickFarming:{}", JSONUtil.toJsonStr(sysQuartzJob), JSONUtil.toJsonStr(ctClickFarming)); - // 创建后启用状态 并且 失败不暂停(失败后要暂停的) - sysQuartzJob.setIsPause(TaskIsPauseEnum.NOT_PAUSE.value()); - sysQuartzJob.setPauseAfterFailure(TaskIsPauseEnum.IS_PAUSE.value()); - // 设置执行时间 - String cronStr = CronUtils.onlyOnce(DateUtil.formatDateTime(DateUtil.offsetSecond(DateUtil.date(), START_TASK_TIME))); - sysQuartzJob.setCronExpression(cronStr); - // 新的定时任务taskNum - Long taskNum = snowflake.nextId(); - sysQuartzJob.setJobName(jobNameNew(sysQuartzJob.getJobName(), sysQuartzJob.getTaskNum().toString())); - // 买家信息 - String paramsStr = sysQuartzJob.getParams(); - Boss bossObj = JSONUtil.toBean(paramsStr, Boss.class); - log.info("bossObj--before:" + JSONUtil.toJsonStr(bossObj)); - List paramList = bossObj.getParams(); - Param paramAccount = paramList.stream().filter(r->"account".equals(r.getName())).findFirst().get(); - Param paramCountry = paramList.stream().filter(r->"country".equals(r.getName())).findFirst().get(); - // 替换新的买家信息 - CtBuyerDetailVO ctBuyerDetailVO = getRuleCtBuyer(paramAccount.getValue(), paramCountry.getValue(), ctClickFarming); - if (ObjectUtil.isEmpty(ctBuyerDetailVO)) { - log.info("买家信息全部执行完成,没有可选择的买家信息!-任务不在重试"); - return false; - } - for (Param paramObj:paramList) { - if (("country").equals(paramObj.getName())) { - paramObj.setValue(ctBuyerDetailVO.getCountry()); - } - if (("account").equals(paramObj.getName())) { - paramObj.setValue(ctBuyerDetailVO.getAccount()); - } - if (("pwd").equals(paramObj.getName())) { - paramObj.setValue(ctBuyerDetailVO.getPwd()); - } - if (("vpnShare").equals(paramObj.getName())) { - paramObj.setValue(ctBuyerDetailVO.getVpn()); - } - // 信用卡 - if (("cardName").equals(paramObj.getName())) { - paramObj.setValue(ctBuyerDetailVO.getHolderSurname() + " " + ctBuyerDetailVO.getHolderName()); - } - if (("cardNumber").equals(paramObj.getName())) { - paramObj.setValue(ctBuyerDetailVO.getNumber()); - } - if (("cardPwd").equals(paramObj.getName())) { - paramObj.setValue(ctBuyerDetailVO.getCardPwd()); - } - if (("taskNum").equals(paramObj.getName())) { - paramObj.setValue(taskNum.toString()); - } - } - - log.info("bossObj--after:" + JSONUtil.toJsonStr(bossObj)); - sysQuartzJob.setParams(JSONUtil.toJsonStr(bossObj)); - sysQuartzJob.setTaskNum(taskNum); - - sysQuartzJobService.reAddQuartzJob(sysQuartzJob); - - return true; - } - - /** - * 返回新的jobName名字 - * 原则上传入的 jobName 和 taskNum 是同一个QuartzJob的。 - * 这个返回的 作为子集的 job_name = 父级原本的jobName + 父级的taskNum - * 为后续 排查使用 (最好是新设置一个字段,这里先这样) - * 说明: 父级的意思说的是 上级, 比如A任务 回调失败,换个买家 新创建任务B A就说是B的父级 - * @param jobName - * @param taskNum - * @return - */ - public String jobNameNew(String jobName, String taskNum) { - if (jobName.contains("-")) { - jobName = jobName.substring(0,jobName.lastIndexOf("-")); - } - - return jobName + "-" + taskNum; - } - - - /** - * 根据规则获取新的买家信息 - * @param buyerAccount - * @return - */ - public CtBuyerDetailVO getRuleCtBuyer(String buyerAccount, String country, CtClickFarming ctClickFarming) { - if (ObjectUtil.isEmpty(buyerAccount) - || ObjectUtil.isEmpty(country) - || ObjectUtil.isEmpty(ctClickFarming) - || ObjectUtil.isEmpty(ctClickFarming.getShopName()) - || ObjectUtil.isEmpty(ctClickFarming.getId())) { - return null; - } - // 获取所有成功的刷单信息买家 然后统计每个成功的个数并返回 同时剔除传过来的参数信息 - // TODO 这里不能无限制的取, 通过redis 根据 刷单id 设置取过的买家信息,取过的不再取了 - List ctBuyerClickSuccessList = ctClickFarmingService.ruleGetCtBuyer(buyerAccount, country, ctClickFarming.getShopName()); - String clickFarmingExecBuyerIdPrefix = PublicConstant.getClickFarmingExecBuyerIdPrefix(ctClickFarming.getId()); - Long setSize = redisUtils.sGetSetSize(clickFarmingExecBuyerIdPrefix); - Long buyerId = null; - if (setSize == 0) { - buyerId = ctBuyerClickSuccessList.get(new Random().nextInt(ctBuyerClickSuccessList.size())).getBuyerId(); - } else { - for (CtBuyerClickSuccess ctBuyerClickSuccess : ctBuyerClickSuccessList) { - buyerId = ctBuyerClickSuccess.getBuyerId(); - if (redisUtils.sHasKey(clickFarmingExecBuyerIdPrefix, buyerId.toString())) { - continue; - } - break; - } - System.out.println("没有取到合适的========================================"); - } - - if (ObjectUtil.isNotEmpty(buyerId)) { - redisUtils.sSet(clickFarmingExecBuyerIdPrefix, buyerId.toString()); - return ctBuyerService.getDetailById(buyerId); - } - return null; - } - - - - /** - * 解析json 区分错误类型 4.有订单id之前的异常 5.有订单未支付 6.支付成功异常 - * @param remark - * @return Integer - */ - private Integer analysisReturnJson(String remark) { - // 根据规则解析 - // "remark": "【0757f764-07b4-4d4d-a48d-e1e13b598a1f】任务失败,在【5-1清空银行卡】中第17行:出错:未找到元素, 元素名: 按钮_OK", - // "remark": "【9a92a414-e957-47f8-ada1-7296723769a9】任务失败,在【9-1优惠劵】中第7行:出错:未找到元素", - // "remark": "【60a92f00-f7cb-4321-aa0b-6f18814fb462】任务失败,在【3.切换国家】中第8行:出错:未找到元素", - // "remark": "【81f6c1ac-6493-40cf-83fd-867b1a39e3ca】任务失败,在【9-3添加银行卡】中第5行:出错:未找到元素, 元素名: SAVE CARD", - // "remark": "【e201a1b3-f0a1-42b9-8315-d6736eead5a4】任务失败,在【1-2清空浏览器数据】中第1行:出错:操作无法执行!请重启当前浏览器 或 重装当前浏览器插件后再次尝试。", -// 【923eea47-c056-47ef-bccf-930d8ef700da】任务失败,在【9-1.留言】中第2行:出错:未找到元素, 元素名: 留言板 -// private final String STAET_MODULAR = "】任务失败,在【"; -// private final String END_MODULAR = "】中第"; -// private final String END_LINE_NUMBER = "行:出错"; -// private final Integer START_TASK_TIME = 10; - /** - * 1.切换VPN - * 2.关闭弹窗 - * 3.清空浏览器 - * 4.切换国家 - * 5.登录 - * 6.清空购物车 - * 6-1.清空银行卡 - * 7.搜索商品 - * 7-1.随意浏览界面 - * 7-2.滚动鼠标浏览界面 - * 7-3.随机点击商品 - * 7-4.浏览随机商品 - * 7-5匹配商品信息 - * 8.商品下单 - * 8-1.滚动鼠标浏览商品 - * 8-2.查找规格 - * 8-3.查找颜色 - * 8-4.商品个数 - * 9.购物车-------------------------------有订单未支付:流程第19行点击Pay_now - * 9-1.留言 - * 9-2.添加银行卡 - * 9-3.选择银行卡有效时间 - * 9-4.选择优惠券 - * 10.回到首页----------------------回到首页:流程第11行点击首页 - * 11.获取订单信息 - * 12.退出账号 - */ - log.info(remark); - if (ObjectUtil.isEmpty(remark) - || !remark.contains("任务失败") - || !remark.contains("中第") - || !remark.contains("行:出错") - || remark.length() <= 12) { - return ClickFarmingStatusEnum.EXECUTION_FAILE.value(); - } - - String modular = remark.substring(remark.indexOf(STAET_MODULAR) + 8, remark.indexOf(END_MODULAR)); - String lineNumber = remark.substring(remark.indexOf(END_MODULAR) + 3, remark.indexOf(END_LINE_NUMBER)); - - // 子模块可以忽略 - Integer modularInteger = 0; - Integer lineNumberInteger = 0; - if (ObjectUtil.isNotEmpty(modular)) { - if (modular.contains(".") && !modular.contains("-") ) { - modularInteger = Integer.valueOf(modular.substring(0, modular.indexOf("."))); - } else if (modular.contains("-")) { - modularInteger = Integer.valueOf(modular.split("-")[0]); - } - } - if (ObjectUtil.isNotEmpty(lineNumber)) { - lineNumberInteger = Integer.valueOf(lineNumber); - } - - if (modularInteger < 9) { - return ClickFarmingStatusEnum.EXECUTION_FAILE.value(); - } else if(modularInteger == 9) { - if (lineNumberInteger <= 19) { - return ClickFarmingStatusEnum.EXECUTION_FAILE.value(); - } else { - return ClickFarmingStatusEnum.AWAITING_PAYMENT.value(); - } - } else if (modularInteger < 10){ - return ClickFarmingStatusEnum.AWAITING_PAYMENT.value(); - } else if(modularInteger == 10) { - if (lineNumberInteger <= 11) { - return ClickFarmingStatusEnum.AWAITING_PAYMENT.value(); - } else { - return ClickFarmingStatusEnum.PAY_OK_ERROR.value(); - } - } else { - return ClickFarmingStatusEnum.PAY_OK_ERROR.value(); - } - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/ClickFarmingSuppleMentCallBackController.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/ClickFarmingSuppleMentCallBackController.java deleted file mode 100644 index 1250309..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/ClickFarmingSuppleMentCallBackController.java +++ /dev/null @@ -1,234 +0,0 @@ -package me.zhengjie.modules.group.controller.callbcak; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.date.DateUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.json.JSONUtil; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.annotation.AnonymousAccess; -import me.zhengjie.annotation.Log; -import me.zhengjie.constant.PublicConstant; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.*; -import me.zhengjie.entity.quartz.JobQueryByUuidReturn; -import me.zhengjie.enums.BuyerOccupyStatusEnum; -import me.zhengjie.enums.ClickFarmingStatusEnum; -import me.zhengjie.enums.TaskInfoEnum; -import me.zhengjie.service.*; -import me.zhengjie.utils.RedisUtils; -import me.zhengjie.utils.YdCallBackUtil; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; -import javax.validation.Valid; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * @Description - * 刷单补录定时任务回调逻辑 - * 回调需要鉴权,鉴权是根据 accesskey accessKeySrect - * 我们应用确认之后 accesskey 和 Srect是确定的 - * - * @Date 2022-8-23 - * @Author rch - */ -@Slf4j -@Validated -@RequestMapping("/api/clickFarmSupplyMent") -@RestController -@Api(tags = "回调:速卖通刷单补录-影刀回调") -public class ClickFarmingSuppleMentCallBackController { - - @Resource - private CtApplyService ctApplyService; - @Resource - private YdQuartzService ydQuartzService; - @Resource - private CtClickFarmingService ctClickFarmingService; - @Resource - private CtClickOrderService ctClickOrderService; - @Resource - private RedisUtils redisUtils; - @Resource - private CtBuyerService ctBuyerService; - - private final String STAET_MODULAR = "】任务失败,在【"; - private final String END_MODULAR = "】中第"; - private final String END_LINE_NUMBER = "行:出错"; - private final Integer START_TASK_TIME = 20; - - /** - * 速卖通刷单补录-回调 - */ - @ApiOperation("速卖通刷单补录-回调") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 3700, message = "影刀回调参数空值异常!"), - @ApiResponse(code = 3701, message = "影刀回调鉴权异常!") - }) - @Log(value = "速卖通刷单补录-回调") - @PostMapping("/callback") - @AnonymousAccess - @Transactional(rollbackFor = Exception.class) - public Dto callback(@Valid @RequestBody String data, HttpServletRequest httpServletRequest){ - - // 根据task枚举获取 应用信息 取出 accessKey 和 accessKeySecret 用于鉴权 - YdCallBackUtil ydCallBackUtil = new YdCallBackUtil(); - CtApply ctApply = ctApplyService.getApplyByTaskAndMethod(TaskInfoEnum.CLICK_FARMING_SUPPLE_MENY.getTaskName(), TaskInfoEnum.CLICK_FARMING_SUPPLE_MENY.getMethodName()); - Dto dto = ydCallBackUtil.callback(httpServletRequest, ctApply, data); - if (!dto.success(dto)) { - return dto; - } - - // 执行自己的业务逻辑 - log.info("============刷单回调鉴权完成 开始执行对应的定时业务逻辑================begin="); - log.info("回调======data:" + data); - // 获取自己想要的数据 - ReturnObje returnObje = JSONUtil.toBean(data, ReturnObje.class); - // job ID - String jobUuid = returnObje.getJobUuid(); - - // TODO 回调会重试 这里注意保证幂等 - // TODO 所以需要对接方在业务层面保障幂等(可以根据jobUuid或者taskUuid进行幂等保障,视startJob时是指定应用和机器人模式还是指定任务模式) - String keyJobUuid = PublicConstant.getJobUuidKeyPrefix(jobUuid); - if (!redisUtils.setIfAbsent(keyJobUuid, DateUtil.now())) { - log.info("-刷单回调接口-幂等性:keyJobUuid:" + keyJobUuid); - return Dto.returnResult(true); - } - - log.info("====returnObje====:{}", JSONUtil.toJsonStr(returnObje)); - JobQueryByUuidReturn jobQueryByUuidReturn = ydQuartzService.queryJobUuid(returnObje.getJobUuid(), ctApply.getAccessKeyId(), ctApply.getAccessKeySecret()); - log.info("====jobQueryByUuidReturn====:{}", JSONUtil.toJsonStr(jobQueryByUuidReturn)); - List inputsList = jobQueryByUuidReturn.getData().getRobotParams().getInputs(); - // 获取id - String id = null; - String buyerName = null; - for (ResultObj resultObj:inputsList) { - if ("id".equals(resultObj.getName())) { - id = resultObj.getValue(); - } - - if ("account".equals(resultObj.getName())) { - buyerName = resultObj.getValue(); - } - } - -// Integer status = ClickFarmingStatusEnum.EXECUTION_FAILE.value(); - Integer status = ClickFarmingStatusEnum.AWAITING_PAYMENT.value(); - if ("finish".equals(jobQueryByUuidReturn.getData().getStatus())) { - status = ClickFarmingStatusEnum.EXECUTION_SUCCESS.value(); - } - - // 执行失败 - Boolean resultBoolean = false; - if (ObjectUtil.isNotEmpty(id)) { - CtClickFarming ctClickFarming = new CtClickFarming(); - ctClickFarming.setId(Long.valueOf(id)); - - // 获取买家信息并修改买家信息 - CtBuyer ctBuyer = ctBuyerService.getBuyerOccupyStatusLock(buyerName); - if (ObjectUtil.isNotEmpty(ctBuyer) && BuyerOccupyStatusEnum.OCCUPIED.value().equals(ctBuyer.getOccupyStatus())) { - ctBuyer.setOccupyStatus(BuyerOccupyStatusEnum.UN_OCCUPIED.value()); - resultBoolean = ctBuyerService.updateById(ctBuyer); - } - - // TODO 需要更新的字段 从这里获取影刀返回的 然后接着设置到 对应的 基础信息里 - List outputsList = jobQueryByUuidReturn.getData().getRobotParams().getOutputs(); - if (resultBoolean && ObjectUtil.isNotEmpty(outputsList)) { - Map resultObjMap = outputsList.stream().collect(Collectors.toMap(ResultObj::getName, ResultObj::getValue)); - CtClickOrder ctClickOrder = BeanUtil.mapToBean(resultObjMap, CtClickOrder.class, false); - if (ObjectUtil.isNotEmpty(ctClickOrder)) { - if (ObjectUtil.isNotEmpty(ctClickOrder.getPaymentResults()) && "Awaiting payment".equals(ctClickOrder.getPaymentResults())) { - status = ClickFarmingStatusEnum.AWAITING_PAYMENT.value(); - } - // 设置订单 公司 平台信息 - ctClickOrder.setCompanyId(ctBuyer.getCompanyId()); - if (ctClickOrderService.save(ctClickOrder)) { - ctClickFarming.setCtClickOrderId(ctClickOrder.getId()); - } - } - }else { - // 解析json 返回错误类型 - status = analysisReturnJson(jobQueryByUuidReturn.getData().getRemark()); - } - - ctClickFarming.setStatus(status); - if (ClickFarmingStatusEnum.EXECUTION_FAILE.value().equals(status) || ClickFarmingStatusEnum.PAY_OK_ERROR.value().equals(status)) { - ctClickFarming.setResponse(jobQueryByUuidReturn.getData().getRemark()); - }else { - ctClickFarming.setResponse(jobQueryByUuidReturn.getData().getStatusName()); - } - resultBoolean = ctClickFarmingService.updateById(ctClickFarming); - } - - log.info("============刷单补录回调鉴权完成 开始执行对应的定时业务逻辑================end==="); - return Dto.returnResult(resultBoolean); - } - - - /** - * 解析json 区分错误类型 - * @param remark - * @return Integer - */ - private Integer analysisReturnJson(String remark) { - // 根据规则解析 - /** - 1.切换VPN - 2.关闭弹窗 - 3.清空浏览器 - 4.切换国家 - 5.登录 - 6.订单首页 - 6-1.添加银行卡 - 6-2.选择银行卡有效时间 - 7.获取订单信息-------------------支付成功:流程7行(包含) - 8.退出账号 - */ - if (ObjectUtil.isEmpty(remark) || !remark.contains("任务失败")) { - return ClickFarmingStatusEnum.EXECUTION_FAILE.value(); - } - - String modular = remark.substring(remark.indexOf(STAET_MODULAR) + 8, remark.indexOf(END_MODULAR)); - String lineNumber = remark.substring(remark.indexOf(END_MODULAR) + 3, remark.indexOf(END_LINE_NUMBER)); - - // 子模块可以忽略 - Integer modularInteger = 0; - Integer lineNumberInteger = 0; - if (ObjectUtil.isNotEmpty(modular)) { - if (modular.contains(".") && !modular.contains("-") ) { - modularInteger = Integer.valueOf(modular.substring(0, modular.indexOf("."))); - } else if (modular.contains("-")) { - modularInteger = Integer.valueOf(modular.split("-")[0]); - } - } - if (ObjectUtil.isNotEmpty(lineNumber)) { - lineNumberInteger = Integer.valueOf(lineNumber); - } - - if (modularInteger < 7) { - return ClickFarmingStatusEnum.AWAITING_PAYMENT.value(); - } else if(modularInteger == 7) { - if (lineNumberInteger < 7) { - return ClickFarmingStatusEnum.AWAITING_PAYMENT.value(); - } else { - return ClickFarmingStatusEnum.PAY_OK_ERROR.value(); - } - } else { - return ClickFarmingStatusEnum.PAY_OK_ERROR.value(); - } - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/ClickOrderCallBackController.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/ClickOrderCallBackController.java deleted file mode 100644 index d903379..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/ClickOrderCallBackController.java +++ /dev/null @@ -1,151 +0,0 @@ -package me.zhengjie.modules.group.controller.callbcak; - -import cn.hutool.core.date.DateUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.json.JSONUtil; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.annotation.AnonymousAccess; -import me.zhengjie.annotation.Log; -import me.zhengjie.constant.PublicConstant; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.*; -import me.zhengjie.entity.quartz.JobQueryByUuidReturn; -import me.zhengjie.enums.BuyerOccupyStatusEnum; -import me.zhengjie.enums.ClickOrderStatusEnum; -import me.zhengjie.enums.TaskInfoEnum; -import me.zhengjie.service.CtApplyService; -import me.zhengjie.service.CtBuyerService; -import me.zhengjie.service.CtClickOrderService; -import me.zhengjie.service.YdQuartzService; -import me.zhengjie.utils.RedisUtils; -import me.zhengjie.utils.YdCallBackUtil; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; -import javax.validation.Valid; -import java.util.List; - -/** - * @Description - * 好评定时任务回调逻辑 - * 回调需要鉴权,鉴权是根据 accesskey accessKeySrect - * 我们应用确认之后 accesskey 和 Srect是确定的 - * - * @Date 2022-8-23 - * @Author rch - */ -@Slf4j -@Validated -@RequestMapping("/api/clickOrder") -@RestController -@Api(tags = "回调:速卖通刷单好评-影刀回调") -public class ClickOrderCallBackController { - - @Resource - private CtApplyService ctApplyService; - @Resource - private YdQuartzService ydQuartzService; - @Resource - private CtClickOrderService ctClickOrderService; - @Resource - private RedisUtils redisUtils; - @Resource - private CtBuyerService ctBuyerService; - - /** - * 速卖通刷单好评-好评回调 - */ - @ApiOperation("速卖通刷单好评-好评回调") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 3700, message = "影刀回调参数空值异常!"), - @ApiResponse(code = 3701, message = "影刀回调鉴权异常!") - }) - @Log(value = "速卖通刷单好评-好评回调") - @PostMapping("/callback") - @AnonymousAccess - @Transactional(rollbackFor = Exception.class) - public Dto callback(@Valid @RequestBody String data, HttpServletRequest httpServletRequest){ - - // 根据task枚举获取 应用信息 取出 accessKey 和 accessKeySecret 用于鉴权 - YdCallBackUtil ydCallBackUtil = new YdCallBackUtil(); - CtApply ctApply = ctApplyService.getApplyByTaskAndMethod(TaskInfoEnum.WELL_RECEIVED.getTaskName(), TaskInfoEnum.WELL_RECEIVED.getMethodName()); - Dto dto = ydCallBackUtil.callback(httpServletRequest, ctApply, data); - if (!dto.success(dto)) { - return dto; - } - - // 执行自己的业务逻辑 - log.info("============刷单回调鉴权完成 开始执行对应的定时业务逻辑================begin="); - log.info("回调======data:" + data); - // 获取自己想要的数据 - ReturnObje returnObje = JSONUtil.toBean(data, ReturnObje.class); - // job ID - String jobUuid = returnObje.getJobUuid(); - - // TODO 回调会重试 这里注意保证幂等 - // TODO 所以需要对接方在业务层面保障幂等(可以根据jobUuid或者taskUuid进行幂等保障,视startJob时是指定应用和机器人模式还是指定任务模式) - String keyJobUuid = PublicConstant.getJobUuidKeyPrefix(jobUuid); - if (!redisUtils.setIfAbsent(keyJobUuid, DateUtil.now())) { - log.info("-刷单回调接口-幂等性:keyJobUuid:" + keyJobUuid); - return Dto.returnResult(true); - } - - log.info("====returnObje====:{}", JSONUtil.toJsonStr(returnObje)); - JobQueryByUuidReturn jobQueryByUuidReturn = ydQuartzService.queryJobUuid(returnObje.getJobUuid(), ctApply.getAccessKeyId(), ctApply.getAccessKeySecret()); - log.info("====jobQueryByUuidReturn====:{}", JSONUtil.toJsonStr(jobQueryByUuidReturn)); - List inputsList = jobQueryByUuidReturn.getData().getRobotParams().getInputs(); - // 获取id - String id = null; - String buyerName = null; - for (ResultObj resultObj:inputsList) { - if ("id".equals(resultObj.getName())) { - id = resultObj.getValue(); - } - - if ("account".equals(resultObj.getName())) { - buyerName = resultObj.getValue(); - } - } - - Integer status = ClickOrderStatusEnum.EXECUTION_FAILE.value(); - if ("finish".equals(jobQueryByUuidReturn.getData().getStatus())) { - status = ClickOrderStatusEnum.EXECUTION_SUCCESS.value(); - } - - // 执行失败 - Boolean resultBoolean = false; - if (ObjectUtil.isNotEmpty(id)) { - CtClickOrder ctClickOrder = new CtClickOrder(); - ctClickOrder.setId(Long.valueOf(id)); - ctClickOrder.setStatus(status); - ctClickOrder.setPaymentResults(jobQueryByUuidReturn.getData().getRemark()); - - // 获取买家信息并修改买家信息 - CtBuyer ctBuyer = ctBuyerService.getBuyerOccupyStatusLock(buyerName); - if (ObjectUtil.isNotEmpty(ctBuyer) && BuyerOccupyStatusEnum.OCCUPIED.value().equals(ctBuyer.getOccupyStatus())) { - ctBuyer.setOccupyStatus(BuyerOccupyStatusEnum.UN_OCCUPIED.value()); - resultBoolean = ctBuyerService.updateById(ctBuyer); - } - - // TODO 需要更新的字段 从这里获取影刀返回的 然后接着设置到 对应的 基础信息里 - if (resultBoolean) { - resultBoolean = ctClickOrderService.updateById(ctClickOrder); - } - } - - log.info("============刷单回调鉴权完成 开始执行对应的定时业务逻辑================end==="); - return Dto.returnResult(resultBoolean); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/CtbrowseCallBackController.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/CtbrowseCallBackController.java deleted file mode 100644 index f575b42..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/CtbrowseCallBackController.java +++ /dev/null @@ -1,148 +0,0 @@ -package me.zhengjie.modules.group.controller.callbcak; - -import cn.hutool.core.date.DateUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.json.JSONUtil; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.annotation.AnonymousAccess; -import me.zhengjie.annotation.Log; -import me.zhengjie.constant.PublicConstant; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.*; -import me.zhengjie.entity.quartz.JobQueryByUuidReturn; -import me.zhengjie.enums.BuyerOccupyStatusEnum; -import me.zhengjie.enums.ClickOrderStatusEnum; -import me.zhengjie.enums.TaskInfoEnum; -import me.zhengjie.service.*; -import me.zhengjie.utils.RedisUtils; -import me.zhengjie.utils.YdCallBackUtil; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; -import javax.validation.Valid; -import java.util.List; - -/** - * @Description - * 浏览收藏定时任务回调逻辑 - * 回调需要鉴权,鉴权是根据 accesskey accessKeySrect - * 我们应用确认之后 accesskey 和 Srect是确定的 - * - * @Date 2022-8-23 - * @Author rch - */ -@Slf4j -@Validated -@RequestMapping("/api/ctBrowse") -@RestController -@Api(tags = "回调:速卖通浏览收藏-影刀回调") -public class CtbrowseCallBackController { - - @Resource - private CtApplyService ctApplyService; - @Resource - private YdQuartzService ydQuartzService; - @Resource - private CtBrowseService ctBrowseService; - @Resource - private RedisUtils redisUtils; - @Resource - private CtBuyerService ctBuyerService; - - /** - * 速卖通刷单好评-好评回调 - */ - @ApiOperation("速卖通浏览收藏-回调") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 3700, message = "影刀回调参数空值异常!"), - @ApiResponse(code = 3701, message = "影刀回调鉴权异常!") - }) - @Log(value = "速卖通浏览收藏-回调") - @PostMapping("/callback") - @AnonymousAccess - @Transactional(rollbackFor = Exception.class) - public Dto callback(@Valid @RequestBody String data, HttpServletRequest httpServletRequest){ - - // 根据task枚举获取 应用信息 取出 accessKey 和 accessKeySecret 用于鉴权 - YdCallBackUtil ydCallBackUtil = new YdCallBackUtil(); - CtApply ctApply = ctApplyService.getApplyByTaskAndMethod(TaskInfoEnum.BROWSE.getTaskName(), TaskInfoEnum.BROWSE.getMethodName()); - Dto dto = ydCallBackUtil.callback(httpServletRequest, ctApply, data); - if (!dto.success(dto)) { - return dto; - } - - // 执行自己的业务逻辑 - log.info("============刷单回调鉴权完成 开始执行对应的定时业务逻辑================begin="); - log.info("回调======data:" + data); - // 获取自己想要的数据 - ReturnObje returnObje = JSONUtil.toBean(data, ReturnObje.class); - // job ID - String jobUuid = returnObje.getJobUuid(); - - // TODO 回调会重试 这里注意保证幂等 - // TODO 所以需要对接方在业务层面保障幂等(可以根据jobUuid或者taskUuid进行幂等保障,视startJob时是指定应用和机器人模式还是指定任务模式) - String keyJobUuid = PublicConstant.getJobUuidKeyPrefix(jobUuid); - if (!redisUtils.setIfAbsent(keyJobUuid, DateUtil.now())) { - log.info("-刷单回调接口-幂等性:keyJobUuid:" + keyJobUuid); - return Dto.returnResult(true); - } - - log.info("====returnObje====:{}", JSONUtil.toJsonStr(returnObje)); - JobQueryByUuidReturn jobQueryByUuidReturn = ydQuartzService.queryJobUuid(returnObje.getJobUuid(), ctApply.getAccessKeyId(), ctApply.getAccessKeySecret()); - log.info("====jobQueryByUuidReturn====:{}", JSONUtil.toJsonStr(jobQueryByUuidReturn)); - List inputsList = jobQueryByUuidReturn.getData().getRobotParams().getInputs(); - // 获取id - String id = null; - String buyerName = null; - for (ResultObj resultObj:inputsList) { - if ("id".equals(resultObj.getName())) { - id = resultObj.getValue(); - } - - if ("account".equals(resultObj.getName())) { - buyerName = resultObj.getValue(); - } - } - - Integer status = ClickOrderStatusEnum.EXECUTION_FAILE.value(); - if ("finish".equals(jobQueryByUuidReturn.getData().getStatus())) { - status = ClickOrderStatusEnum.EXECUTION_SUCCESS.value(); - } - - // 执行失败 - Boolean resultBoolean = false; - if (ObjectUtil.isNotEmpty(id)) { - CtBrowse ctBrowse = new CtBrowse(); - ctBrowse.setId(Long.valueOf(id)); - ctBrowse.setStatus(status); - ctBrowse.setPaymentResults(jobQueryByUuidReturn.getData().getRemark()); - - // 获取买家信息并修改买家信息 - CtBuyer ctBuyer = ctBuyerService.getBuyerOccupyStatusLock(buyerName); - if (ObjectUtil.isNotEmpty(ctBuyer) && BuyerOccupyStatusEnum.OCCUPIED.value().equals(ctBuyer.getOccupyStatus())) { - ctBuyer.setOccupyStatus(BuyerOccupyStatusEnum.UN_OCCUPIED.value()); - resultBoolean = ctBuyerService.updateById(ctBuyer); - } - - // TODO 需要更新的字段 从这里获取影刀返回的 然后接着设置到 对应的 基础信息里 - if (resultBoolean) { - resultBoolean = ctBrowseService.updateById(ctBrowse); - } - } - - log.info("============刷单回调鉴权完成 开始执行对应的定时业务逻辑================end==="); - return Dto.returnResult(resultBoolean); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/DhAddCarCallBackController.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/DhAddCarCallBackController.java deleted file mode 100644 index e133d6a..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/DhAddCarCallBackController.java +++ /dev/null @@ -1,152 +0,0 @@ -package me.zhengjie.modules.group.controller.callbcak; - -import cn.hutool.core.date.DateUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.json.JSONUtil; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.annotation.AnonymousAccess; -import me.zhengjie.annotation.Log; -import me.zhengjie.constant.PublicConstant; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.*; -import me.zhengjie.entity.quartz.JobQueryByUuidReturn; -import me.zhengjie.enums.BuyerOccupyStatusEnum; -import me.zhengjie.enums.ClickFarmingStatusEnum; -import me.zhengjie.enums.DhAddCarStatusEnum; -import me.zhengjie.enums.TaskInfoEnum; -import me.zhengjie.service.*; -import me.zhengjie.utils.RedisUtils; -import me.zhengjie.utils.YdCallBackUtil; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; -import javax.validation.Valid; -import java.util.List; - -/** - * @Description - * 敦煌加购定时任务回调逻辑 - * 回调需要鉴权,鉴权是根据 accesskey accessKeySrect - * 我们应用确认之后 accesskey 和 Srect是确定的 - * - * @Date 2022-8-23 - * @Author rch - */ -@Slf4j -@Validated -@RequestMapping("/api/dhAddCar") -@RestController -@Api(tags = "回调:敦煌加购-影刀回调") -public class DhAddCarCallBackController { - - @Resource - private CtApplyService ctApplyService; - @Resource - private YdQuartzService ydQuartzService; - @Resource - private DhAddCarService dhAddCarService; - @Resource - private DhAddCarOrderService dhAddCarOrderService; - @Resource - private RedisUtils redisUtils; - @Resource - private CtBuyerService ctBuyerService; - /** - * 敦煌加购-影刀回调 - */ - @ApiOperation("敦煌加购-影刀回调") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 3700, message = "影刀回调参数空值异常!"), - @ApiResponse(code = 3701, message = "影刀回调鉴权异常!") - }) - @Log(value = "敦煌加购-影刀回调") - @PostMapping("/callback") - @AnonymousAccess - @Transactional(rollbackFor = Exception.class) - public Dto callback(@Valid @RequestBody String data, HttpServletRequest httpServletRequest){ - - // 根据task枚举获取 应用信息 取出 accessKey 和 accessKeySecret 用于鉴权 - YdCallBackUtil ydCallBackUtil = new YdCallBackUtil(); - CtApply ctApply = ctApplyService.getApplyByTaskAndMethod(TaskInfoEnum.DH_ADD_CAR_FARMING.getTaskName(), TaskInfoEnum.DH_ADD_CAR_FARMING.getMethodName()); - Dto dto = ydCallBackUtil.callback(httpServletRequest, ctApply, data); - if (!dto.success(dto)) { - return dto; - } - - // 执行自己的业务逻辑 - log.info("============敦煌加购回调鉴权完成 开始执行对应的定时业务逻辑================begin="); - log.info("回调======data:" + data); - // 获取自己想要的数据 - ReturnObje returnObje = JSONUtil.toBean(data, ReturnObje.class); - // job ID - String jobUuid = returnObje.getJobUuid(); - - // TODO 回调会重试 这里注意保证幂等 - // TODO 所以需要对接方在业务层面保障幂等(可以根据jobUuid或者taskUuid进行幂等保障,视startJob时是指定应用和机器人模式还是指定任务模式) - String keyJobUuid = PublicConstant.getJobUuidKeyPrefix(jobUuid); - if (!redisUtils.setIfAbsent(keyJobUuid, DateUtil.now())) { - log.info("-敦煌加购回调接口-幂等性:keyJobUuid:" + keyJobUuid); - return Dto.returnResult(true); - } - - log.info("====returnObje====:{}", JSONUtil.toJsonStr(returnObje)); - JobQueryByUuidReturn jobQueryByUuidReturn = ydQuartzService.queryJobUuid(returnObje.getJobUuid(), ctApply.getAccessKeyId(), ctApply.getAccessKeySecret()); - log.info("====jobQueryByUuidReturn====:{}", JSONUtil.toJsonStr(jobQueryByUuidReturn)); - List inputsList = jobQueryByUuidReturn.getData().getRobotParams().getInputs(); - // 获取id - String id = null; - String buyerName = null; - for (ResultObj resultObj:inputsList) { - if ("id".equals(resultObj.getName())) { - id = resultObj.getValue(); - } - if ("account".equals(resultObj.getName())) { - buyerName = resultObj.getValue(); - } - } - - Integer status = DhAddCarStatusEnum.ADD_CARD_FAILE.value(); - if ("finish".equals(jobQueryByUuidReturn.getData().getStatus())) { - status = DhAddCarStatusEnum.Add_CARD_SUCCESS.value(); - } - - // 执行失败 - Boolean resultBoolean = false; - if (ObjectUtil.isNotEmpty(id)) { - DhAddCar dhAddCar = new DhAddCar(); - dhAddCar.setId(Long.valueOf(id)); - - // 获取买家信息并修改买家信息 - CtBuyer ctBuyer = ctBuyerService.getBuyerOccupyStatusLock(buyerName); - if (ObjectUtil.isNotEmpty(ctBuyer) && BuyerOccupyStatusEnum.OCCUPIED.value().equals(ctBuyer.getOccupyStatus())) { - ctBuyer.setOccupyStatus(BuyerOccupyStatusEnum.UN_OCCUPIED.value()); - resultBoolean = ctBuyerService.updateById(ctBuyer); - } - - if (resultBoolean) { - dhAddCar.setStatus(status); - if (ClickFarmingStatusEnum.EXECUTION_FAILE.value().equals(status)) { - dhAddCar.setResponse(jobQueryByUuidReturn.getData().getRemark()); - }else { - dhAddCar.setResponse(jobQueryByUuidReturn.getData().getStatusName()); - } - resultBoolean = dhAddCarService.updateById(dhAddCar); - } - } - - log.info("============敦煌加购回调鉴权完成 开始执行对应的定时业务逻辑================end==="); - return Dto.returnResult(resultBoolean); - } -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/DhCarOrderCallBackController.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/DhCarOrderCallBackController.java deleted file mode 100644 index 3cc8364..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/DhCarOrderCallBackController.java +++ /dev/null @@ -1,170 +0,0 @@ -package me.zhengjie.modules.group.controller.callbcak; - -import cn.hutool.core.date.DateUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.json.JSONUtil; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.annotation.AnonymousAccess; -import me.zhengjie.annotation.Log; -import me.zhengjie.constant.PublicConstant; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.*; -import me.zhengjie.entity.quartz.JobQueryByUuidReturn; -import me.zhengjie.enums.BuyerOccupyStatusEnum; -import me.zhengjie.enums.ClickOrderStatusEnum; -import me.zhengjie.enums.DhAddCarStatusEnum; -import me.zhengjie.enums.TaskInfoEnum; -import me.zhengjie.service.CtApplyService; -import me.zhengjie.service.CtBuyerService; -import me.zhengjie.service.DhAddCarOrderService; -import me.zhengjie.service.YdQuartzService; -import me.zhengjie.utils.RedisUtils; -import me.zhengjie.utils.YdCallBackUtil; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; -import javax.validation.Valid; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * @Description - * 敦煌加购好评定时任务回调逻辑 - * 回调需要鉴权,鉴权是根据 accesskey accessKeySrect - * 我们应用确认之后 accesskey 和 Srect是确定的 - * - * @Date 2022-8-23 - * @Author rch - */ -@Slf4j -@Validated -@RequestMapping("/api/dhCarOrder") -@RestController -@Api(tags = "回调:敦煌加购好评-影刀回调") -public class DhCarOrderCallBackController { - - @Resource - private CtApplyService ctApplyService; - @Resource - private YdQuartzService ydQuartzService; - @Resource - private DhAddCarOrderService dhAddCarOrderService; - @Resource - private RedisUtils redisUtils; - @Resource - private CtBuyerService ctBuyerService; - - /** - * 速卖通刷单好评-好评回调 - */ - @ApiOperation("速卖通刷单好评-好评回调") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 3700, message = "影刀回调参数空值异常!"), - @ApiResponse(code = 3701, message = "影刀回调鉴权异常!") - }) - @Log(value = "敦煌加购好评-好评回调") - @PostMapping("/callback") - @AnonymousAccess - @Transactional(rollbackFor = Exception.class) - public Dto callback(@Valid @RequestBody String data, HttpServletRequest httpServletRequest){ - - // 根据task枚举获取 应用信息 取出 accessKey 和 accessKeySecret 用于鉴权 - YdCallBackUtil ydCallBackUtil = new YdCallBackUtil(); - CtApply ctApply = ctApplyService.getApplyByTaskAndMethod(TaskInfoEnum.DH_WELL_RECEIVED.getTaskName(), TaskInfoEnum.DH_WELL_RECEIVED.getMethodName()); - Dto dto = ydCallBackUtil.callback(httpServletRequest, ctApply, data); - if (!dto.success(dto)) { - return dto; - } - - // 执行自己的业务逻辑 - log.info("============刷单回调鉴权完成 开始执行对应的定时业务逻辑================begin="); - log.info("回调======data:" + data); - // 获取自己想要的数据 - ReturnObje returnObje = JSONUtil.toBean(data, ReturnObje.class); - // job ID - String jobUuid = returnObje.getJobUuid(); - - // TODO 回调会重试 这里注意保证幂等 - // TODO 所以需要对接方在业务层面保障幂等(可以根据jobUuid或者taskUuid进行幂等保障,视startJob时是指定应用和机器人模式还是指定任务模式) - String keyJobUuid = PublicConstant.getJobUuidKeyPrefix(jobUuid); - if (!redisUtils.setIfAbsent(keyJobUuid, DateUtil.now())) { - log.info("-刷单回调接口-幂等性:keyJobUuid:" + keyJobUuid); - return Dto.returnResult(true); - } - - log.info("====returnObje====:{}", JSONUtil.toJsonStr(returnObje)); - JobQueryByUuidReturn jobQueryByUuidReturn = ydQuartzService.queryJobUuid(returnObje.getJobUuid(), ctApply.getAccessKeyId(), ctApply.getAccessKeySecret()); - log.info("====jobQueryByUuidReturn====:{}", JSONUtil.toJsonStr(jobQueryByUuidReturn)); - List inputsList = jobQueryByUuidReturn.getData().getRobotParams().getInputs(); - // 获取id - String id = null; - String buyerName = null; - for (ResultObj resultObj:inputsList) { - if ("id".equals(resultObj.getName())) { - id = resultObj.getValue(); - } - - if ("account".equals(resultObj.getName())) { - buyerName = resultObj.getValue(); - } - } - - Integer status = ClickOrderStatusEnum.EXECUTION_FAILE.value(); - if ("finish".equals(jobQueryByUuidReturn.getData().getStatus())) { - status = ClickOrderStatusEnum.EXECUTION_SUCCESS.value(); - } - - // 执行失败 - Boolean resultBoolean = false; - if (ObjectUtil.isNotEmpty(id)) { - DhAddCarOrder dhAddCarOrder = new DhAddCarOrder(); - dhAddCarOrder.setId(Long.valueOf(id)); - dhAddCarOrder.setStatus(status); - - // 获取买家信息并修改买家信息 - CtBuyer ctBuyer = ctBuyerService.getBuyerOccupyStatusLock(buyerName); - if (ObjectUtil.isNotEmpty(ctBuyer) && BuyerOccupyStatusEnum.OCCUPIED.value().equals(ctBuyer.getOccupyStatus())) { - ctBuyer.setOccupyStatus(BuyerOccupyStatusEnum.UN_OCCUPIED.value()); - resultBoolean = ctBuyerService.updateById(ctBuyer); - } - - // TODO 需要更新的字段 从这里获取影刀返回的 然后接着设置到 对应的 基础信息里 - List outputsList = jobQueryByUuidReturn.getData().getRobotParams().getOutputs(); - if (ObjectUtil.isNotEmpty(outputsList)) { - Map resultObjMap = outputsList.stream().collect(Collectors.toMap(ResultObj::getName, ResultObj::getValue)); - if (ObjectUtil.isNotEmpty(resultObjMap.containsKey("receipt"))) { - dhAddCarOrder.setPaymentResults(resultObjMap.get("receipt")); - if ("success".equals(resultObjMap.get("receipt"))) { - status = ClickOrderStatusEnum.EXECUTION_SUCCESS.value(); - } - } else { - status = ClickOrderStatusEnum.EXECUTION_FAILE.value(); - } - } else { - status = DhAddCarStatusEnum.CATCH_ORDER_FAILE.value(); - } - - // TODO 需要更新的字段 从这里获取影刀返回的 然后接着设置到 对应的 基础信息里 - if (resultBoolean) { - dhAddCarOrder.setStatus(status); - resultBoolean = dhAddCarOrderService.updateById(dhAddCarOrder); - } - } - - log.info("============刷单回调鉴权完成 开始执行对应的定时业务逻辑================end==="); - return Dto.returnResult(resultBoolean); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/DhCatchOrderCallBackController.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/DhCatchOrderCallBackController.java deleted file mode 100644 index bc9fc22..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/controller/callbcak/DhCatchOrderCallBackController.java +++ /dev/null @@ -1,166 +0,0 @@ -package me.zhengjie.modules.group.controller.callbcak; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.date.DateUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.json.JSONUtil; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.annotation.AnonymousAccess; -import me.zhengjie.annotation.Log; -import me.zhengjie.constant.PublicConstant; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.*; -import me.zhengjie.entity.quartz.JobQueryByUuidReturn; -import me.zhengjie.enums.BuyerOccupyStatusEnum; -import me.zhengjie.enums.DhAddCarStatusEnum; -import me.zhengjie.enums.OrderTypeEnum; -import me.zhengjie.enums.TaskInfoEnum; -import me.zhengjie.service.*; -import me.zhengjie.utils.RedisUtils; -import me.zhengjie.utils.YdCallBackUtil; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; -import javax.validation.Valid; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * @Description - * 敦煌-加购-抓单定时任务回调逻辑 - * 回调需要鉴权,鉴权是根据 accesskey accessKeySrect - * 我们应用确认之后 accesskey 和 Srect是确定的 - * - * @Date 2022-8-23 - * @Author rch - */ -@Slf4j -@Validated -@RequestMapping("/api/catchOrder") -@RestController -@Api(tags = "回调:敦煌抓单-影刀回调") -public class DhCatchOrderCallBackController { - - @Resource - private CtApplyService ctApplyService; - @Resource - private YdQuartzService ydQuartzService; - @Resource - private DhAddCarService dhAddCarService; - @Resource - private DhAddCarOrderService dhAddCarOrderService; - @Resource - private RedisUtils redisUtils; - @Resource - private CtBuyerService ctBuyerService; - - /** - * 敦煌-加购抓单-影刀回调 - */ - @ApiOperation("敦煌-加购抓单-影刀回调") - @ApiResponses(value = { - @ApiResponse(code = 200, message = "响应成功"), - @ApiResponse(code = 2000, message = "服务器开小差了....,请稍后再试!"), - @ApiResponse(code = 3700, message = "影刀回调参数空值异常!"), - @ApiResponse(code = 3701, message = "影刀回调鉴权异常!") - }) - @Log(value = "敦煌-加购抓单-影刀回调") - @PostMapping("/callback") - @AnonymousAccess - @Transactional(rollbackFor = Exception.class) - public Dto callback(@Valid @RequestBody String data, HttpServletRequest httpServletRequest){ - - // 根据task枚举获取 应用信息 取出 accessKey 和 accessKeySecret 用于鉴权 - YdCallBackUtil ydCallBackUtil = new YdCallBackUtil(); - CtApply ctApply = ctApplyService.getApplyByTaskAndMethod(TaskInfoEnum.DH_ADD_CAR_CATCH_ORDER.getTaskName(), TaskInfoEnum.DH_ADD_CAR_CATCH_ORDER.getMethodName()); - Dto dto = ydCallBackUtil.callback(httpServletRequest, ctApply, data); - if (!dto.success(dto)) { - return dto; - } - - // 执行自己的业务逻辑 - log.info("============刷单回调鉴权完成 开始执行对应的定时业务逻辑================begin="); - log.info("回调======data:" + data); - // 获取自己想要的数据 - ReturnObje returnObje = JSONUtil.toBean(data, ReturnObje.class); - // job ID - String jobUuid = returnObje.getJobUuid(); - - // TODO 回调会重试 这里注意保证幂等 - // TODO 所以需要对接方在业务层面保障幂等(可以根据jobUuid或者taskUuid进行幂等保障,视startJob时是指定应用和机器人模式还是指定任务模式) - String keyJobUuid = PublicConstant.getJobUuidKeyPrefix(jobUuid); - if (!redisUtils.setIfAbsent(keyJobUuid, DateUtil.now())) { - log.info("-刷单回调接口-幂等性:keyJobUuid:" + keyJobUuid); - return Dto.returnResult(true); - } - - log.info("====returnObje====:{}", JSONUtil.toJsonStr(returnObje)); - JobQueryByUuidReturn jobQueryByUuidReturn = ydQuartzService.queryJobUuid(returnObje.getJobUuid(), ctApply.getAccessKeyId(), ctApply.getAccessKeySecret()); - log.info("====jobQueryByUuidReturn====:{}", JSONUtil.toJsonStr(jobQueryByUuidReturn)); - List inputsList = jobQueryByUuidReturn.getData().getRobotParams().getInputs(); - // 获取id - String id = null; - String buyerName = null; - for (ResultObj resultObj:inputsList) { - if ("id".equals(resultObj.getName())) { - id = resultObj.getValue(); - } - - if ("account".equals(resultObj.getName())) { - buyerName = resultObj.getValue(); - } - } - - Integer status = DhAddCarStatusEnum.CATCH_ORDER_FAILE.value(); - if ("finish".equals(jobQueryByUuidReturn.getData().getStatus())) { - status = DhAddCarStatusEnum.CATCH_ORDER_SUCCESS.value(); - } - - Boolean resultBoolean = false; - if (ObjectUtil.isNotEmpty(id)) { - DhAddCar dhAddCar = new DhAddCar(); - dhAddCar.setId(Long.valueOf(id)); - - // 获取买家信息并修改买家信息 - CtBuyer ctBuyer = ctBuyerService.getBuyerOccupyStatusLock(buyerName); - if (ObjectUtil.isNotEmpty(ctBuyer) && BuyerOccupyStatusEnum.OCCUPIED.value().equals(ctBuyer.getOccupyStatus())) { - ctBuyer.setOccupyStatus(BuyerOccupyStatusEnum.UN_OCCUPIED.value()); - resultBoolean = ctBuyerService.updateById(ctBuyer); - } - - // TODO 需要更新的字段 从这里获取影刀返回的 然后接着设置到 对应的 基础信息里 - List outputsList = jobQueryByUuidReturn.getData().getRobotParams().getOutputs(); - if (ObjectUtil.isNotEmpty(outputsList)) { - Map resultObjMap = outputsList.stream().collect(Collectors.toMap(ResultObj::getName, ResultObj::getValue)); - DhAddCarOrder dhAddCarOrder = BeanUtil.mapToBean(resultObjMap, DhAddCarOrder.class, false); - if (ObjectUtil.isNotEmpty(dhAddCarOrder)) { - // 设置订单 公司 平台信息 - dhAddCarOrder.setType(OrderTypeEnum.CLICK_FARMING.value()); - if (dhAddCarOrderService.save(dhAddCarOrder)) { - dhAddCarOrder.setAddCarId(Long.valueOf(id)); - } - } - } else { - status = DhAddCarStatusEnum.CATCH_ORDER_FAILE.value(); - } - - dhAddCar.setResponse(jobQueryByUuidReturn.getData().getStatusName()); - dhAddCar.setStatus(status); - resultBoolean = dhAddCarService.updateById(dhAddCar); - } - - log.info("============敦煌-加购抓单-回调鉴权完成 开始执行对应的定时业务逻辑================end==="); - return Dto.returnResult(resultBoolean); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtApplyAddDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtApplyAddDTO.java deleted file mode 100644 index 5f665af..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtApplyAddDTO.java +++ /dev/null @@ -1,57 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotNull; - -/** - * 应用信息(ct_apply)新增 DTO - * - * Author zhw - * Data 2022-07-23 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel(description="添加应用信息") -public class CtApplyAddDTO { - - /** 应用名称 */ - @NotNull - @ApiModelProperty(value = "应用名称", required = true) - private String name; - - /** 任务名称 */ - @NotNull - @ApiModelProperty(value = "任务名称", required = true) - private String taskName; - - /** 方法名称 */ - @ApiModelProperty(value = "方法名称") - private String methodName; - - /** accessKeyId */ - @NotNull - @ApiModelProperty(value = "accessKeyId", required = true) - private String accessKeyId; - - /** accessKeySecret */ - @NotNull - @ApiModelProperty(value = "accessKeySecret", required = true) - private String accessKeySecret; - - /** 应用id */ - @NotNull - @ApiModelProperty(value = "应用id", required = true) - private String robotUuid; - - /** 备注 */ - @NotNull - @ApiModelProperty(value = "备注", required = true) - private String remark; - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtApplyListDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtApplyListDTO.java deleted file mode 100644 index 4347328..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtApplyListDTO.java +++ /dev/null @@ -1,43 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.dto.PageDTO; -import me.zhengjie.entity.CtApply; - - -/** - * @Description 分页查询 应用信息 - * @Date 2022/7/23 - * @Author zhw - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("查询用户") -public class CtApplyListDTO extends PageDTO { - - /** 应用名称 */ - @ApiModelProperty(value = "应用名称") - private String name; - /** 应用id */ - @ApiModelProperty(value = "应用id") - private String robotUuid; - - public Wrapper getWrapper(){ - QueryWrapper qw = new QueryWrapper<>(); - qw - .like(ObjectUtil.isNotEmpty(name),"name",name) - .like(ObjectUtil.isNotEmpty(robotUuid),"robot_uuid", robotUuid) - .orderBy(ObjectUtil.isNotEmpty(getSort()),isAsc(),getSort()) - .orderByDesc("id") - ; - return qw; - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtApplyUpdateDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtApplyUpdateDTO.java deleted file mode 100644 index f5476ce..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtApplyUpdateDTO.java +++ /dev/null @@ -1,54 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotNull; - -/** - * 应用信息(ct_apply)修改 DTO - * - * Author zhw - * Data 2022-07-23 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("修改应用") -public class CtApplyUpdateDTO { - - @NotNull - @ApiModelProperty(value = "id", required = true) - private Long id; - - /** 应用名称 */ - @ApiModelProperty(value = "应用名称") - private String name; - - /** 任务名称 */ - @ApiModelProperty(value = "任务名称") - private String taskName; - - /** 方法名称 */ - @ApiModelProperty(value = "方法名称") - private String methodName; - - /** accessKeyId */ - @ApiModelProperty(value = "accessKeyId") - private String accessKeyId; - - /** accessKeySecret */ - @ApiModelProperty(value = "accessKeySecret") - private String accessKeySecret; - - /** 应用id */ - @ApiModelProperty(value = "应用id") - private String robotUuid; - - /** 备注 */ - @ApiModelProperty(value = "备注") - private String remark; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtBrowseAddDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtBrowseAddDTO.java deleted file mode 100644 index f99b236..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtBrowseAddDTO.java +++ /dev/null @@ -1,33 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotNull; - -/** - * 浏览收藏信息 DTO - * - * @author rch - * @create 2022-11-04 - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("新增浏览收藏") -public class CtBrowseAddDTO { - - /** 买家ID */ - @NotNull - @ApiModelProperty(value = "买家ID", required = true) - private Long buyerId; - - /** 收藏链接 */ - @NotNull - @ApiModelProperty(value = "收藏链接", required = true) - private String linkUrl; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtBrowseListDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtBrowseListDTO.java deleted file mode 100644 index 7b8a80e..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtBrowseListDTO.java +++ /dev/null @@ -1,57 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; -import me.zhengjie.dto.PageDTO; -import me.zhengjie.entity.CtBuyer; -import me.zhengjie.enums.ClickBrowseStatusEnum; -import me.zhengjie.enums.ClickFarmingStatusEnum; -import me.zhengjie.enums.ClickOrderStatusEnum; - -import java.util.Arrays; -import java.util.Date; - - -/** - * @Description 分页查询 浏览刷单 - * @Date 2022-11-04 - * @Author rch - */ -@Data -@ApiModel("分页查询浏览刷单") -public class CtBrowseListDTO extends PageDTO { - - /** 账号 */ - @ApiModelProperty(value = "账号") - private String account; - - /** 收藏链接 */ - @ApiModelProperty(value = "收藏链接") - private String linkUrl; - - /** 状态 1.待执行 2.执行中 3.执行成功 4.执行失败 */ - @ApiModelProperty(value = "状态 1.待执行 2.执行中 3.执行成功 4.执行失败", allowableValues = "1,2,3,4") - private Integer status; - - @ApiModelProperty(value = "是否是仅查询可以执行的浏览收藏") - private Integer inStatusList; - - public Wrapper getWrapper() { - QueryWrapper qw = new QueryWrapper(); - qw - .eq(ObjectUtil.isNotEmpty(account), "ctBuyer.account", account) - .eq(ObjectUtil.isNotEmpty(linkUrl), "ctBrowse.link_url", linkUrl) - .eq(ObjectUtil.isNotEmpty(status), "ctBrowse.status", status) - .in(ObjectUtil.isNotEmpty(inStatusList), "ctBrowse.status", Arrays.asList(ClickBrowseStatusEnum.TOBE_EXECUTION.value(), ClickBrowseStatusEnum.EXECUTION_FAILE.value())) - .orderBy(ObjectUtil.isNotEmpty(getSort()), isAsc(), getSort()) - .orderByDesc("ctBrowse.updated_at") - ; - - return qw; - } - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtBrowseUpdateDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtBrowseUpdateDTO.java deleted file mode 100644 index 3859d1a..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtBrowseUpdateDTO.java +++ /dev/null @@ -1,46 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.Max; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotNull; - - -/** - * 修改浏览收藏 - * - * @author rch - * @create 2022-11-04 - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("修改浏览收藏") -public class CtBrowseUpdateDTO { - - @NotNull - @ApiModelProperty(value = "id") - private Long id; - - /** 买家ID */ - @ApiModelProperty(value = "买家ID") - private Long buyerId; - - /** 收藏链接 */ - @ApiModelProperty(value = "收藏链接") - private String linkUrl; - - /** 状态描述 */ - @ApiModelProperty(value = "状态描述") - private String paymentResults; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtBuyerAddDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtBuyerAddDTO.java deleted file mode 100644 index 97ed46d..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtBuyerAddDTO.java +++ /dev/null @@ -1,135 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.Max; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotNull; - -/** - * 买家信息 DTO - * - * @author rch - * @create 2022-06-22 - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("新增买家") -public class CtBuyerAddDTO { - - /** 昵称*/ - @NotNull - @ApiModelProperty(value = "昵称", required = true) - private String nickName; - - /** 账号*/ - @NotNull - @ApiModelProperty(value = "账号", required = true) - private String account; - - /** 密码*/ - @NotNull - @ApiModelProperty(value = "密码", required = true) - private String pwd; - - /** 公司id */ - @NotNull - @ApiModelProperty(value = "公司id", required = true) - private Long companyId; - - /** 平台id */ - @NotNull - @ApiModelProperty(value = "平台id", required = true) - private Integer platformId; - - ////////////////////////////////////// 新增字段 - /** 国家 */ - @NotNull - @ApiModelProperty(value = "国家", required = true) - private String contntryShort; - - /** VPN_ID(导入excel里包含) */ - @NotNull - @ApiModelProperty(value = "VPN_ID", required = true) - private Long vpnId; - - /** 信用卡ID */ - @ApiModelProperty(value = "信用卡ID", required = true) - private Long cardId; - - /** 用户等级(导入默认内部账号) 1.普通 2.精品 3.压力 4.内部账号 */ - @NotNull - @Min(1) - @Max(4) - @ApiModelProperty(value = "用户等级(导入默认内部账号) 1.普通 2.精品 3.压力 4.内部账号", required = true, allowableValues = "1,2,3,4") - private Integer level; - - /** 占用状态 1.已占用 2.未占用 */ - @NotNull - @Min(1) - @Max(2) - @ApiModelProperty(value = "占用状态 1.已占用 2.未占用", required = true, allowableValues = "1,2") - private Integer occupyStatus; - - /** 状态(导入默认正常) 1.待注册 2待验证 3.待完善 4.正常 5.异常 6.可用但已用 7.删除 */ - @NotNull - @Min(1) - @Max(7) - @ApiModelProperty(value = "状态(导入默认正常) 1.待注册 2待验证 3.待完善 4.正常 5.异常 6.可用但已用 7.删除", required = true, allowableValues = "1,2,3,4,5,6,7") - private Integer status; - - // ==================地址信息相关========================================begin - /** 地址1 */ - @NotNull - @ApiModelProperty(value = "地址1", required = true) - private String addressline1; - - /** 国家 */ - @NotNull - @ApiModelProperty(value = "国家", required = true) - private String country; - - /** 州 */ - @NotNull - @ApiModelProperty(value = "州", required = true) - private String state; - - /** 电话 */ - @NotNull - @ApiModelProperty(value = "电话", required = true) - private String tel; - - /** lastname */ - @NotNull - @ApiModelProperty(value = "lastname", required = true) - private String lastname; - - /** 税号 */ - @ApiModelProperty(value = "税号") - private String vatNumber; - - /** 城市 */ - @NotNull - @ApiModelProperty(value = "城市", required = true) - private String city; - - /** 地址2 */ - @ApiModelProperty(value = "地址2") - private String addressline2; - - /** firstname */ - @NotNull - @ApiModelProperty(value = "firstname", required = true) - private String firstname; - - /** 邮政编码 */ - @NotNull - @ApiModelProperty(value = "邮政编码", required = true) - private String postalcode; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtBuyerListDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtBuyerListDTO.java deleted file mode 100644 index 9c6dc08..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtBuyerListDTO.java +++ /dev/null @@ -1,57 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; -import me.zhengjie.dto.PageDTO; -import me.zhengjie.entity.CtBuyer; - - -/** - * @Description 分页查询 买家信息 - * @Date 2022-06-22 - * @Author rch - */ -@Data -@ApiModel("查询买家") -public class CtBuyerListDTO extends PageDTO { - - /** 昵称*/ - @ApiModelProperty(value = "昵称") - private String nickName; - - /** 账号*/ - @ApiModelProperty(value = "账号") - private String account; - - /** 姓名 */ - @ApiModelProperty(value = "姓名") - private String pwd; - - /** 平台id */ - @ApiModelProperty(value = "平台id") - private Integer platformId; - - /** 公司id */ - @ApiModelProperty(value = "公司id") - private Long companyId; - - public Wrapper getWrapper() { - QueryWrapper qw = new QueryWrapper(); - qw - .eq(ObjectUtil.isNotEmpty(platformId), "t1.platform_id", platformId) - .eq(ObjectUtil.isNotEmpty(companyId), "t1.company_id", companyId) - .like(ObjectUtil.isNotEmpty(nickName), "t1.nick_name", nickName) - .like(ObjectUtil.isNotEmpty(account), "t1.account", account) - .like(ObjectUtil.isNotEmpty(pwd), "t1.pwd", pwd) - .orderBy(ObjectUtil.isNotEmpty(getSort()), isAsc(), getSort()) - .orderByDesc("updated_at") - ; - - return qw; - } - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtBuyerUpdateDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtBuyerUpdateDTO.java deleted file mode 100644 index 9bd28c2..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtBuyerUpdateDTO.java +++ /dev/null @@ -1,122 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.Max; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotNull; - - -/** - * 修改 买家 - * - * @author rch - * @create 2022-06-22 - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("编辑买家") -public class CtBuyerUpdateDTO { - - @NotNull - @ApiModelProperty(value = "Id", required = true) - private Integer id; - - /** 公司id */ - @ApiModelProperty(value = "公司id") - private Long companyId; - - /** 平台id */ - @ApiModelProperty(value = "平台id") - private Integer platformId; - - /** 昵称 */ - @ApiModelProperty(value = "昵称") - private String nickName; - - /** 账号 */ - @ApiModelProperty(value = "账号") - private String account; - - /** 密码 */ - @ApiModelProperty(value = "密码") - private String pwd; - - ////////////////////////////////////// 新增字段 - /** 国家 */ - @ApiModelProperty(value = "国家") - private String contntryShort; - - /** VPN_ID(导入excel里包含) */ - @ApiModelProperty(value = "VPN_ID") - private Long vpnId; - - /** 信用卡ID */ - @ApiModelProperty(value = "信用卡ID") - private Long cardId; - - /** 用户等级(导入默认内部账号) 1.普通 2.精品 3.压力 4.内部账号 */ - @Min(1) - @Max(4) - @ApiModelProperty(value = "用户等级(导入默认内部账号) 1.普通 2.精品 3.压力 4.内部账号", allowableValues = "1,2,3,4") - private Integer level; - - /** 占用状态 1.已占用 2.未占用 */ - @Min(1) - @Max(2) - @ApiModelProperty(value = "占用状态 1.已占用 2.未占用", allowableValues = "1,2") - private Integer occupyStatus; - - /** 状态(导入默认正常) 1.待注册 2待验证 3.待完善 4.正常 5.异常 6.可用但已用 7.删除 */ - @Min(1) - @Max(7) - @ApiModelProperty(value = "状态(导入默认正常) 1.待注册 2待验证 3.待完善 4.正常 5.异常 6.可用但已用 7.删除", allowableValues = "1,2,3,4,5,6,7") - private Integer status; - - // ==================地址信息相关========================================begin - /** 地址1 */ - @ApiModelProperty(value = "地址1") - private String addressline1; - - /** 国家 */ - @ApiModelProperty(value = "国家") - private String country; - - /** 州 */ - @ApiModelProperty(value = "州") - private String state; - - /** 电话 */ - @ApiModelProperty(value = "电话") - private String tel; - - /** lastname */ - @ApiModelProperty(value = "lastname") - private String lastname; - - /** 税号 */ - @ApiModelProperty(value = "税号") - private String vatNumber; - - /** 城市 */ - @ApiModelProperty(value = "城市") - private String city; - - /** 地址2 */ - @ApiModelProperty(value = "地址2") - private String addressline2; - - /** firstname */ - @ApiModelProperty(value = "firstname") - private String firstname; - - /** 邮政编码 */ - @ApiModelProperty(value = "邮政编码") - private String postalcode; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtCardAddDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtCardAddDTO.java deleted file mode 100644 index 8cba632..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtCardAddDTO.java +++ /dev/null @@ -1,105 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.Max; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import java.util.Date; - -/** - * 信用卡信息 DTO - * - * @author rch - * @create 2022-07-09 - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("新增信用卡") -public class CtCardAddDTO { - - /** 父ID */ - // private Long parentId; - - /** 卡号 */ - @NotBlank - @ApiModelProperty(value = "卡号", required = true) - private String number; - -// /** PIN码 */ -// @NotBlank -// @ApiModelProperty(value = "PIN码", required = true) -// private String pinNumber; - - /** 持卡人姓氏 */ - @NotBlank - @ApiModelProperty(value = "持卡人姓氏", required = true) - private String holderSurname; - - /** 持卡人名称 */ - @NotBlank - @ApiModelProperty(value = "持卡人名称", required = true) - private String holderName; - - /** 有效期 */ - @NotBlank - private String termOfValidity; - - /** 开卡日期 */ - // private Date openDate; - - /** 所属国家 */ - @ApiModelProperty(value = "所属国家", required = true) - private String contntryShort; - - /** 信用卡类型 1.Payoneer 2.万事达虚拟卡 3.Visa信用卡 */ - @NotNull - @Min(1) - @Max(3) - @ApiModelProperty(value = "信用卡类型 1.Payoneer 2.万事达虚拟卡 3.Visa信用卡", required = true, allowableValues = "1,2,3") - private Integer type; - - /** 所属厂商:1.AmzKeys 2.Airwallex */ - @NotNull - @Min(1) - @Max(2) - @ApiModelProperty(value = "所属厂商:1.AmzKeys 2.Airwallex", required = true, allowableValues = "1,2") - private Integer cardDealer; - - /** 身份证号 */ - // private String idNumber; - - /** 省份 */ - // private String province; - - /** 城市 */ - // private String country; - - /** 地址 */ - // private String address; - - /** 手机号 */ - // private String phone; - - /** 邮箱 */ - // private String email; - - /** 登陆账号 */ - // private String account; - - /** 密码 */ - @ApiModelProperty(value = "密码", required = true) - @NotNull - private String pwd; - - /** 备注 */ - @ApiModelProperty(value = "备注") - private String remarks; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtCardListDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtCardListDTO.java deleted file mode 100644 index bcb8320..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtCardListDTO.java +++ /dev/null @@ -1,62 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; -import me.zhengjie.dto.PageDTO; -import me.zhengjie.entity.CtBuyer; - - -/** - * @Description 分页查询 信用卡 - * @Date 2022-07-9 - * @Author rch - */ -@Data -@ApiModel("分页查询信用卡") -public class CtCardListDTO extends PageDTO { - - /** 卡号 */ - @ApiModelProperty(value = "卡号") - private String number; - - /** PIN码 */ - @ApiModelProperty(value = "PIN码") - private String pinNumber; - - /** 持卡人名称 */ - @ApiModelProperty(value = "持卡人名称") - private String holderName; - - /** 信用卡类型 1.Payoneer 2.万事达虚拟卡 3.Visa信用卡 */ - @ApiModelProperty(value = "信用卡类型 1.Payoneer 2.万事达虚拟卡 3.Visa信用卡", allowableValues = "1,2,3") - private Integer type; - - /** 所属厂商:1.AmzKeys 2.Airwallex */ - @ApiModelProperty(value = "所属厂商:1.AmzKeys 2.Airwallex", allowableValues = "1,2") - private Integer cardDealer; - - /** 状态:1.正常、2.异常、3.已删除 */ - @ApiModelProperty(value = "状态:1.正常、2.异常、3.已删除", allowableValues = "1,2,3") - private Integer status; - - public Wrapper getWrapper() { - QueryWrapper qw = new QueryWrapper(); - qw - .eq(ObjectUtil.isNotEmpty(type), "type", type) - .eq(ObjectUtil.isNotEmpty(cardDealer), "card_dealer", cardDealer) - .eq(ObjectUtil.isNotEmpty(status), "status", status) - .like(ObjectUtil.isNotEmpty(number), "number", number) - .like(ObjectUtil.isNotEmpty(pinNumber), "pin_number", pinNumber) - .like(ObjectUtil.isNotEmpty(holderName), "holder_name", holderName) - .orderBy(ObjectUtil.isNotEmpty(getSort()), isAsc(), getSort()) - .orderByDesc("updated_at") - ; - - return qw; - } - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtCardUpdateDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtCardUpdateDTO.java deleted file mode 100644 index c63831c..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtCardUpdateDTO.java +++ /dev/null @@ -1,75 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.Max; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotNull; - - -/** - * 修改信用卡 - * - * @author rch - * @create 2022-06-22 - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("修改信用卡") -public class CtCardUpdateDTO { - - @NotNull - @ApiModelProperty(value = "Id", required = true) - private Integer id; - - /** 卡号 */ - @ApiModelProperty(value = "卡号") - private String number; - -// /** PIN码 */ -// @ApiModelProperty(value = "PIN码") -// private String pinNumber; - - /** 持卡人姓氏 */ - @ApiModelProperty(value = "持卡人姓氏") - private String holderSurname; - - /** 持卡人名称 */ - @ApiModelProperty(value = "持卡人名称") - private String holderName; - - /** 有效期 */ - @ApiModelProperty(value = "有效期") - private String termOfValidity; - - /** 所属国家 */ - @ApiModelProperty(value = "所属国家") - private String contntryShort; - - /** 信用卡类型 1.Payoneer 2.万事达虚拟卡 3.Visa信用卡 */ - @Min(1) - @Max(3) - @ApiModelProperty(value = "信用卡类型 1.Payoneer 2.万事达虚拟卡 3.Visa信用卡", required = true, allowableValues = "1,2,3") - private Integer type; - - /** 所属厂商:1.AmzKeys 2.Airwallex */ - @Min(1) - @Max(2) - @ApiModelProperty(value = "所属厂商:1.AmzKeys 2.Airwallex", required = true, allowableValues = "1,2") - private Integer cardDealer; - - /** 密码 */ - @NotNull - @ApiModelProperty(value = "密码", required = true) - private String pwd; - - /** 备注 */ - @ApiModelProperty(value = "备注") - private String remarks; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtClickFarmingAddDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtClickFarmingAddDTO.java deleted file mode 100644 index 3ec971a..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtClickFarmingAddDTO.java +++ /dev/null @@ -1,83 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import io.swagger.models.auth.In; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; - -/** - * 刷单信息 DTO - * - * @author rch - * @create 2022-07-09 - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("新增刷单信息") -public class CtClickFarmingAddDTO { - - @NotNull - /** 买家id */ - @ApiModelProperty(value = "买家id", required = true) - private Long buyerId; - - /** 店铺名称 */ - @ApiModelProperty(value = "店铺名称", required = true) - private String shopName; - - /** 刷单类型 */ - @NotNull - @ApiModelProperty(value = "商品属性类型:1.关键词 2.链接", required = true, allowableValues = "1,2") - private Integer paramsType; - - /** 关键词 */ - @ApiModelProperty(value = "关键词", required = true) - private String keyWord; - - /** 标题 */ - @ApiModelProperty(value = "标题", required = true) - private String title; - - /** 链接 */ - @ApiModelProperty(value = "链接", required = true) - private String link; - - /** 数量 */ - @ApiModelProperty(value = "数量", required = true) - private Integer number; - - /** 规格 */ - @ApiModelProperty(value = "规格") - private String specification; - - /** 颜色 */ - @ApiModelProperty(value = "颜色") - private String color; - - /** item */ - @ApiModelProperty(value = "item", required = true) - private String item; - - @ApiModelProperty(value = "exchange") - private String exchange; - - /** 最小价格区间 */ - @ApiModelProperty(value = "最小价格区间") - private String sectionMin; - - /** 最大价格区间 */ - @ApiModelProperty(value = "最大价格区间") - private String sectionMax; - - /** 留言 */ - @NotBlank - @ApiModelProperty(value = "留言", required = true) - private String amessage; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtClickFarmingDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtClickFarmingDTO.java deleted file mode 100644 index 5827d9b..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtClickFarmingDTO.java +++ /dev/null @@ -1,87 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; -import me.zhengjie.dto.PageDTO; -import me.zhengjie.entity.CtBuyer; -import me.zhengjie.enums.ClickFarmingStatusEnum; - -import java.util.Arrays; -import java.util.List; - - -/** - * @Description 分页查询 刷单信息 - * @Date 2022-07-9 - * @Author rch - */ -@Data -@ApiModel("分页查询刷单信息") -public class CtClickFarmingDTO extends PageDTO { - - /** 关键词 */ - @ApiModelProperty(value = "关键词") - private String keyWord; - - /** Item */ - @ApiModelProperty(value = "Item") - private String item; - - /** 店铺名称 */ - @ApiModelProperty(value = "店铺名称") - private String shopName; - -// /** 刷单类型 */ -// private Integer type; - /** 刷单类型 */ - private Integer paramsType; - /** 国家 */ - private String country; - /** 账号 */ - private String account; - -// /** 平台类型 2.速卖通 1.敦煌*/ -// private Integer platformId; - - /** 状态 1.待执行 2.执行中 3.执行成功 4.执行失败 5.代付款 */ - @ApiModelProperty(value = "状态 1.待执行 2.执行中 3.执行成功 4.执行失败 5.代付款", allowableValues = "1,2,3,4,5") - private Integer status; - - @ApiModelProperty(value = "") - private List inStatusList; - - /** 支付订单ID */ - @ApiModelProperty(value = "支付订单ID") - private String payOrderId; - -// @ApiModelProperty(value = "是否是抓单 1.是 0.否") // ct_click_order_id -// private Integer inCatchorder; - - public Wrapper getWrapper() { - QueryWrapper qw = new QueryWrapper(); - qw -// .eq(ObjectUtil.isNotEmpty(type), "farming.type", type) - .eq(ObjectUtil.isNotEmpty(paramsType), "farming.params_type", paramsType) - .eq(ObjectUtil.isNotEmpty(country), "buyer.contntry_short", country) - .eq(ObjectUtil.isNotEmpty(account), "buyer.account", account) -// .eq(ObjectUtil.isNotEmpty(platformId), "buyer.platform_id", platformId) - .eq(ObjectUtil.isNotEmpty(status), "farming.status", status) -// .isNull(ObjectUtil.isNotEmpty(inCatchorder), "farming.ct_click_order_id") - .in(ObjectUtil.isNotEmpty(inStatusList), "farming.status", Arrays.asList(ClickFarmingStatusEnum.TOBE_EXECUTION.value(), ClickFarmingStatusEnum.EXECUTION_FAILE.value())) -// .in(ObjectUtil.isNotEmpty(inCatchorder), "farming.status", Arrays.asList(ClickFarmingStatusEnum.EXECUTION_SUCCESS.value(), ClickFarmingStatusEnum.EXECUTION_FAILE.value())) - .like(ObjectUtil.isNotEmpty(keyWord), "farming.key_word", keyWord) - .like(ObjectUtil.isNotEmpty(item), "farming.item", item) - .like(ObjectUtil.isNotEmpty(shopName), "farming.shop_name", shopName) - .like(ObjectUtil.isNotEmpty(payOrderId), "clickOrder.order_id", payOrderId) - .orderBy(ObjectUtil.isNotEmpty(getSort()), isAsc(), getSort()) - .orderByDesc("updated_at") - ; - - return qw; - } - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtClickFarmingEditDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtClickFarmingEditDTO.java deleted file mode 100644 index a10d747..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtClickFarmingEditDTO.java +++ /dev/null @@ -1,84 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; - -/** - * 刷单信息 DTO - * - * @author rch - * @create 2022-07-09 - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("刷单信息") -public class CtClickFarmingEditDTO { - - @NotNull - @ApiModelProperty(value = "Id", required = true) - private Long id; - - @ApiModelProperty(value = "buyerId") - @NotNull - private Long buyerId; - - /** 刷单类型 */ - @NotNull - @ApiModelProperty(value = "商品属性类型:1.关键词 2.链接", required = true, allowableValues = "1,2") - private Integer paramsType; - - /** 店铺名称 */ - @ApiModelProperty(value = "店铺名称") - private String shopName; - - /** 关键词 */ - @ApiModelProperty(value = "关键词") - private String keyWord; - - /** 标题 */ - @ApiModelProperty(value = "标题") - private String title; - - /** 链接 */ - @ApiModelProperty(value = "链接") - private String link; - - /** 数量 */ - @ApiModelProperty(value = "数量") - private Integer number; - - /** 规格 */ - @ApiModelProperty(value = "规格") - private String specification; - - /** 颜色 */ - @ApiModelProperty(value = "颜色") - private String color; - - /** item */ - @ApiModelProperty(value = "item") - private String item; - - @ApiModelProperty(value = "exchange") - private String exchange; - - /** 最小价格区间 */ - @ApiModelProperty(value = "最小价格区间") - private String sectionMin; - - /** 最大价格区间 */ - @ApiModelProperty(value = "最大价格区间") - private String sectionMax; - - /** 留言 */ - @ApiModelProperty(value = "留言") - private String amessage; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtClickOrderAddDto.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtClickOrderAddDto.java deleted file mode 100644 index 1e35345..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtClickOrderAddDto.java +++ /dev/null @@ -1,71 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotNull; - -/** - * 刷单-订单评论信息 - * - * @author rch - * @since 2022-10-20 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("新增刷单订单评论") -public class CtClickOrderAddDto { - - /** 公司ID */ - @NotNull - @ApiModelProperty(value = "公司ID", required = true) - private Long companyId; - - /** 总金额 */ - @NotNull - @ApiModelProperty(value = "总金额", required = true) - private String amount; - - /** 状态描述 */ - @NotNull - @ApiModelProperty(value = "状态描述", required = true) - private String paymentResults; - - /** 店铺名称 */ - @NotNull - @ApiModelProperty(value = "店铺名称", required = true) - private String shop; - - /** 购买数量 */ - @NotNull - @ApiModelProperty(value = "购买数量", required = true) - private String pricesNumber; - - /** 订单id */ - @NotNull - @ApiModelProperty(value = "订单id", required = true) - private String orderId; - - /** 商品名称 */ - @NotNull - @ApiModelProperty(value = "商品名称", required = true) - private String shopName; - - /** 时间 */ - @NotNull - @ApiModelProperty(value = "时间", required = true) - private String orderDate; - - /** 评论 */ - @ApiModelProperty(value = "评论") - private String comment; - - /** 图片地址 */ - @ApiModelProperty(value = "图片地址") - private String paths; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtClickOrderCommentDto.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtClickOrderCommentDto.java deleted file mode 100644 index 19fb974..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtClickOrderCommentDto.java +++ /dev/null @@ -1,34 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotNull; - -/** - * 刷单-订单评论信息 - * - * @author rch - * @since 2022-10-20 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("新增评论") -public class CtClickOrderCommentDto { - /** 刷单订单id */ - @NotNull - @ApiModelProperty(value = "Id", required = true) - private Long id; - - /** 评论信息 */ - @ApiModelProperty(value = "评论信息") - private String comment; - - /** 图片地址 */ - @ApiModelProperty(value = "图片地址") - private String paths; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtClickOrderListDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtClickOrderListDTO.java deleted file mode 100644 index 6751a07..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtClickOrderListDTO.java +++ /dev/null @@ -1,69 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; -import me.zhengjie.dto.PageDTO; -import me.zhengjie.entity.CtClickOrder; - - -/** - * @Description 分页查询 刷单订单信息 - * @Date 2022-06-22 - * @Author rch - */ -@Data -@ApiModel("分页查询刷单订单") -public class CtClickOrderListDTO extends PageDTO { - - /** 店铺 */ - @ApiModelProperty(value = "店铺") - private String shop; - - /** 订单id */ - @ApiModelProperty(value = "订单id") - private String orderId; - - /** 公司id */ - @ApiModelProperty(value = "公司id") - private Long companyId; - - /** 类型 */ - @ApiModelProperty(value = "类型") - private Integer type; - - /** 状态 1.待执行 2.执行中 3.执行成功 4.执行失败 */ - @ApiModelProperty(value = "状态 1.待执行 2.执行中 3.执行成功 4.执行失败", allowableValues = "1,2,3,4") - private Integer status; - - /** 开始时间 */ - @ApiModelProperty(value = "开始时间") - private String sTime; - - /** 结束时间 */ - @ApiModelProperty(value = "结束时间") - private String eTime; - - @ApiModelProperty(value = "是否评论") - private Boolean commentBoolean; - - public Wrapper getWrapper() { - QueryWrapper qw = new QueryWrapper(); - qw - .eq(ObjectUtil.isNotEmpty(companyId), "company.id", companyId) - .eq(ObjectUtil.isNotEmpty(status), "clickOrder.status", status) - .eq(ObjectUtil.isNotEmpty(type), "clickOrder.type", type) - .isNotNull((ObjectUtil.isNotEmpty(commentBoolean) && commentBoolean), "comment") - .like(ObjectUtil.isNotEmpty(shop), "clickOrder.shop", shop) - .like(ObjectUtil.isNotEmpty(orderId), "clickOrder.order_id", orderId) - .between(ObjectUtil.isNotEmpty(sTime) && ObjectUtil.isNotEmpty(eTime), "clickOrder.created_at", sTime, eTime) - .orderByDesc("created_at") - ; - - return qw; - } - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtClickOrderSupplementDto.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtClickOrderSupplementDto.java deleted file mode 100644 index 16043a3..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtClickOrderSupplementDto.java +++ /dev/null @@ -1,58 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotNull; - -/** - * 刷单-订单信息手动补录 - * - * @author rch - * @since 2022-10-15 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("补录订单信息") -public class CtClickOrderSupplementDto { - /** 刷单id */ - @NotNull - @ApiModelProperty(value = "刷单id", required = true) - private Long clickFarmingId; - - /** 总金额 */ - @NotNull - @ApiModelProperty(value = "总金额", required = true) - private String amount; - - /** 状态描述 */ - @NotNull - @ApiModelProperty(value = "状态描述", required = true) - private String paymentResults; - - /** 店铺名称 */ - @NotNull - @ApiModelProperty(value = "店铺名称", required = true) - private String shop; - - /** 购买数量 */ - @NotNull - @ApiModelProperty(value = "购买数量", required = true) - private String pricesNumber; - - /** 订单id */ - @ApiModelProperty(value = "订单id") - private String orderId; - - /** 商品名称 */ - @ApiModelProperty(value = "商品名称") - private String shopName; - - /** 时间 */ - @ApiModelProperty(value = "时间") - private String orderDate; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtCompanyAddDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtCompanyAddDTO.java deleted file mode 100644 index dfad073..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtCompanyAddDTO.java +++ /dev/null @@ -1,29 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 公司信息 DTO - * - * @author rch - * @create 2022-06-28 - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtCompanyAddDTO { - - /** 名称 */ - private String name; - /** 地址 */ - private String address; - /** 电话 */ - private String phone; - - // 下面这两个需要新增的时候生成 - /** 商户码(公司调用api公司唯一标识) */ - /** 商户token(公司调用api公司token身份标识) */ -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtCompanyListDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtCompanyListDTO.java deleted file mode 100644 index 72aa00a..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtCompanyListDTO.java +++ /dev/null @@ -1,47 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import lombok.Data; -import me.zhengjie.dto.PageDTO; -import me.zhengjie.entity.CtBuyer; - - -/** - * @Description 分页查询 公司信息 - * @Date 2022-06-28 - * @Author rch - */ -@Data -public class CtCompanyListDTO extends PageDTO { - /** 名称 */ - private String name; - /** 电话 */ - private String phone; - /** 地址 */ - private String address; - /** 商户码(公司调用api公司唯一标识) */ - private String number; - /** 商户token(公司调用api公司token身份标识) */ - private String token; - - /** 操作人账号*/ - private String gmName; - - public Wrapper getWrapper() { - QueryWrapper qw = new QueryWrapper(); - qw - .like(ObjectUtil.isNotEmpty(name), "name", name) - .like(ObjectUtil.isNotEmpty(phone), "phone", phone) - .like(ObjectUtil.isNotEmpty(address), "address", address) - .like(ObjectUtil.isNotEmpty(number), "number", number) - .like(ObjectUtil.isNotEmpty(token), "token", token) - .orderBy(ObjectUtil.isNotEmpty(getSort()), isAsc(), getSort()) - .orderByDesc("updated_at") - ; - - return qw; - } - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtCompanyUpdateDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtCompanyUpdateDTO.java deleted file mode 100644 index 0309484..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtCompanyUpdateDTO.java +++ /dev/null @@ -1,30 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotNull; - - -/** - * 修改 买家 - * - * @author rch - * @create 2022-06-22 - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtCompanyUpdateDTO { - - @NotNull - private Integer id; - /** 名称 */ - private String name; - /** 地址 */ - private String address; - /** 电话 */ - private String phone; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtDhPayAddDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtDhPayAddDTO.java deleted file mode 100644 index 22d3499..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtDhPayAddDTO.java +++ /dev/null @@ -1,30 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Pattern; - -/** - * 敦煌支付信息 DTO - * - * @author rch - * @create 2022-07-09 - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtDhPayAddDTO { - - /** 买家名称 */ - @NotBlank - private String buyerName; - - /** 支付订单ID(敦煌的) */ - @NotBlank - @Pattern(regexp = "^[0-9]+(,[0-9]+)*$", message = "订单编号不符合要求") - private String orderId; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtDhPayListDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtDhPayListDTO.java deleted file mode 100644 index 3f3fa01..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtDhPayListDTO.java +++ /dev/null @@ -1,39 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import lombok.Data; -import me.zhengjie.dto.PageDTO; -import me.zhengjie.entity.CtBuyer; - - -/** - * @Description 分页查询 敦煌支付信息 - * @Date 2022-07-28 - * @Author rch - */ -@Data -public class CtDhPayListDTO extends PageDTO { - - /** 买家名称 */ - private String buyerName; - /** 支付订单ID(敦煌的) */ - private String orderId; - /** 状态 0.待处理 1.支付成功 2.支付失败 3.删除*/ - private Integer status; - - public Wrapper getWrapper() { - QueryWrapper qw = new QueryWrapper(); - qw - .eq(ObjectUtil.isNotEmpty(status), "status", status) - .like(ObjectUtil.isNotEmpty(buyerName), "buyer_name", buyerName) - .like(ObjectUtil.isNotEmpty(orderId), "order_id", orderId) - .orderBy(ObjectUtil.isNotEmpty(getSort()), isAsc(), getSort()) - .orderByDesc("updated_at") - ; - - return qw; - } - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtExcelAddDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtExcelAddDTO.java deleted file mode 100644 index 891b5f4..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtExcelAddDTO.java +++ /dev/null @@ -1,27 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotNull; - -/** - * Excel 导入信息(CtExcel)表实体类 DTO - * - * @author rch - * @since 2022-06-23 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtExcelAddDTO{ - - /** 备注 */ - @NotNull - private String remarks; - - /** excel路径 */ - @NotNull - private String path; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtExcelImportInfoListDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtExcelImportInfoListDTO.java deleted file mode 100644 index 582100c..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtExcelImportInfoListDTO.java +++ /dev/null @@ -1,41 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import lombok.Data; -import me.zhengjie.dto.PageDTO; -import me.zhengjie.entity.CtBuyer; - - -/** - * @Description 分页查询 买家信息 - * @Date 2022-06-22 - * @Author rch - */ -@Data -public class CtExcelImportInfoListDTO extends PageDTO { - - /** 公司主键 */ - private Long companyId; - - /** 鉴权枚举 */ - private Integer tokenEnum; - - /** 状态 1.待处理 2.处理成功 3.处理失败 */ - private Integer status; - - public Wrapper getWrapper() { - QueryWrapper qw = new QueryWrapper(); - qw - .eq(ObjectUtil.isNotEmpty(companyId), "company_id", companyId) - .eq(ObjectUtil.isNotEmpty(tokenEnum), "token_enum", tokenEnum) - .eq(ObjectUtil.isNotEmpty(status), "status", status) - .orderBy(ObjectUtil.isNotEmpty(getSort()), isAsc(), getSort()) - .orderByDesc("updated_at") - ; - - return qw; - } - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtExcelListDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtExcelListDTO.java deleted file mode 100644 index e51b0f5..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtExcelListDTO.java +++ /dev/null @@ -1,40 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.dto.PageDTO; -import me.zhengjie.entity.CtExcel; - -/** - * Excel 导入信息(CtExcel)表实体类 DTO - * - * @author rch - * @since 2022-06-23 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtExcelListDTO extends PageDTO { - - /** 备注 */ - private String remarks; - - /** 状态1.待处理 2.已处理 */ - private Integer status; - - public Wrapper getWrapper() { - QueryWrapper qw = new QueryWrapper(); - qw - .like(ObjectUtil.isNotEmpty(remarks), "remarks", remarks) - .eq(ObjectUtil.isNotEmpty(status), "status", status) - .orderBy(ObjectUtil.isNotEmpty(getSort()), isAsc(), getSort()) - .orderByDesc("updated_at") - ; - - return qw; - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtExcelUpdateDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtExcelUpdateDTO.java deleted file mode 100644 index 0dbd06b..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtExcelUpdateDTO.java +++ /dev/null @@ -1,27 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotNull; - - -/** - * 修改 Excel - * - * @author rch - * @create 2022-06-22 - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtExcelUpdateDTO { - - @NotNull - private Integer id; - - /** 备注 */ - private String remarks; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtOrderListDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtOrderListDTO.java deleted file mode 100644 index 75ce756..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtOrderListDTO.java +++ /dev/null @@ -1,42 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import lombok.Data; -import me.zhengjie.dto.PageDTO; -import me.zhengjie.entity.CtBuyer; - - -/** - * @Description 分页查询 订单信息 - * @Date 2022-07-01 - * @Author rch - */ -@Data -public class CtOrderListDTO extends PageDTO { - - /** 公司Id */ - private Long companyId; - /** ExcelId 信息 */ - private Long excelInfoId; - /** 我们平台订单编号 */ - private String ctOrderNo; - /** 订单号,下单成功响应的订单号(冗余字段 下单成功响应订单信息里有) */ - private Long orderNo; - - public Wrapper getWrapper() { - QueryWrapper qw = new QueryWrapper(); - qw - .eq(ObjectUtil.isNotEmpty(companyId), "company_id", companyId) - .eq(ObjectUtil.isNotEmpty(excelInfoId), "excel_info_id", excelInfoId) - .eq(ObjectUtil.isNotEmpty(ctOrderNo), "ct_order_no", ctOrderNo) - .eq(ObjectUtil.isNotEmpty(orderNo), "order_no", orderNo) - .orderBy(ObjectUtil.isNotEmpty(getSort()), isAsc(), getSort()) - .orderByDesc("updated_at") - ; - - return qw; - } - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtPlatformAddDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtPlatformAddDTO.java deleted file mode 100644 index 88a1c82..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtPlatformAddDTO.java +++ /dev/null @@ -1,25 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 平台信息 DTO - * - * @author rch - * @create 2022-06-23 - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtPlatformAddDTO { - - /** 名称 */ - private String name; - /** 地址 */ - private String address; - /** 电话 */ - private String phone; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtPlatformListDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtPlatformListDTO.java deleted file mode 100644 index a7d71a9..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtPlatformListDTO.java +++ /dev/null @@ -1,39 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import lombok.Data; -import me.zhengjie.dto.PageDTO; -import me.zhengjie.entity.CtPlatform; - - -/** - * @Description 分页查询 平台信息 - * @Date 2022-06-23 - * @Author rch - */ -@Data -public class CtPlatformListDTO extends PageDTO { - - /** 名称 */ - private String name; - /** 地址 */ - private String address; - /** 电话 */ - private String phone; - - public Wrapper getWrapper() { - QueryWrapper qw = new QueryWrapper(); - qw - .like(ObjectUtil.isNotEmpty(name), "name", name) - .like(ObjectUtil.isNotEmpty(address), "address", address) - .like(ObjectUtil.isNotEmpty(phone), "phone", phone) - .orderBy(ObjectUtil.isNotEmpty(getSort()), isAsc(), getSort()) - .orderByDesc("updated_at") - ; - - return qw; - } - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtPlatformUpdateDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtPlatformUpdateDTO.java deleted file mode 100644 index e04fcd9..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtPlatformUpdateDTO.java +++ /dev/null @@ -1,31 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotNull; - - -/** - * 修改 平台信息 - * - * @author rch - * @create 2022-06-22 - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtPlatformUpdateDTO { - - @NotNull - private Integer id; - - /** 名称 */ - private String name; - /** 地址 */ - private String address; - /** 电话 */ - private String phone; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtRebotAddDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtRebotAddDTO.java deleted file mode 100644 index 0e58d38..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtRebotAddDTO.java +++ /dev/null @@ -1,26 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotNull; - -/** - * 影刀机器人(ct_rebot) 新增DTO - * - * @Author zhw - * @Date 2022-07-23 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtRebotAddDTO { - - /** 机器人账号 */ - @NotNull - private String accountName; - /** 机器人Uuid信息 */ - @NotNull - private String robotClientUuid; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtRebotListDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtRebotListDTO.java deleted file mode 100644 index 3393a56..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtRebotListDTO.java +++ /dev/null @@ -1,42 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.dto.PageDTO; -import me.zhengjie.entity.CtRebot; - -/** - * 影刀机器人 分页查询DTO - * - * @Author zhw - * @Date 2022-07-23 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtRebotListDTO extends PageDTO { - - /** 机器人账号 */ - private String accountName; - /** 机器人Uuid信息 */ - private String robotClientUuid; - - public Wrapper getWrapper(){ - QueryWrapper qw = new QueryWrapper<>(); - qw - .like(ObjectUtil.isNotEmpty(accountName),"account_name",accountName) - .like(ObjectUtil.isNotEmpty(robotClientUuid),"robot_client_uuid",robotClientUuid) - .orderBy(ObjectUtil.isNotEmpty(getSort()),isAsc(),getSort()) - .orderByDesc("id") - ; - return qw; - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtRebotUpdateDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtRebotUpdateDTO.java deleted file mode 100644 index f5b9a4e..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtRebotUpdateDTO.java +++ /dev/null @@ -1,33 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import com.baomidou.mybatisplus.annotation.FieldFill; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotNull; - -/** - * 根据ID修改影刀机器人(ct_rebot) 信息 - * - * @Author zhw - * @Date 2022-07-23 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtRebotUpdateDTO { - - @NotNull - private Long id; - - /** 机器人账号 */ - private String accountName; - /** 机器人Uuid信息 */ - private String robotClientUuid; - /** 任务id(任务id 不为0说明机器被占用) */ - private Integer jobId; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtRebotUpdateStatusDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtRebotUpdateStatusDTO.java deleted file mode 100644 index fba3f4b..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtRebotUpdateStatusDTO.java +++ /dev/null @@ -1,24 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotNull; - -/** - * 根据ID修改影刀机器人(ct_rebot) 状态测试使用 - * - * @Author zhw - * @Date 2022-07-23 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtRebotUpdateStatusDTO { - - @NotNull - private Long id; - - private Integer status; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtVpnAddDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtVpnAddDTO.java deleted file mode 100644 index 4c92a85..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtVpnAddDTO.java +++ /dev/null @@ -1,50 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotNull; - -/** - * @Author zhw - * @Date 2022-07-07 - * @Description Vpn新增DTO - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtVpnAddDTO { - /** 所属国家简称 */ - @NotNull - private String contntryShort; - /** IP地址 */ - @NotNull - private String ipAddress; - /** 父ip地址 */ - @NotNull - private String parentIpAddress; - /** 端口 */ - @NotNull - private Integer port; - /** 名称 */ - @NotNull - private String name; - /** 密码 */ - @NotNull - private String pwd; - /** VPS类型 1.传统 */ - @NotNull - private Integer vpsType; - /** 经销商 1.V2 */ - @NotNull - private Integer dealer; - /** mac地址 */ - @NotNull - public String mac; - /** 链接 */ - private String link; - /** 状态 1.可用 2.禁用 */ - public Integer status;; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtVpnListDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtVpnListDTO.java deleted file mode 100644 index 06348ea..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtVpnListDTO.java +++ /dev/null @@ -1,59 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import lombok.Data; -import me.zhengjie.dto.PageDTO; -import me.zhengjie.entity.CtVpn; - -/** - * @Description 分页查询 VPN信息 - * @Date 2022/7/7 - * @Author zhw - */ -@Data -public class CtVpnListDTO extends PageDTO { - - /** 所属国家简称 */ - private String contntryShort; - /** IP地址 */ - private String ipAddress; - /** 父ip地址 */ - private String parentIpAddress; - /** 端口 */ - private Integer port; - /** 名称 */ - private String name; - /** 密码 */ - private String pwd; - /** VPS类型 1.传统 */ - private Integer vpsType; - /** 经销商 1.V2 */ - private Integer dealer; - /** mac地址 */ - public String mac; - /** 状态 1.可用 2.禁用 */ - public Integer status; - - public Wrapper getWrapper() { - QueryWrapper qw = new QueryWrapper(); - qw - .like(ObjectUtil.isNotEmpty(contntryShort), "contntry_short", contntryShort) - .like(ObjectUtil.isNotEmpty(ipAddress), "ip_address", ipAddress) - .like(ObjectUtil.isNotEmpty(parentIpAddress), "parent_ip_address", parentIpAddress) - .like(ObjectUtil.isNotEmpty(port), "port", port) - .like(ObjectUtil.isNotEmpty(name), "name", name) - .like(ObjectUtil.isNotEmpty(pwd), "pwd", pwd) - .like(ObjectUtil.isNotEmpty(vpsType), "vps_type", vpsType) - .like(ObjectUtil.isNotEmpty(dealer), "dealer", dealer) - .like(ObjectUtil.isNotEmpty(mac), "mac", mac) - .like(ObjectUtil.isNotEmpty(status), "status", status) - .orderBy(ObjectUtil.isNotEmpty(getSort()), isAsc(), getSort()) - .orderByDesc("updated_at") - ; - return qw; - } - - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtVpnUpdateDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtVpnUpdateDTO.java deleted file mode 100644 index cfc9a4e..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/CtVpnUpdateDTO.java +++ /dev/null @@ -1,43 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotNull; - -/** - * @Author zhw - * @Date 2022-07-08 - * @Description VPN信息更新 dto - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -public class CtVpnUpdateDTO { - @NotNull - private Integer id; - /** 所属国家简称 */ - private String contntryShort; - /** IP地址 */ - private String ipAddress; - /** 父ip地址 */ - private String parentIpAddress; - /** 端口 */ - private Integer port; - /** 名称 */ - private String name; - /** 密码 */ - private String pwd; - /** VPS类型 1.传统 */ - private Integer vpsType; - /** 经销商 1.V2 */ - private Integer dealer; - /** mac地址 */ - public String mac; - /** 链接 */ - private String link; - /** 经销商 1.可用 2.禁用 */ - public Integer status; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/DhCarGoodWellReceivedDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/DhCarGoodWellReceivedDTO.java deleted file mode 100644 index 0a7a804..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/DhCarGoodWellReceivedDTO.java +++ /dev/null @@ -1,30 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; - -import javax.validation.constraints.NotNull; - -/** - * - * @Description IdDTO - * @Date 2022-06-22 - * @Author rch - */ -@Data -@ApiModel("敦煌加购好评商品细腻洗") -public class DhCarGoodWellReceivedDTO { - - @NotNull - @ApiModelProperty(value = "id", required = true) - private Long id; - - @NotNull - @ApiModelProperty(value = "评论内容", required = true) - private String comment; - - @NotNull - @ApiModelProperty(value = "图片路径", required = true) - private String paths; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/DhCarWellReceivedDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/DhCarWellReceivedDTO.java deleted file mode 100644 index be59ac0..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/DhCarWellReceivedDTO.java +++ /dev/null @@ -1,29 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; -import org.springframework.validation.annotation.Validated; - -import javax.validation.Valid; -import javax.validation.constraints.NotNull; -import java.util.List; - -/** - * - * @Description IdDTO - * @Date 2022-06-22 - * @Author rch - */ -@Data -@ApiModel("敦煌加购好评") -public class DhCarWellReceivedDTO { - - @NotNull - @ApiModelProperty(value = "id", required = true) - private Long id; - - @Valid - @ApiModelProperty(value = "评论内容", required = true) - private List dialogWellReceivedGoods; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/IdDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/IdDTO.java deleted file mode 100644 index 8304628..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/IdDTO.java +++ /dev/null @@ -1,22 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; - -import javax.validation.constraints.NotNull; - -/** - * - * @Description IdDTO - * @Date 2022-06-22 - * @Author rch - */ -@Data -@ApiModel("IdDto") -public class IdDTO { - - @NotNull - @ApiModelProperty(value = "id", required = true) - private Long id; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/SearchOrderListDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/SearchOrderListDTO.java deleted file mode 100644 index fab304d..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/SearchOrderListDTO.java +++ /dev/null @@ -1,69 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; -import me.zhengjie.dto.PageDTO; -import me.zhengjie.entity.CtClickOrder; - - -/** - * @Description 分页查询 开放刷单订单接口给到ERP - * @Date 2022-11-10 - * @Author rch - */ -@Data -@ApiModel("分页查询刷单订单") -public class SearchOrderListDTO extends PageDTO { - - /** 店铺 */ - @ApiModelProperty(value = "店铺") - private String shop; - - /** 订单id */ - @ApiModelProperty(value = "订单id") - private String orderId; - - /** 公司id */ - @ApiModelProperty(value = "公司id") - private Long companyId; - - /** 类型 */ - @ApiModelProperty(value = "类型") - private Integer type; - - /** 状态 1.待执行 2.执行中 3.执行成功 4.执行失败 */ - @ApiModelProperty(value = "状态 1.待执行 2.执行中 3.执行成功 4.执行失败", allowableValues = "1,2,3,4") - private Integer status; - - /** 开始时间 */ - @ApiModelProperty(value = "开始时间") - private String sTime; - - /** 结束时间 */ - @ApiModelProperty(value = "结束时间") - private String eTime; - - @ApiModelProperty(value = "是否评论") - private Boolean commentBoolean; - - public Wrapper getWrapper() { - QueryWrapper qw = new QueryWrapper(); - qw - .eq(ObjectUtil.isNotEmpty(companyId), "company.id", companyId) - .eq(ObjectUtil.isNotEmpty(status), "clickOrder.status", status) - .eq(ObjectUtil.isNotEmpty(type), "clickOrder.type", type) - .isNotNull((ObjectUtil.isNotEmpty(commentBoolean) && commentBoolean), "comment") - .like(ObjectUtil.isNotEmpty(shop), "clickOrder.shop", shop) - .like(ObjectUtil.isNotEmpty(orderId), "clickOrder.order_id", orderId) - .between(ObjectUtil.isNotEmpty(sTime) && ObjectUtil.isNotEmpty(eTime), "clickOrder.created_at", sTime, eTime) - .orderByDesc("created_at") - ; - - return qw; - } - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/SysQuartzJobAddDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/SysQuartzJobAddDTO.java deleted file mode 100644 index 4c86419..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/SysQuartzJobAddDTO.java +++ /dev/null @@ -1,54 +0,0 @@ -package me.zhengjie.modules.group.dto; - - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotNull; - -/** - * @Description 影刀定时任务新增 DTO - * @Date 2022-07-21 - * @Author zhw - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class SysQuartzJobAddDTO { - - private Long taskNum; - /** 任务名称 */ - @NotNull - private String jobName; - /** 备注 */ - @NotNull - private String description; - /** 应用id:根据应用查找bean名称和方法名称 */ - @NotNull - private Long applyId; - /** cron 表达式 */ - @NotNull - private String cronExpression; - /** 子任务ID */ - private String subTask; - /** 负责人 */ - @NotNull - private String personInCharge; - /** 报警邮箱 */ - private String email; - /** 失败后暂停:1暂停、0启用 */ - @NotNull - private Integer pauseAfterFailure; - /** 状态:1暂停、0启用 */ - @NotNull - private Integer isPause; - /** 参数 */ - @NotNull - private String params; - /** 参数类型 */ - @NotNull - private Integer paramsType; - - private String paramId; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/SysQuartzJobListDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/SysQuartzJobListDTO.java deleted file mode 100644 index fcb02fe..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/SysQuartzJobListDTO.java +++ /dev/null @@ -1,43 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import lombok.Data; -import me.zhengjie.dto.PageDTO; -import me.zhengjie.entity.SysQuartzJob; -import me.zhengjie.enums.TaskTypeEnum; - -/** - * @Description 分页查询 影刀定时任务 - * @Date 2022-07-21 - * @Author zhw - */ -@Data -public class SysQuartzJobListDTO extends PageDTO { - - /** 任务名称 */ - private String jobName; - - /** 是否暂停 */ - private Integer isPause; - - /** 开始时间 */ - private String sTime; - - /** 结束时间 */ - private String eTime; - - public Wrapper getWrapper() { - QueryWrapper qw = new QueryWrapper<>(); - qw - .eq("type", TaskTypeEnum.SHADOW_KNIFE.value()) - .like(ObjectUtil.isNotEmpty(jobName), "job_name", jobName) - .eq(ObjectUtil.isNotEmpty(isPause), "is_pause", isPause) - .between(ObjectUtil.isNotEmpty(sTime) && ObjectUtil.isNotNull(eTime), "create_time", sTime, eTime) - .orderBy(ObjectUtil.isNotEmpty(getSort()), isAsc(), getSort()) - ; - return qw; - } - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/SysQuartzJobUpdateDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/SysQuartzJobUpdateDTO.java deleted file mode 100644 index 2c40feb..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/SysQuartzJobUpdateDTO.java +++ /dev/null @@ -1,49 +0,0 @@ -package me.zhengjie.modules.group.dto; - - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotNull; - - -/** - * @Author zhw - * @Date 2022-07-21 - * @Description 影刀信息更新 dto - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class SysQuartzJobUpdateDTO { - - @NotNull - private Long jobId; - /** 任务名称 */ - private String jobName; - /** 备注 */ - private String description; - /** Spring Bean名称 */ - private String beanName; - /** 方法名称 */ - private String methodName; - /** 应用ID 通过ID查找Bean名称、方法名称 */ - private Long applyId; - /** cron 表达式 */ - private String cronExpression; - /** 子任务ID */ - private String subTask; - /** 负责人 */ - private String personInCharge; - /** 报警邮箱 */ - private String email; - /** 失败后暂停:1暂停、0启用 */ - private Integer pauseAfterFailure; - /** 状态:1暂停、0启用 */ - private Integer isPause; - /** 参数 */ - private String params; - /** 参数类型 */ - private Integer paramsType; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/SysQuartzLogListDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/SysQuartzLogListDTO.java deleted file mode 100644 index 7bb972d..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/SysQuartzLogListDTO.java +++ /dev/null @@ -1,42 +0,0 @@ -package me.zhengjie.modules.group.dto; - -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import lombok.Data; -import me.zhengjie.dto.PageDTO; -import me.zhengjie.entity.SysQuartzLog; -import me.zhengjie.enums.TaskTypeEnum; - - -/** - * @Description 分页查询 影刀定时任务日志 - * @Date 2022-07-9 - * @Author rch - */ -@Data -public class SysQuartzLogListDTO extends PageDTO { - - /** 卡号 */ - private String jobName; - - private Integer isSuccess; - - private String sTime; - - private String eTime; - - public Wrapper getWrapper() { - QueryWrapper qw = new QueryWrapper(); - qw - .eq("type", TaskTypeEnum.SHADOW_KNIFE.value()) - .eq(ObjectUtil.isNotEmpty(isSuccess), "is_success", isSuccess) - .like(ObjectUtil.isNotEmpty(jobName), "job_name", jobName) - .between(ObjectUtil.isNotEmpty(sTime) && ObjectUtil.isNotEmpty(eTime), "create_time", sTime, eTime) - .orderBy(ObjectUtil.isNotEmpty(getSort()), isAsc(), getSort()) - ; - - return qw; - } - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhaddcar/DhAddCarAddDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhaddcar/DhAddCarAddDTO.java deleted file mode 100644 index 098ca04..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhaddcar/DhAddCarAddDTO.java +++ /dev/null @@ -1,46 +0,0 @@ -package me.zhengjie.modules.group.dto.dhaddcar; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.modules.group.dto.dhcargood.DhCarGoodKeyAddDTO; -import me.zhengjie.modules.group.dto.dhcargood.DhCarGoodKeyEditDTO; -import me.zhengjie.modules.group.dto.dhcargood.DhCarGoodLinkAddDTO; -import me.zhengjie.modules.group.dto.dhcargood.DhCarGoodLinkEditDTO; - -import javax.validation.constraints.NotNull; -import java.util.List; - -/** - * 新增敦煌加购 DTO - * - * @author rch - * @create 2022-07-09 - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("新增敦煌加购") -public class DhAddCarAddDTO { - - /** 商品属性类型:1.关键词 2.链接 */ - @NotNull - @ApiModelProperty(value = "商品属性类型:1.关键词 2.链接", required = true, allowableValues = "1,2") - private Integer paramsType; - - /** 买家ID */ - @NotNull - @ApiModelProperty(value = "买家ID", required = true) - private Integer buyerId; - - /** 加购物车商品ids */ - @ApiModelProperty(value = "加购物车商品ids") - private List carGoodKeys; - - /** 加购物车商品ids */ - @ApiModelProperty(value = "加购物车商品ids") - private List carGoodLinks; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhaddcar/DhAddCarEditDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhaddcar/DhAddCarEditDTO.java deleted file mode 100644 index b26d485..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhaddcar/DhAddCarEditDTO.java +++ /dev/null @@ -1,48 +0,0 @@ -package me.zhengjie.modules.group.dto.dhaddcar; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.modules.group.dto.dhcargood.DhCarGoodKeyEditDTO; -import me.zhengjie.modules.group.dto.dhcargood.DhCarGoodLinkEditDTO; - -import javax.validation.constraints.NotNull; -import java.util.List; - -/** - * 修改敦煌加购信息 DTO - * - * @author rch - * @create 2022-07-09 - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("修改敦煌加购信息") -public class DhAddCarEditDTO { - - /** ID */ - @ApiModelProperty(value = "ID", required = true) - private Long id; - - /** 商品属性类型:1.关键词 2.链接 */ - @NotNull - @ApiModelProperty(value = "商品属性类型:1.关键词 2.链接", required = true, allowableValues = "1,2") - private Integer paramsType; - - /** 买家ID */ - @NotNull - @ApiModelProperty(value = "买家ID", required = true) - private Integer buyerId; - - /** 加购物车商品ids */ - @ApiModelProperty(value = "加购物车商品ids") - private List carGoodKeys; - - /** 加购物车商品ids */ - @ApiModelProperty(value = "加购物车商品ids") - private List carGoodLinks; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhaddcar/DhAddCarListDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhaddcar/DhAddCarListDTO.java deleted file mode 100644 index e6a63c1..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhaddcar/DhAddCarListDTO.java +++ /dev/null @@ -1,73 +0,0 @@ -package me.zhengjie.modules.group.dto.dhaddcar; - -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.dto.PageDTO; -import me.zhengjie.entity.CtBuyer; -import me.zhengjie.enums.DhAddCarStatusEnum; - -import java.util.Arrays; - -/** - * 分页查询-敦煌加购-信息 DTO - * - * @author rch - * @create 2022-07-09 - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("新增刷单信息") -public class DhAddCarListDTO extends PageDTO { - - /** 商品属性类型:1.关键词 2.链接 */ - @ApiModelProperty(value = "商品属性类型:1.关键词 2.链接", allowableValues = "1,2") - private Integer paramsType; - - /** 账号 */ - @ApiModelProperty(value = "账号") - private String account; - - /** 账号 */ - @ApiModelProperty(value = "国家") - private String country; - - /** 账号 */ - @ApiModelProperty(value = "1.获取敦煌加购列表(状态:1.待执行 4.加购失败); 2.获取敦煌抓单列表(状态:6.待抓单 9.抓单失败)") - private Integer inStatusList; - - /** 状态 1.待执行 2.执行中 3.加购成功 4.加购失败 5.下单成功 6.支付成功 7.抓单成功 8.抓单失败 */ - @ApiModelProperty(value = "状态 1.待执行 2.执行中 3.加购成功 4.加购失败 5.下单成功 6.支付成功 7.抓单成功 8.抓单失败", allowableValues = "1,2,3,4,5,6,7,8") - private Integer status; - -// /** 加购物车商品ids */ -// @ApiModelProperty(value = "加购物车商品ids") -// private List carGoodKeys; -// -// /** 加购物车商品ids */ -// @ApiModelProperty(value = "加购物车商品ids") -// private List carGoodLinks; - - public Wrapper getWrapper() { - QueryWrapper qw = new QueryWrapper(); - qw - .eq(ObjectUtil.isNotEmpty(paramsType), "dhAddCar.params_type", paramsType) - .eq(ObjectUtil.isNotEmpty(account), "buyer.account", account) - .in(ObjectUtil.isNotEmpty(inStatusList) && inStatusList == 1, "dhAddCar.status", Arrays.asList(DhAddCarStatusEnum.TOBE_EXECUTION.value(), DhAddCarStatusEnum.ADD_CARD_FAILE.value())) - .in(ObjectUtil.isNotEmpty(inStatusList) && inStatusList == 2, "dhAddCar.status", Arrays.asList(DhAddCarStatusEnum.TO_BE_CATCH_ORDER.value(), DhAddCarStatusEnum.CATCH_ORDER_FAILE.value())) - .eq(ObjectUtil.isNotEmpty(status), "dhAddCar.status", status) - .eq(ObjectUtil.isNotEmpty(country), "company.name", country) - .orderBy(ObjectUtil.isNotEmpty(getSort()), isAsc(), getSort()) - .orderByDesc("updated_at") - ; - - return qw; - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhcargood/DhCarGoodKeyAddDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhcargood/DhCarGoodKeyAddDTO.java deleted file mode 100644 index a4d8fb9..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhcargood/DhCarGoodKeyAddDTO.java +++ /dev/null @@ -1,70 +0,0 @@ -package me.zhengjie.modules.group.dto.dhcargood; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Null; - -/** - * 敦煌-加购商品(根据关键词) DTO - * - * @author rch - * @create 2022-07-09 - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("敦煌-加购商品(根据关键词)") -public class DhCarGoodKeyAddDTO { - - /** 商品属性类型:1.关键词 2.链接 */ - @Null - @ApiModelProperty(value = "商品属性类型:1.关键词 2.链接", required = true, allowableValues = "1,2") - private Integer paramsType; - - /** 店铺名称 */ - @NotBlank - @ApiModelProperty(value = "NotBlank", required = true) - private String shopName; - - /** 关键词 */ - @NotBlank - @ApiModelProperty(value = "关键词", required = true) - private String keyWord; - - /** 标题 */ - @NotBlank - @ApiModelProperty(value = "标题", required = true) - private String title; - - /** 数量 */ - @NotBlank - @ApiModelProperty(value = "数量", required = true) - private Integer number; - - /** 规格 */ - @ApiModelProperty(value = "规格") - private String specification; - - /** 颜色 */ - @ApiModelProperty(value = "颜色") - private String color; - - /** item */ - @NotBlank - @ApiModelProperty(value = "item", required = true) - private String item; - - /** 最小价格区间 */ - @ApiModelProperty(value = "最小价格区间") - private String sectionMin; - - /** 最大价格区间 */ - @ApiModelProperty(value = "最大价格区间") - private String sectionMax; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhcargood/DhCarGoodKeyEditDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhcargood/DhCarGoodKeyEditDTO.java deleted file mode 100644 index 3bdadc0..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhcargood/DhCarGoodKeyEditDTO.java +++ /dev/null @@ -1,74 +0,0 @@ -package me.zhengjie.modules.group.dto.dhcargood; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Null; - -/** - * 敦煌-加购商品(根据关键词) DTO - * - * @author rch - * @create 2022-07-09 - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("敦煌-加购商品(根据关键词)") -public class DhCarGoodKeyEditDTO { - - /** ID */ - @ApiModelProperty(value = "ID", required = true) - private Long id; - - /** 商品属性类型:1.关键词 2.链接 */ - @Null - @ApiModelProperty(value = "商品属性类型:1.关键词 2.链接", required = true, allowableValues = "1,2") - private Integer paramsType; - - /** 店铺名称 */ - @NotBlank - @ApiModelProperty(value = "NotBlank", required = true) - private String shopName; - - /** 关键词 */ - @NotBlank - @ApiModelProperty(value = "关键词", required = true) - private String keyWord; - - /** 标题 */ - @NotBlank - @ApiModelProperty(value = "标题", required = true) - private String title; - - /** 数量 */ - @NotBlank - @ApiModelProperty(value = "数量", required = true) - private Integer number; - - /** 规格 */ - @ApiModelProperty(value = "规格") - private String specification; - - /** 颜色 */ - @ApiModelProperty(value = "颜色") - private String color; - - /** item */ - @NotBlank - @ApiModelProperty(value = "item", required = true) - private String item; - - /** 最小价格区间 */ - @ApiModelProperty(value = "最小价格区间") - private String sectionMin; - - /** 最大价格区间 */ - @ApiModelProperty(value = "最大价格区间") - private String sectionMax; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhcargood/DhCarGoodLinkAddDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhcargood/DhCarGoodLinkAddDTO.java deleted file mode 100644 index 5911106..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhcargood/DhCarGoodLinkAddDTO.java +++ /dev/null @@ -1,49 +0,0 @@ -package me.zhengjie.modules.group.dto.dhcargood; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Null; - -/** - * 敦煌-加购商品(根据链接) DTO - * - * @author rch - * @create 2022-07-09 - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("敦煌-加购商品(根据链接)") -public class DhCarGoodLinkAddDTO { - - /** 商品属性类型:1.关键词 2.链接 */ - @Null - @ApiModelProperty(value = "商品属性类型:1.关键词 2.链接", required = true, allowableValues = "1,2") - private Integer paramsType; - - /** 链接 */ - @NotBlank - @ApiModelProperty(value = "链接", required = true) - private String link; - - /** 数量 */ - @NotBlank - @ApiModelProperty(value = "数量", required = true) - private Integer number; - - /** 规格 */ - @NotBlank - @ApiModelProperty(value = "规格", required = true) - private String specification; - - /** 颜色 */ - @NotBlank - @ApiModelProperty(value = "颜色", required = true) - private String color; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhcargood/DhCarGoodLinkEditDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhcargood/DhCarGoodLinkEditDTO.java deleted file mode 100644 index e9c4a4a..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhcargood/DhCarGoodLinkEditDTO.java +++ /dev/null @@ -1,53 +0,0 @@ -package me.zhengjie.modules.group.dto.dhcargood; - -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Null; - -/** - * 敦煌-加购商品(根据链接) DTO - * - * @author rch - * @create 2022-07-09 - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("敦煌-加购商品(根据链接)") -public class DhCarGoodLinkEditDTO { - - /** ID */ - @ApiModelProperty(value = "ID", required = true) - private Long id; - - /** 商品属性类型:1.关键词 2.链接 */ - @Null - @ApiModelProperty(value = "商品属性类型:1.关键词 2.链接", required = true, allowableValues = "1,2") - private Integer paramsType; - - /** 链接 */ - @NotBlank - @ApiModelProperty(value = "链接", required = true) - private String link; - - /** 数量 */ - @NotBlank - @ApiModelProperty(value = "数量", required = true) - private Integer number; - - /** 规格 */ - @NotBlank - @ApiModelProperty(value = "规格", required = true) - private String specification; - - /** 颜色 */ - @NotBlank - @ApiModelProperty(value = "颜色", required = true) - private String color; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhcarorder/DhAddCarOrderListDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhcarorder/DhAddCarOrderListDTO.java deleted file mode 100644 index e3ad0f3..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/group/dto/dhcarorder/DhAddCarOrderListDTO.java +++ /dev/null @@ -1,66 +0,0 @@ -package me.zhengjie.modules.group.dto.dhcarorder; - -import cn.hutool.core.util.ObjectUtil; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.dto.PageDTO; -import me.zhengjie.entity.CtBuyer; -import me.zhengjie.enums.ClickOrderStatusEnum; -import me.zhengjie.enums.DhAddCarStatusEnum; - -import java.util.Arrays; - -/** - * 分页查询-敦煌加购-订单-信息 DTO - * - * @author rch - * @create 2022-07-09 - */ - -@Data -@AllArgsConstructor -@NoArgsConstructor -@ApiModel("敦煌加购订单信息") -public class DhAddCarOrderListDTO extends PageDTO { - - /** 类型: 1.导入 2.刷单 */ - @ApiModelProperty(value = "类型: 1.导入 2.刷单", allowableValues = "1,2") - private Integer type; - - /** 关联敦煌加购的id */ - @ApiModelProperty(value = "关联敦煌加购的id") - private Long addCarId; - - /** 订单id */ - @ApiModelProperty(value = "订单id") - private String orderId; - - /** 好评 */ - @ApiModelProperty(value = "1.获取敦煌好评列表(状态:1.待执行 4.加购失败)") - private Integer inStatusList; - - - /** 状态 1.待执行 2.执行中 3.执行成功 4.执行失败 */ - @ApiModelProperty(value = "状态 1.待执行 2.执行中 3.执行成功 4.执行失败", allowableValues = "1,2,3,4") - private Integer status; - - public Wrapper getWrapper() { - QueryWrapper qw = new QueryWrapper(); - qw - .eq(ObjectUtil.isNotEmpty(type), "type", type) - .eq(ObjectUtil.isNotEmpty(addCarId), "add_car_id", addCarId) - .eq(ObjectUtil.isNotEmpty(orderId), "order_id", orderId) - .eq(ObjectUtil.isNotEmpty(status), "status", status) - .in(ObjectUtil.isNotEmpty(inStatusList) && inStatusList == 1, "status", Arrays.asList(ClickOrderStatusEnum.TOBE_EXECUTION.value(), ClickOrderStatusEnum.EXECUTION_FAILE.value())) - .orderBy(ObjectUtil.isNotEmpty(getSort()), isAsc(), getSort()) - .orderByDesc("updated_at") - ; - - return qw; - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/domain/App.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/domain/App.java deleted file mode 100644 index cf5789c..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/domain/App.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.domain; - -import io.swagger.annotations.ApiModelProperty; -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.bean.copier.CopyOptions; -import lombok.Getter; -import lombok.Setter; -import me.zhengjie.base.BaseEntity; -import javax.persistence.*; -import java.io.Serializable; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -@Entity -@Getter -@Setter -@Table(name="mnt_app") -public class App extends BaseEntity implements Serializable { - - @Id - @Column(name = "app_id") - @ApiModelProperty(value = "ID", hidden = true) - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ApiModelProperty(value = "名称") - private String name; - - @ApiModelProperty(value = "端口") - private int port; - - @ApiModelProperty(value = "上传路径") - private String uploadPath; - - @ApiModelProperty(value = "部署路径") - private String deployPath; - - @ApiModelProperty(value = "备份路径") - private String backupPath; - - @ApiModelProperty(value = "启动脚本") - private String startScript; - - @ApiModelProperty(value = "部署脚本") - private String deployScript; - - public void copy(App source){ - BeanUtil.copyProperties(source,this, CopyOptions.create().setIgnoreNullValue(true)); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/domain/Database.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/domain/Database.java deleted file mode 100644 index 6b3a68a..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/domain/Database.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.domain; - -import io.swagger.annotations.ApiModelProperty; -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.bean.copier.CopyOptions; -import lombok.Getter; -import lombok.Setter; -import me.zhengjie.base.BaseEntity; -import javax.persistence.*; -import java.io.Serializable; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -@Entity -@Getter -@Setter -@Table(name="mnt_database") -public class Database extends BaseEntity implements Serializable { - - @Id - @Column(name = "db_id") - @ApiModelProperty(value = "ID", hidden = true) - private String id; - - @ApiModelProperty(value = "数据库名称") - private String name; - - @ApiModelProperty(value = "数据库连接地址") - private String jdbcUrl; - - @ApiModelProperty(value = "数据库密码") - private String pwd; - - @ApiModelProperty(value = "用户名") - private String userName; - - public void copy(Database source){ - BeanUtil.copyProperties(source,this, CopyOptions.create().setIgnoreNullValue(true)); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/domain/Deploy.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/domain/Deploy.java deleted file mode 100644 index bcf61e5..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/domain/Deploy.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.domain; - -import io.swagger.annotations.ApiModelProperty; -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.bean.copier.CopyOptions; -import lombok.Getter; -import lombok.Setter; -import me.zhengjie.base.BaseEntity; -import javax.persistence.*; -import java.io.Serializable; -import java.util.Set; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -@Entity -@Getter -@Setter -@Table(name="mnt_deploy") -public class Deploy extends BaseEntity implements Serializable { - - @Id - @Column(name = "deploy_id") - @ApiModelProperty(value = "ID", hidden = true) - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ManyToMany - @ApiModelProperty(name = "服务器", hidden = true) - @JoinTable(name = "mnt_deploy_server", - joinColumns = {@JoinColumn(name = "deploy_id",referencedColumnName = "deploy_id")}, - inverseJoinColumns = {@JoinColumn(name = "server_id",referencedColumnName = "server_id")}) - private Set deploys; - - @ManyToOne - @JoinColumn(name = "app_id") - @ApiModelProperty(value = "应用编号") - private App app; - - public void copy(Deploy source){ - BeanUtil.copyProperties(source,this, CopyOptions.create().setIgnoreNullValue(true)); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/domain/DeployHistory.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/domain/DeployHistory.java deleted file mode 100644 index 6e07e13..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/domain/DeployHistory.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.domain; - -import io.swagger.annotations.ApiModelProperty; -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.bean.copier.CopyOptions; -import lombok.Getter; -import lombok.Setter; -import org.hibernate.annotations.CreationTimestamp; -import javax.persistence.*; -import java.io.Serializable; -import java.sql.Timestamp; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -@Entity -@Getter -@Setter -@Table(name="mnt_deploy_history") -public class DeployHistory implements Serializable { - - @Id - @Column(name = "history_id") - @ApiModelProperty(value = "ID", hidden = true) - private String id; - - @ApiModelProperty(value = "应用名称") - private String appName; - - @ApiModelProperty(value = "IP") - private String ip; - - @CreationTimestamp - @ApiModelProperty(value = "部署时间") - private Timestamp deployDate; - - @ApiModelProperty(value = "部署者") - private String deployUser; - - @ApiModelProperty(value = "部署ID") - private Long deployId; - - public void copy(DeployHistory source){ - BeanUtil.copyProperties(source,this, CopyOptions.create().setIgnoreNullValue(true)); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/domain/ServerDeploy.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/domain/ServerDeploy.java deleted file mode 100644 index f523562..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/domain/ServerDeploy.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.domain; - -import io.swagger.annotations.ApiModelProperty; -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.bean.copier.CopyOptions; -import lombok.Getter; -import lombok.Setter; -import me.zhengjie.base.BaseEntity; -import javax.persistence.*; -import java.io.Serializable; -import java.util.Objects; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -@Entity -@Getter -@Setter -@Table(name="mnt_server") -public class ServerDeploy extends BaseEntity implements Serializable { - - @Id - @Column(name = "server_id") - @ApiModelProperty(value = "ID", hidden = true) - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ApiModelProperty(value = "服务器名称") - private String name; - - @ApiModelProperty(value = "IP") - private String ip; - - @ApiModelProperty(value = "端口") - private Integer port; - - @ApiModelProperty(value = "账号") - private String account; - - @ApiModelProperty(value = "密码") - private String password; - - public void copy(ServerDeploy source){ - BeanUtil.copyProperties(source,this, CopyOptions.create().setIgnoreNullValue(true)); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - ServerDeploy that = (ServerDeploy) o; - return Objects.equals(id, that.id) && - Objects.equals(name, that.name); - } - - @Override - public int hashCode() { - return Objects.hash(id, name); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/repository/AppRepository.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/repository/AppRepository.java deleted file mode 100644 index 41e5f5c..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/repository/AppRepository.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.repository; - -import me.zhengjie.modules.mnt.domain.App; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -public interface AppRepository extends JpaRepository, JpaSpecificationExecutor { -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/repository/DatabaseRepository.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/repository/DatabaseRepository.java deleted file mode 100644 index 695e0ad..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/repository/DatabaseRepository.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.repository; - -import me.zhengjie.modules.mnt.domain.Database; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -public interface DatabaseRepository extends JpaRepository, JpaSpecificationExecutor { -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/repository/DeployHistoryRepository.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/repository/DeployHistoryRepository.java deleted file mode 100644 index 3c8980e..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/repository/DeployHistoryRepository.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.repository; - -import me.zhengjie.modules.mnt.domain.DeployHistory; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -public interface DeployHistoryRepository extends JpaRepository, JpaSpecificationExecutor { -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/repository/DeployRepository.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/repository/DeployRepository.java deleted file mode 100644 index 2ea4498..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/repository/DeployRepository.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.repository; - -import me.zhengjie.modules.mnt.domain.Deploy; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -public interface DeployRepository extends JpaRepository, JpaSpecificationExecutor { -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/repository/ServerDeployRepository.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/repository/ServerDeployRepository.java deleted file mode 100644 index 4ca336c..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/repository/ServerDeployRepository.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.repository; - -import me.zhengjie.modules.mnt.domain.ServerDeploy; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -public interface ServerDeployRepository extends JpaRepository, JpaSpecificationExecutor { - - /** - * 根据IP查询 - * @param ip / - * @return / - */ - ServerDeploy findByIp(String ip); -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/rest/AppController.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/rest/AppController.java deleted file mode 100644 index 9b5b08f..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/rest/AppController.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.rest; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import lombok.RequiredArgsConstructor; -import me.zhengjie.annotation.Log; -import me.zhengjie.modules.mnt.domain.App; -import me.zhengjie.modules.mnt.service.AppService; -import me.zhengjie.modules.mnt.service.dto.AppQueryCriteria; -import org.springframework.data.domain.Pageable; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.Set; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -@RestController -@RequiredArgsConstructor -@Api(tags = "运维:应用管理") -@RequestMapping("/api/app") -public class AppController { - - private final AppService appService; - - @ApiOperation("导出应用数据") - @GetMapping(value = "/download") - @PreAuthorize("@el.check('app:list')") - public void download(HttpServletResponse response, AppQueryCriteria criteria) throws IOException { - appService.download(appService.queryAll(criteria), response); - } - - @ApiOperation(value = "查询应用") - @GetMapping - @PreAuthorize("@el.check('app:list')") - public ResponseEntity query(AppQueryCriteria criteria, Pageable pageable){ - return new ResponseEntity<>(appService.queryAll(criteria,pageable),HttpStatus.OK); - } - - @Log("新增应用") - @ApiOperation(value = "新增应用") - @PostMapping - @PreAuthorize("@el.check('app:add')") - public ResponseEntity create(@Validated @RequestBody App resources){ - appService.create(resources); - return new ResponseEntity<>(HttpStatus.CREATED); - } - - @Log("修改应用") - @ApiOperation(value = "修改应用") - @PutMapping - @PreAuthorize("@el.check('app:edit')") - public ResponseEntity update(@Validated @RequestBody App resources){ - appService.update(resources); - return new ResponseEntity<>(HttpStatus.NO_CONTENT); - } - - @Log("删除应用") - @ApiOperation(value = "删除应用") - @DeleteMapping - @PreAuthorize("@el.check('app:del')") - public ResponseEntity delete(@RequestBody Set ids){ - appService.delete(ids); - return new ResponseEntity<>(HttpStatus.OK); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/rest/DatabaseController.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/rest/DatabaseController.java deleted file mode 100644 index 9dfb43c..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/rest/DatabaseController.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.rest; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import lombok.RequiredArgsConstructor; -import me.zhengjie.annotation.Log; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.modules.mnt.domain.Database; -import me.zhengjie.modules.mnt.service.DatabaseService; -import me.zhengjie.modules.mnt.service.dto.DatabaseDto; -import me.zhengjie.modules.mnt.service.dto.DatabaseQueryCriteria; -import me.zhengjie.modules.mnt.util.SqlUtils; -import me.zhengjie.utils.FileUtil; -import org.springframework.data.domain.Pageable; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.File; -import java.io.IOException; -import java.util.Set; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -@Api(tags = "运维:数据库管理") -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/database") -public class DatabaseController { - - private final String fileSavePath = FileUtil.getTmpDirPath()+"/"; - private final DatabaseService databaseService; - - @ApiOperation("导出数据库数据") - @GetMapping(value = "/download") - @PreAuthorize("@el.check('database:list')") - public void download(HttpServletResponse response, DatabaseQueryCriteria criteria) throws IOException { - databaseService.download(databaseService.queryAll(criteria), response); - } - - @ApiOperation(value = "查询数据库") - @GetMapping - @PreAuthorize("@el.check('database:list')") - public ResponseEntity query(DatabaseQueryCriteria criteria, Pageable pageable){ - return new ResponseEntity<>(databaseService.queryAll(criteria,pageable),HttpStatus.OK); - } - - @Log("新增数据库") - @ApiOperation(value = "新增数据库") - @PostMapping - @PreAuthorize("@el.check('database:add')") - public ResponseEntity create(@Validated @RequestBody Database resources){ - databaseService.create(resources); - return new ResponseEntity<>(HttpStatus.CREATED); - } - - @Log("修改数据库") - @ApiOperation(value = "修改数据库") - @PutMapping - @PreAuthorize("@el.check('database:edit')") - public ResponseEntity update(@Validated @RequestBody Database resources){ - databaseService.update(resources); - return new ResponseEntity<>(HttpStatus.NO_CONTENT); - } - - @Log("删除数据库") - @ApiOperation(value = "删除数据库") - @DeleteMapping - @PreAuthorize("@el.check('database:del')") - public ResponseEntity delete(@RequestBody Set ids){ - databaseService.delete(ids); - return new ResponseEntity<>(HttpStatus.OK); - } - - @Log("测试数据库链接") - @ApiOperation(value = "测试数据库链接") - @PostMapping("/testConnect") - @PreAuthorize("@el.check('database:testConnect')") - public ResponseEntity testConnect(@Validated @RequestBody Database resources){ - return new ResponseEntity<>(databaseService.testConnection(resources),HttpStatus.CREATED); - } - - @Log("执行SQL脚本") - @ApiOperation(value = "执行SQL脚本") - @PostMapping(value = "/upload") - @PreAuthorize("@el.check('database:add')") - public ResponseEntity upload(@RequestBody MultipartFile file, HttpServletRequest request)throws Exception{ - String id = request.getParameter("id"); - DatabaseDto database = databaseService.findById(id); - String fileName; - if(database != null){ - fileName = file.getOriginalFilename(); - File executeFile = new File(fileSavePath+fileName); - FileUtil.del(executeFile); - file.transferTo(executeFile); - String result = SqlUtils.executeFile(database.getJdbcUrl(), database.getUserName(), database.getPwd(), executeFile); - return new ResponseEntity<>(result,HttpStatus.OK); - }else{ - throw new BadRequestException("Database not exist"); - } - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/rest/DeployController.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/rest/DeployController.java deleted file mode 100644 index 72b7b3e..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/rest/DeployController.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.rest; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import lombok.RequiredArgsConstructor; -import me.zhengjie.annotation.Log; -import me.zhengjie.modules.mnt.domain.Deploy; -import me.zhengjie.modules.mnt.domain.DeployHistory; -import me.zhengjie.modules.mnt.service.DeployService; -import me.zhengjie.modules.mnt.service.dto.DeployQueryCriteria; -import me.zhengjie.utils.FileUtil; -import org.springframework.data.domain.Pageable; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.File; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.Set; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -@RestController -@Api(tags = "运维:部署管理") -@RequiredArgsConstructor -@RequestMapping("/api/deploy") -public class DeployController { - - private final String fileSavePath = FileUtil.getTmpDirPath()+"/"; - private final DeployService deployService; - - - @ApiOperation("导出部署数据") - @GetMapping(value = "/download") - @PreAuthorize("@el.check('database:list')") - public void download(HttpServletResponse response, DeployQueryCriteria criteria) throws IOException { - deployService.download(deployService.queryAll(criteria), response); - } - - @ApiOperation(value = "查询部署") - @GetMapping - @PreAuthorize("@el.check('deploy:list')") - public ResponseEntity query(DeployQueryCriteria criteria, Pageable pageable){ - return new ResponseEntity<>(deployService.queryAll(criteria,pageable),HttpStatus.OK); - } - - @Log("新增部署") - @ApiOperation(value = "新增部署") - @PostMapping - @PreAuthorize("@el.check('deploy:add')") - public ResponseEntity create(@Validated @RequestBody Deploy resources){ - deployService.create(resources); - return new ResponseEntity<>(HttpStatus.CREATED); - } - - @Log("修改部署") - @ApiOperation(value = "修改部署") - @PutMapping - @PreAuthorize("@el.check('deploy:edit')") - public ResponseEntity update(@Validated @RequestBody Deploy resources){ - deployService.update(resources); - return new ResponseEntity<>(HttpStatus.NO_CONTENT); - } - - @Log("删除部署") - @ApiOperation(value = "删除部署") - @DeleteMapping - @PreAuthorize("@el.check('deploy:del')") - public ResponseEntity delete(@RequestBody Set ids){ - deployService.delete(ids); - return new ResponseEntity<>(HttpStatus.OK); - } - - @Log("上传文件部署") - @ApiOperation(value = "上传文件部署") - @PostMapping(value = "/upload") - @PreAuthorize("@el.check('deploy:edit')") - public ResponseEntity upload(@RequestBody MultipartFile file, HttpServletRequest request)throws Exception{ - Long id = Long.valueOf(request.getParameter("id")); - String fileName = ""; - if(file != null){ - fileName = file.getOriginalFilename(); - File deployFile = new File(fileSavePath+fileName); - FileUtil.del(deployFile); - file.transferTo(deployFile); - //文件下一步要根据文件名字来 - deployService.deploy(fileSavePath+fileName ,id); - }else{ - System.out.println("没有找到相对应的文件"); - } - System.out.println("文件上传的原名称为:"+ Objects.requireNonNull(file).getOriginalFilename()); - Map map = new HashMap<>(2); - map.put("errno",0); - map.put("id",fileName); - return new ResponseEntity<>(map,HttpStatus.OK); - } - @Log("系统还原") - @ApiOperation(value = "系统还原") - @PostMapping(value = "/serverReduction") - @PreAuthorize("@el.check('deploy:edit')") - public ResponseEntity serverReduction(@Validated @RequestBody DeployHistory resources){ - String result = deployService.serverReduction(resources); - return new ResponseEntity<>(result,HttpStatus.OK); - } - @Log("服务运行状态") - @ApiOperation(value = "服务运行状态") - @PostMapping(value = "/serverStatus") - @PreAuthorize("@el.check('deploy:edit')") - public ResponseEntity serverStatus(@Validated @RequestBody Deploy resources){ - String result = deployService.serverStatus(resources); - return new ResponseEntity<>(result,HttpStatus.OK); - } - @Log("启动服务") - @ApiOperation(value = "启动服务") - @PostMapping(value = "/startServer") - @PreAuthorize("@el.check('deploy:edit')") - public ResponseEntity startServer(@Validated @RequestBody Deploy resources){ - String result = deployService.startServer(resources); - return new ResponseEntity<>(result,HttpStatus.OK); - } - @Log("停止服务") - @ApiOperation(value = "停止服务") - @PostMapping(value = "/stopServer") - @PreAuthorize("@el.check('deploy:edit')") - public ResponseEntity stopServer(@Validated @RequestBody Deploy resources){ - String result = deployService.stopServer(resources); - return new ResponseEntity<>(result,HttpStatus.OK); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/rest/DeployHistoryController.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/rest/DeployHistoryController.java deleted file mode 100644 index 49fb694..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/rest/DeployHistoryController.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.rest; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import lombok.RequiredArgsConstructor; -import me.zhengjie.annotation.Log; -import me.zhengjie.modules.mnt.service.DeployHistoryService; -import me.zhengjie.modules.mnt.service.dto.DeployHistoryQueryCriteria; -import org.springframework.data.domain.Pageable; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.Set; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -@RestController -@RequiredArgsConstructor -@Api(tags = "运维:部署历史管理") -@RequestMapping("/api/deployHistory") -public class DeployHistoryController { - - private final DeployHistoryService deployhistoryService; - - @ApiOperation("导出部署历史数据") - @GetMapping(value = "/download") - @PreAuthorize("@el.check('deployHistory:list')") - public void download(HttpServletResponse response, DeployHistoryQueryCriteria criteria) throws IOException { - deployhistoryService.download(deployhistoryService.queryAll(criteria), response); - } - - @ApiOperation(value = "查询部署历史") - @GetMapping - @PreAuthorize("@el.check('deployHistory:list')") - public ResponseEntity query(DeployHistoryQueryCriteria criteria, Pageable pageable){ - return new ResponseEntity<>(deployhistoryService.queryAll(criteria,pageable),HttpStatus.OK); - } - - @Log("删除DeployHistory") - @ApiOperation(value = "删除部署历史") - @DeleteMapping - @PreAuthorize("@el.check('deployHistory:del')") - public ResponseEntity delete(@RequestBody Set ids){ - deployhistoryService.delete(ids); - return new ResponseEntity<>(HttpStatus.OK); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/rest/ServerDeployController.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/rest/ServerDeployController.java deleted file mode 100644 index d4a135b..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/rest/ServerDeployController.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.rest; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import lombok.RequiredArgsConstructor; -import me.zhengjie.annotation.Log; -import me.zhengjie.modules.mnt.domain.ServerDeploy; -import me.zhengjie.modules.mnt.service.ServerDeployService; -import me.zhengjie.modules.mnt.service.dto.ServerDeployQueryCriteria; -import org.springframework.data.domain.Pageable; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.Set; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -@RestController -@Api(tags = "运维:服务器管理") -@RequiredArgsConstructor -@RequestMapping("/api/serverDeploy") -public class ServerDeployController { - - private final ServerDeployService serverDeployService; - - @ApiOperation("导出服务器数据") - @GetMapping(value = "/download") - @PreAuthorize("@el.check('serverDeploy:list')") - public void download(HttpServletResponse response, ServerDeployQueryCriteria criteria) throws IOException { - serverDeployService.download(serverDeployService.queryAll(criteria), response); - } - - @ApiOperation(value = "查询服务器") - @GetMapping - @PreAuthorize("@el.check('serverDeploy:list')") - public ResponseEntity query(ServerDeployQueryCriteria criteria, Pageable pageable){ - return new ResponseEntity<>(serverDeployService.queryAll(criteria,pageable),HttpStatus.OK); - } - - @Log("新增服务器") - @ApiOperation(value = "新增服务器") - @PostMapping - @PreAuthorize("@el.check('serverDeploy:add')") - public ResponseEntity create(@Validated @RequestBody ServerDeploy resources){ - serverDeployService.create(resources); - return new ResponseEntity<>(HttpStatus.CREATED); - } - - @Log("修改服务器") - @ApiOperation(value = "修改服务器") - @PutMapping - @PreAuthorize("@el.check('serverDeploy:edit')") - public ResponseEntity update(@Validated @RequestBody ServerDeploy resources){ - serverDeployService.update(resources); - return new ResponseEntity<>(HttpStatus.NO_CONTENT); - } - - @Log("删除服务器") - @ApiOperation(value = "删除Server") - @DeleteMapping - @PreAuthorize("@el.check('serverDeploy:del')") - public ResponseEntity delete(@RequestBody Set ids){ - serverDeployService.delete(ids); - return new ResponseEntity<>(HttpStatus.OK); - } - - @Log("测试连接服务器") - @ApiOperation(value = "测试连接服务器") - @PostMapping("/testConnect") - @PreAuthorize("@el.check('serverDeploy:add')") - public ResponseEntity testConnect(@Validated @RequestBody ServerDeploy resources){ - return new ResponseEntity<>(serverDeployService.testConnect(resources),HttpStatus.CREATED); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/AppService.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/AppService.java deleted file mode 100644 index c822778..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/AppService.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.service; - -import me.zhengjie.modules.mnt.domain.App; -import me.zhengjie.modules.mnt.service.dto.AppDto; -import me.zhengjie.modules.mnt.service.dto.AppQueryCriteria; -import org.springframework.data.domain.Pageable; - -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.List; -import java.util.Set; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -public interface AppService { - - /** - * 分页查询 - * @param criteria 条件 - * @param pageable 分页参数 - * @return / - */ - Object queryAll(AppQueryCriteria criteria, Pageable pageable); - - /** - * 查询全部数据 - * @param criteria 条件 - * @return / - */ - List queryAll(AppQueryCriteria criteria); - - /** - * 根据ID查询 - * @param id / - * @return / - */ - AppDto findById(Long id); - - /** - * 创建 - * @param resources / - */ - void create(App resources); - - /** - * 编辑 - * @param resources / - */ - void update(App resources); - - /** - * 删除 - * @param ids / - */ - void delete(Set ids); - - /** - * 导出数据 - * @param queryAll / - * @param response / - * @throws IOException / - */ - void download(List queryAll, HttpServletResponse response) throws IOException; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/DatabaseService.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/DatabaseService.java deleted file mode 100644 index e8a3acb..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/DatabaseService.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.service; - -import me.zhengjie.modules.mnt.domain.Database; -import me.zhengjie.modules.mnt.service.dto.DatabaseDto; -import me.zhengjie.modules.mnt.service.dto.DatabaseQueryCriteria; -import org.springframework.data.domain.Pageable; - -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.List; -import java.util.Set; - -/** - * @author ZhangHouYing - * @date 2019-08-24 - */ -public interface DatabaseService { - - /** - * 分页查询 - * @param criteria 条件 - * @param pageable 分页参数 - * @return / - */ - Object queryAll(DatabaseQueryCriteria criteria, Pageable pageable); - - /** - * 查询全部 - * @param criteria 条件 - * @return / - */ - List queryAll(DatabaseQueryCriteria criteria); - - /** - * 根据ID查询 - * @param id / - * @return / - */ - DatabaseDto findById(String id); - - /** - * 创建 - * @param resources / - */ - void create(Database resources); - - /** - * 编辑 - * @param resources / - */ - void update(Database resources); - - /** - * 删除 - * @param ids / - */ - void delete(Set ids); - - /** - * 测试连接数据库 - * @param resources / - * @return / - */ - boolean testConnection(Database resources); - - /** - * 导出数据 - * @param queryAll / - * @param response / - * @throws IOException e - */ - void download(List queryAll, HttpServletResponse response) throws IOException; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/DeployHistoryService.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/DeployHistoryService.java deleted file mode 100644 index 5eb1b3d..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/DeployHistoryService.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.service; - -import me.zhengjie.modules.mnt.domain.DeployHistory; -import me.zhengjie.modules.mnt.service.dto.DeployHistoryDto; -import me.zhengjie.modules.mnt.service.dto.DeployHistoryQueryCriteria; -import org.springframework.data.domain.Pageable; - -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.List; -import java.util.Set; - -/** - * @author zhanghouying - */ -public interface DeployHistoryService { - - /** - * 分页查询 - * @param criteria 条件 - * @param pageable 分页参数 - * @return / - */ - Object queryAll(DeployHistoryQueryCriteria criteria, Pageable pageable); - - /** - * 查询全部 - * @param criteria 条件 - * @return / - */ - List queryAll(DeployHistoryQueryCriteria criteria); - - /** - * 根据ID查询 - * @param id / - * @return / - */ - DeployHistoryDto findById(String id); - - /** - * 创建 - * @param resources / - */ - void create(DeployHistory resources); - - /** - * 删除 - * @param ids / - */ - void delete(Set ids); - - /** - * 导出数据 - * @param queryAll / - * @param response / - * @throws IOException / - */ - void download(List queryAll, HttpServletResponse response) throws IOException; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/DeployService.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/DeployService.java deleted file mode 100644 index 583474d..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/DeployService.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.service; - -import me.zhengjie.modules.mnt.domain.Deploy; -import me.zhengjie.modules.mnt.domain.DeployHistory; -import me.zhengjie.modules.mnt.service.dto.DeployDto; -import me.zhengjie.modules.mnt.service.dto.DeployQueryCriteria; -import org.springframework.data.domain.Pageable; - -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.List; -import java.util.Set; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -public interface DeployService { - - /** - * 分页查询 - * @param criteria 条件 - * @param pageable 分页参数 - * @return / - */ - Object queryAll(DeployQueryCriteria criteria, Pageable pageable); - - /** - * 查询全部数据 - * @param criteria 条件 - * @return / - */ - List queryAll(DeployQueryCriteria criteria); - - /** - * 根据ID查询 - * @param id / - * @return / - */ - DeployDto findById(Long id); - - /** - * 创建 - * @param resources / - */ - void create(Deploy resources); - - - /** - * 编辑 - * @param resources / - */ - void update(Deploy resources); - - /** - * 删除 - * @param ids / - */ - void delete(Set ids); - - /** - * 部署文件到服务器 - * @param fileSavePath 文件路径 - * @param appId 应用ID - */ - void deploy(String fileSavePath, Long appId); - - /** - * 查询部署状态 - * @param resources / - * @return / - */ - String serverStatus(Deploy resources); - /** - * 启动服务 - * @param resources / - * @return / - */ - String startServer(Deploy resources); - /** - * 停止服务 - * @param resources / - * @return / - */ - String stopServer(Deploy resources); - - /** - * 停止服务 - * @param resources / - * @return / - */ - String serverReduction(DeployHistory resources); - - /** - * 导出数据 - * @param queryAll / - * @param response / - * @throws IOException / - */ - void download(List queryAll, HttpServletResponse response) throws IOException; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/ServerDeployService.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/ServerDeployService.java deleted file mode 100644 index be8bb57..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/ServerDeployService.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.service; - -import me.zhengjie.modules.mnt.domain.ServerDeploy; -import me.zhengjie.modules.mnt.service.dto.ServerDeployDto; -import me.zhengjie.modules.mnt.service.dto.ServerDeployQueryCriteria; -import org.springframework.data.domain.Pageable; - -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.List; -import java.util.Set; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -public interface ServerDeployService { - - /** - * 分页查询 - * @param criteria 条件 - * @param pageable 分页参数 - * @return / - */ - Object queryAll(ServerDeployQueryCriteria criteria, Pageable pageable); - - /** - * 查询全部数据 - * @param criteria 条件 - * @return / - */ - List queryAll(ServerDeployQueryCriteria criteria); - - /** - * 根据ID查询 - * @param id / - * @return / - */ - ServerDeployDto findById(Long id); - - /** - * 创建 - * @param resources / - */ - void create(ServerDeploy resources); - - /** - * 编辑 - * @param resources / - */ - void update(ServerDeploy resources); - - /** - * 删除 - * @param ids / - */ - void delete(Set ids); - - /** - * 根据IP查询 - * @param ip / - * @return / - */ - ServerDeployDto findByIp(String ip); - - /** - * 测试登录服务器 - * @param resources / - * @return / - */ - Boolean testConnect(ServerDeploy resources); - - /** - * 导出数据 - * @param queryAll / - * @param response / - * @throws IOException / - */ - void download(List queryAll, HttpServletResponse response) throws IOException; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/AppDto.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/AppDto.java deleted file mode 100644 index c6fd6f7..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/AppDto.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.service.dto; - -import lombok.Getter; -import lombok.Setter; -import me.zhengjie.base.BaseDTO; -import java.io.Serializable; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -@Getter -@Setter -public class AppDto extends BaseDTO implements Serializable { - - /** - * 应用编号 - */ - private Long id; - - /** - * 应用名称 - */ - private String name; - - /** - * 端口 - */ - private Integer port; - - /** - * 上传目录 - */ - private String uploadPath; - - /** - * 部署目录 - */ - private String deployPath; - - /** - * 备份目录 - */ - private String backupPath; - - /** - * 启动脚本 - */ - private String startScript; - - /** - * 部署脚本 - */ - private String deployScript; - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/AppQueryCriteria.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/AppQueryCriteria.java deleted file mode 100644 index 17f358f..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/AppQueryCriteria.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.service.dto; - -import lombok.Data; -import me.zhengjie.annotation.Query; -import java.sql.Timestamp; -import java.util.List; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -@Data -public class AppQueryCriteria{ - - /** - * 模糊 - */ - @Query(type = Query.Type.INNER_LIKE) - private String name; - - @Query(type = Query.Type.BETWEEN) - private List createTime; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/DatabaseDto.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/DatabaseDto.java deleted file mode 100644 index 689b06b..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/DatabaseDto.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.service.dto; - -import lombok.Getter; -import lombok.Setter; -import me.zhengjie.base.BaseDTO; -import java.io.Serializable; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -@Getter -@Setter -public class DatabaseDto extends BaseDTO implements Serializable { - - /** - * id - */ - private String id; - - /** - * 数据库名称 - */ - private String name; - - /** - * 数据库连接地址 - */ - private String jdbcUrl; - - /** - * 数据库密码 - */ - private String pwd; - - /** - * 用户名 - */ - private String userName; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/DatabaseQueryCriteria.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/DatabaseQueryCriteria.java deleted file mode 100644 index 53d619d..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/DatabaseQueryCriteria.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.service.dto; - -import lombok.Data; -import me.zhengjie.annotation.Query; -import java.sql.Timestamp; -import java.util.List; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -@Data -public class DatabaseQueryCriteria{ - - /** - * 模糊 - */ - @Query(type = Query.Type.INNER_LIKE) - private String name; - - /** - * 精确 - */ - @Query - private String jdbcUrl; - - @Query(type = Query.Type.BETWEEN) - private List createTime; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/DeployDto.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/DeployDto.java deleted file mode 100644 index f3d77b8..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/DeployDto.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.service.dto; - -import cn.hutool.core.collection.CollectionUtil; -import lombok.Getter; -import lombok.Setter; -import me.zhengjie.base.BaseDTO; -import java.io.Serializable; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; - - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -@Getter -@Setter -public class DeployDto extends BaseDTO implements Serializable { - - /** - * 部署编号 - */ - private String id; - - private AppDto app; - - /** - * 服务器 - */ - private Set deploys; - - private String servers; - - /** - * 服务状态 - */ - private String status; - - public String getServers() { - if(CollectionUtil.isNotEmpty(deploys)){ - return deploys.stream().map(ServerDeployDto::getName).collect(Collectors.joining(",")); - } - return servers; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - DeployDto deployDto = (DeployDto) o; - return Objects.equals(id, deployDto.id); - } - - @Override - public int hashCode() { - return Objects.hash(id); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/DeployHistoryDto.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/DeployHistoryDto.java deleted file mode 100644 index a9f480c..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/DeployHistoryDto.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.service.dto; - -import lombok.Data; -import java.io.Serializable; -import java.sql.Timestamp; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -@Data -public class DeployHistoryDto implements Serializable { - - /** - * 编号 - */ - private String id; - - /** - * 应用名称 - */ - private String appName; - - /** - * 部署IP - */ - private String ip; - - /** - * 部署时间 - */ - private Timestamp deployDate; - - /** - * 部署人员 - */ - private String deployUser; - - /** - * 部署编号 - */ - private Long deployId; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/DeployHistoryQueryCriteria.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/DeployHistoryQueryCriteria.java deleted file mode 100644 index c34f124..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/DeployHistoryQueryCriteria.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.service.dto; - -import lombok.Data; -import me.zhengjie.annotation.Query; -import java.sql.Timestamp; -import java.util.List; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -@Data -public class DeployHistoryQueryCriteria{ - - /** - * 精确 - */ - @Query(blurry = "appName,ip,deployUser") - private String blurry; - - @Query - private Long deployId; - - @Query(type = Query.Type.BETWEEN) - private List deployDate; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/DeployQueryCriteria.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/DeployQueryCriteria.java deleted file mode 100644 index c404620..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/DeployQueryCriteria.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.service.dto; - -import lombok.Data; -import me.zhengjie.annotation.Query; -import java.sql.Timestamp; -import java.util.List; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -@Data -public class DeployQueryCriteria{ - - /** - * 模糊 - */ - @Query(type = Query.Type.INNER_LIKE, propName = "name", joinName = "app") - private String appName; - - @Query(type = Query.Type.BETWEEN) - private List createTime; - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/ServerDeployDto.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/ServerDeployDto.java deleted file mode 100644 index a49c795..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/ServerDeployDto.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.service.dto; - -import lombok.Getter; -import lombok.Setter; -import me.zhengjie.base.BaseDTO; -import java.io.Serializable; -import java.util.Objects; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -@Getter -@Setter -public class ServerDeployDto extends BaseDTO implements Serializable { - - private Long id; - - private String name; - - private String ip; - - private Integer port; - - private String account; - - private String password; - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - ServerDeployDto that = (ServerDeployDto) o; - return Objects.equals(id, that.id) && - Objects.equals(name, that.name); - } - - @Override - public int hashCode() { - return Objects.hash(id, name); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/ServerDeployQueryCriteria.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/ServerDeployQueryCriteria.java deleted file mode 100644 index bb8bd41..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/dto/ServerDeployQueryCriteria.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.service.dto; - -import lombok.Data; -import me.zhengjie.annotation.Query; -import java.sql.Timestamp; -import java.util.List; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -@Data -public class ServerDeployQueryCriteria{ - - /** - * 模糊 - */ - @Query(blurry = "name,ip,account") - private String blurry; - - @Query(type = Query.Type.BETWEEN) - private List createTime; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/impl/AppServiceImpl.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/impl/AppServiceImpl.java deleted file mode 100644 index 42b088f..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/impl/AppServiceImpl.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.service.impl; - -import lombok.RequiredArgsConstructor; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.modules.mnt.domain.App; -import me.zhengjie.modules.mnt.repository.AppRepository; -import me.zhengjie.modules.mnt.service.AppService; -import me.zhengjie.modules.mnt.service.dto.AppDto; -import me.zhengjie.modules.mnt.service.dto.AppQueryCriteria; -import me.zhengjie.modules.mnt.service.mapstruct.AppMapper; -import me.zhengjie.utils.FileUtil; -import me.zhengjie.utils.PageUtil; -import me.zhengjie.utils.QueryHelp; -import me.zhengjie.utils.ValidationUtil; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.*; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -@Service -@RequiredArgsConstructor -public class AppServiceImpl implements AppService { - - private final AppRepository appRepository; - private final AppMapper appMapper; - - @Override - public Object queryAll(AppQueryCriteria criteria, Pageable pageable){ - Page page = appRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable); - return PageUtil.toPage(page.map(appMapper::toDto)); - } - - @Override - public List queryAll(AppQueryCriteria criteria){ - return appMapper.toDto(appRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder))); - } - - @Override - public AppDto findById(Long id) { - App app = appRepository.findById(id).orElseGet(App::new); - ValidationUtil.isNull(app.getId(),"App","id",id); - return appMapper.toDto(app); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void create(App resources) { - verification(resources); - appRepository.save(resources); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void update(App resources) { - verification(resources); - App app = appRepository.findById(resources.getId()).orElseGet(App::new); - ValidationUtil.isNull(app.getId(),"App","id",resources.getId()); - app.copy(resources); - appRepository.save(app); - } - - private void verification(App resources){ - String opt = "/opt"; - String home = "/home"; - if (!(resources.getUploadPath().startsWith(opt) || resources.getUploadPath().startsWith(home))) { - throw new BadRequestException("文件只能上传在opt目录或者home目录 "); - } - if (!(resources.getDeployPath().startsWith(opt) || resources.getDeployPath().startsWith(home))) { - throw new BadRequestException("文件只能部署在opt目录或者home目录 "); - } - if (!(resources.getBackupPath().startsWith(opt) || resources.getBackupPath().startsWith(home))) { - throw new BadRequestException("文件只能备份在opt目录或者home目录 "); - } - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Set ids) { - for (Long id : ids) { - appRepository.deleteById(id); - } - } - - @Override - public void download(List queryAll, HttpServletResponse response) throws IOException { - List> list = new ArrayList<>(); - for (AppDto appDto : queryAll) { - Map map = new LinkedHashMap<>(); - map.put("应用名称", appDto.getName()); - map.put("端口", appDto.getPort()); - map.put("上传目录", appDto.getUploadPath()); - map.put("部署目录", appDto.getDeployPath()); - map.put("备份目录", appDto.getBackupPath()); - map.put("启动脚本", appDto.getStartScript()); - map.put("部署脚本", appDto.getDeployScript()); - map.put("创建日期", appDto.getCreateTime()); - list.add(map); - } - FileUtil.downloadExcel(list, response); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/impl/DatabaseServiceImpl.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/impl/DatabaseServiceImpl.java deleted file mode 100644 index c774028..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/impl/DatabaseServiceImpl.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.service.impl; - -import cn.hutool.core.util.IdUtil; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.modules.mnt.domain.Database; -import me.zhengjie.modules.mnt.repository.DatabaseRepository; -import me.zhengjie.modules.mnt.service.DatabaseService; -import me.zhengjie.modules.mnt.service.dto.DatabaseDto; -import me.zhengjie.modules.mnt.service.dto.DatabaseQueryCriteria; -import me.zhengjie.modules.mnt.service.mapstruct.DatabaseMapper; -import me.zhengjie.modules.mnt.util.SqlUtils; -import me.zhengjie.utils.FileUtil; -import me.zhengjie.utils.PageUtil; -import me.zhengjie.utils.QueryHelp; -import me.zhengjie.utils.ValidationUtil; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.*; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -@Slf4j -@Service -@RequiredArgsConstructor -public class DatabaseServiceImpl implements DatabaseService { - - private final DatabaseRepository databaseRepository; - private final DatabaseMapper databaseMapper; - - @Override - public Object queryAll(DatabaseQueryCriteria criteria, Pageable pageable){ - Page page = databaseRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable); - return PageUtil.toPage(page.map(databaseMapper::toDto)); - } - - @Override - public List queryAll(DatabaseQueryCriteria criteria){ - return databaseMapper.toDto(databaseRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder))); - } - - @Override - public DatabaseDto findById(String id) { - Database database = databaseRepository.findById(id).orElseGet(Database::new); - ValidationUtil.isNull(database.getId(),"Database","id",id); - return databaseMapper.toDto(database); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void create(Database resources) { - resources.setId(IdUtil.simpleUUID()); - databaseRepository.save(resources); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void update(Database resources) { - Database database = databaseRepository.findById(resources.getId()).orElseGet(Database::new); - ValidationUtil.isNull(database.getId(),"Database","id",resources.getId()); - database.copy(resources); - databaseRepository.save(database); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Set ids) { - for (String id : ids) { - databaseRepository.deleteById(id); - } - } - - @Override - public boolean testConnection(Database resources) { - try { - return SqlUtils.testConnection(resources.getJdbcUrl(), resources.getUserName(), resources.getPwd()); - } catch (Exception e) { - log.error(e.getMessage()); - return false; - } - } - - @Override - public void download(List queryAll, HttpServletResponse response) throws IOException { - List> list = new ArrayList<>(); - for (DatabaseDto databaseDto : queryAll) { - Map map = new LinkedHashMap<>(); - map.put("数据库名称", databaseDto.getName()); - map.put("数据库连接地址", databaseDto.getJdbcUrl()); - map.put("用户名", databaseDto.getUserName()); - map.put("创建日期", databaseDto.getCreateTime()); - list.add(map); - } - FileUtil.downloadExcel(list, response); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/impl/DeployHistoryServiceImpl.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/impl/DeployHistoryServiceImpl.java deleted file mode 100644 index 7431113..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/impl/DeployHistoryServiceImpl.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.service.impl; - -import cn.hutool.core.util.IdUtil; -import lombok.RequiredArgsConstructor; -import me.zhengjie.modules.mnt.domain.DeployHistory; -import me.zhengjie.modules.mnt.repository.DeployHistoryRepository; -import me.zhengjie.modules.mnt.service.DeployHistoryService; -import me.zhengjie.modules.mnt.service.dto.DeployHistoryDto; -import me.zhengjie.modules.mnt.service.dto.DeployHistoryQueryCriteria; -import me.zhengjie.modules.mnt.service.mapstruct.DeployHistoryMapper; -import me.zhengjie.utils.FileUtil; -import me.zhengjie.utils.PageUtil; -import me.zhengjie.utils.QueryHelp; -import me.zhengjie.utils.ValidationUtil; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.*; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -@Service -@RequiredArgsConstructor -public class DeployHistoryServiceImpl implements DeployHistoryService { - - private final DeployHistoryRepository deployhistoryRepository; - private final DeployHistoryMapper deployhistoryMapper; - - @Override - public Object queryAll(DeployHistoryQueryCriteria criteria, Pageable pageable){ - Page page = deployhistoryRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable); - return PageUtil.toPage(page.map(deployhistoryMapper::toDto)); - } - - @Override - public List queryAll(DeployHistoryQueryCriteria criteria){ - return deployhistoryMapper.toDto(deployhistoryRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder))); - } - - @Override - public DeployHistoryDto findById(String id) { - DeployHistory deployhistory = deployhistoryRepository.findById(id).orElseGet(DeployHistory::new); - ValidationUtil.isNull(deployhistory.getId(),"DeployHistory","id",id); - return deployhistoryMapper.toDto(deployhistory); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void create(DeployHistory resources) { - resources.setId(IdUtil.simpleUUID()); - deployhistoryRepository.save(resources); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Set ids) { - for (String id : ids) { - deployhistoryRepository.deleteById(id); - } - } - - @Override - public void download(List queryAll, HttpServletResponse response) throws IOException { - List> list = new ArrayList<>(); - for (DeployHistoryDto deployHistoryDto : queryAll) { - Map map = new LinkedHashMap<>(); - map.put("部署编号", deployHistoryDto.getDeployId()); - map.put("应用名称", deployHistoryDto.getAppName()); - map.put("部署IP", deployHistoryDto.getIp()); - map.put("部署时间", deployHistoryDto.getDeployDate()); - map.put("部署人员", deployHistoryDto.getDeployUser()); - list.add(map); - } - FileUtil.downloadExcel(list, response); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/impl/DeployServiceImpl.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/impl/DeployServiceImpl.java deleted file mode 100644 index f2491cd..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/impl/DeployServiceImpl.java +++ /dev/null @@ -1,430 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.service.impl; - -import cn.hutool.core.date.DatePattern; -import cn.hutool.core.date.DateUtil; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.modules.mnt.domain.App; -import me.zhengjie.modules.mnt.domain.Deploy; -import me.zhengjie.modules.mnt.domain.DeployHistory; -import me.zhengjie.modules.mnt.domain.ServerDeploy; -import me.zhengjie.modules.mnt.repository.DeployRepository; -import me.zhengjie.modules.mnt.service.DeployHistoryService; -import me.zhengjie.modules.mnt.service.DeployService; -import me.zhengjie.modules.mnt.service.ServerDeployService; -import me.zhengjie.modules.mnt.service.dto.AppDto; -import me.zhengjie.modules.mnt.service.dto.DeployDto; -import me.zhengjie.modules.mnt.service.dto.DeployQueryCriteria; -import me.zhengjie.modules.mnt.service.dto.ServerDeployDto; -import me.zhengjie.modules.mnt.service.mapstruct.DeployMapper; -import me.zhengjie.modules.mnt.util.ExecuteShellUtil; -import me.zhengjie.modules.mnt.util.ScpClientUtil; -import me.zhengjie.modules.mnt.websocket.MsgType; -import me.zhengjie.modules.mnt.websocket.SocketMsg; -import me.zhengjie.modules.mnt.websocket.WebSocketServer; -import me.zhengjie.utils.*; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.*; - -/** - * @author zhanghouying - * @date 2019-08-24 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class DeployServiceImpl implements DeployService { - - private final String FILE_SEPARATOR = "/"; - private final DeployRepository deployRepository; - private final DeployMapper deployMapper; - private final ServerDeployService serverDeployService; - private final DeployHistoryService deployHistoryService; - /** - * 循环次数 - */ - private final Integer count = 30; - - - @Override - public Object queryAll(DeployQueryCriteria criteria, Pageable pageable) { - Page page = deployRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable); - return PageUtil.toPage(page.map(deployMapper::toDto)); - } - - @Override - public List queryAll(DeployQueryCriteria criteria) { - return deployMapper.toDto(deployRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder))); - } - - @Override - public DeployDto findById(Long id) { - Deploy deploy = deployRepository.findById(id).orElseGet(Deploy::new); - ValidationUtil.isNull(deploy.getId(), "Deploy", "id", id); - return deployMapper.toDto(deploy); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void create(Deploy resources) { - deployRepository.save(resources); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void update(Deploy resources) { - Deploy deploy = deployRepository.findById(resources.getId()).orElseGet(Deploy::new); - ValidationUtil.isNull(deploy.getId(), "Deploy", "id", resources.getId()); - deploy.copy(resources); - deployRepository.save(deploy); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Set ids) { - for (Long id : ids) { - deployRepository.deleteById(id); - } - } - - @Override - public void deploy(String fileSavePath, Long id) { - deployApp(fileSavePath, id); - } - - /** - * @param fileSavePath 本机路径 - * @param id ID - */ - private void deployApp(String fileSavePath, Long id) { - - DeployDto deploy = findById(id); - if (deploy == null) { - sendMsg("部署信息不存在", MsgType.ERROR); - throw new BadRequestException("部署信息不存在"); - } - AppDto app = deploy.getApp(); - if (app == null) { - sendMsg("包对应应用信息不存在", MsgType.ERROR); - throw new BadRequestException("包对应应用信息不存在"); - } - int port = app.getPort(); - //这个是服务器部署路径 - String uploadPath = app.getUploadPath(); - StringBuilder sb = new StringBuilder(); - String msg; - Set deploys = deploy.getDeploys(); - for (ServerDeployDto deployDTO : deploys) { - String ip = deployDTO.getIp(); - ExecuteShellUtil executeShellUtil = getExecuteShellUtil(ip); - //判断是否第一次部署 - boolean flag = checkFile(executeShellUtil, app); - //第一步要确认服务器上有这个目录 - executeShellUtil.execute("mkdir -p " + app.getUploadPath()); - executeShellUtil.execute("mkdir -p " + app.getBackupPath()); - executeShellUtil.execute("mkdir -p " + app.getDeployPath()); - //上传文件 - msg = String.format("登陆到服务器:%s", ip); - ScpClientUtil scpClientUtil = getScpClientUtil(ip); - log.info(msg); - sendMsg(msg, MsgType.INFO); - msg = String.format("上传文件到服务器:%s
目录:%s下,请稍等...", ip, uploadPath); - sendMsg(msg, MsgType.INFO); - scpClientUtil.putFile(fileSavePath, uploadPath); - if (flag) { - sendMsg("停止原来应用", MsgType.INFO); - //停止应用 - stopApp(port, executeShellUtil); - sendMsg("备份原来应用", MsgType.INFO); - //备份应用 - backupApp(executeShellUtil, ip, app.getDeployPath()+FILE_SEPARATOR, app.getName(), app.getBackupPath()+FILE_SEPARATOR, id); - } - sendMsg("部署应用", MsgType.INFO); - //部署文件,并启动应用 - String deployScript = app.getDeployScript(); - executeShellUtil.execute(deployScript); - sleep(3); - sendMsg("应用部署中,请耐心等待部署结果,或者稍后手动查看部署状态", MsgType.INFO); - int i = 0; - boolean result = false; - // 由于启动应用需要时间,所以需要循环获取状态,如果超过30次,则认为是启动失败 - while (i++ < count){ - result = checkIsRunningStatus(port, executeShellUtil); - if(result){ - break; - } - // 休眠6秒 - sleep(6); - } - sb.append("服务器:").append(deployDTO.getName()).append("
应用:").append(app.getName()); - sendResultMsg(result, sb); - executeShellUtil.close(); - } - } - - private void sleep(int second) { - try { - Thread.sleep(second * 1000); - } catch (InterruptedException e) { - log.error(e.getMessage(),e); - } - } - - private void backupApp(ExecuteShellUtil executeShellUtil, String ip, String fileSavePath, String appName, String backupPath, Long id) { - String deployDate = DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN); - StringBuilder sb = new StringBuilder(); - backupPath += appName + FILE_SEPARATOR + deployDate + "\n"; - sb.append("mkdir -p ").append(backupPath); - sb.append("mv -f ").append(fileSavePath); - sb.append(appName).append(" ").append(backupPath); - log.info("备份应用脚本:" + sb.toString()); - executeShellUtil.execute(sb.toString()); - //还原信息入库 - DeployHistory deployHistory = new DeployHistory(); - deployHistory.setAppName(appName); - deployHistory.setDeployUser(SecurityUtils.getCurrentUsername()); - deployHistory.setIp(ip); - deployHistory.setDeployId(id); - deployHistoryService.create(deployHistory); - } - - /** - * 停App - * - * @param port 端口 - * @param executeShellUtil / - */ - private void stopApp(int port, ExecuteShellUtil executeShellUtil) { - //发送停止命令 - executeShellUtil.execute(String.format("lsof -i :%d|grep -v \"PID\"|awk '{print \"kill -9\",$2}'|sh", port)); - - } - - /** - * 指定端口程序是否在运行 - * - * @param port 端口 - * @param executeShellUtil / - * @return true 正在运行 false 已经停止 - */ - private boolean checkIsRunningStatus(int port, ExecuteShellUtil executeShellUtil) { - String result = executeShellUtil.executeForResult(String.format("fuser -n tcp %d", port)); - return result.indexOf("/tcp:")>0; - } - - private void sendMsg(String msg, MsgType msgType) { - try { - WebSocketServer.sendInfo(new SocketMsg(msg, msgType), "deploy"); - } catch (IOException e) { - log.error(e.getMessage(),e); - } - } - - @Override - public String serverStatus(Deploy resources) { - Set serverDeploys = resources.getDeploys(); - App app = resources.getApp(); - for (ServerDeploy serverDeploy : serverDeploys) { - StringBuilder sb = new StringBuilder(); - ExecuteShellUtil executeShellUtil = getExecuteShellUtil(serverDeploy.getIp()); - sb.append("服务器:").append(serverDeploy.getName()).append("
应用:").append(app.getName()); - boolean result = checkIsRunningStatus(app.getPort(), executeShellUtil); - if (result) { - sb.append("
正在运行"); - sendMsg(sb.toString(), MsgType.INFO); - } else { - sb.append("
已停止!"); - sendMsg(sb.toString(), MsgType.ERROR); - } - log.info(sb.toString()); - executeShellUtil.close(); - } - return "执行完毕"; - } - - private boolean checkFile(ExecuteShellUtil executeShellUtil, AppDto appDTO) { - String result = executeShellUtil.executeForResult("find " + appDTO.getDeployPath() + " -name " + appDTO.getName()); - return result.indexOf(appDTO.getName())>0; - } - - /** - * 启动服务 - * @param resources / - * @return / - */ - @Override - public String startServer(Deploy resources) { - Set deploys = resources.getDeploys(); - App app = resources.getApp(); - for (ServerDeploy deploy : deploys) { - StringBuilder sb = new StringBuilder(); - ExecuteShellUtil executeShellUtil = getExecuteShellUtil(deploy.getIp()); - //为了防止重复启动,这里先停止应用 - stopApp(app.getPort(), executeShellUtil); - sb.append("服务器:").append(deploy.getName()).append("
应用:").append(app.getName()); - sendMsg("下发启动命令", MsgType.INFO); - executeShellUtil.execute(app.getStartScript()); - sleep(3); - sendMsg("应用启动中,请耐心等待启动结果,或者稍后手动查看运行状态", MsgType.INFO); - int i = 0; - boolean result = false; - // 由于启动应用需要时间,所以需要循环获取状态,如果超过30次,则认为是启动失败 - while (i++ < count){ - result = checkIsRunningStatus(app.getPort(), executeShellUtil); - if(result){ - break; - } - // 休眠6秒 - sleep(6); - } - sendResultMsg(result, sb); - log.info(sb.toString()); - executeShellUtil.close(); - } - return "执行完毕"; - } - - /** - * 停止服务 - * @param resources / - * @return / - */ - @Override - public String stopServer(Deploy resources) { - Set deploys = resources.getDeploys(); - App app = resources.getApp(); - for (ServerDeploy deploy : deploys) { - StringBuilder sb = new StringBuilder(); - ExecuteShellUtil executeShellUtil = getExecuteShellUtil(deploy.getIp()); - sb.append("服务器:").append(deploy.getName()).append("
应用:").append(app.getName()); - sendMsg("下发停止命令", MsgType.INFO); - //停止应用 - stopApp(app.getPort(), executeShellUtil); - sleep(1); - boolean result = checkIsRunningStatus(app.getPort(), executeShellUtil); - if (result) { - sb.append("
关闭失败!"); - sendMsg(sb.toString(), MsgType.ERROR); - } else { - sb.append("
关闭成功!"); - sendMsg(sb.toString(), MsgType.INFO); - } - log.info(sb.toString()); - executeShellUtil.close(); - } - return "执行完毕"; - } - - @Override - public String serverReduction(DeployHistory resources) { - Long deployId = resources.getDeployId(); - Deploy deployInfo = deployRepository.findById(deployId).orElseGet(Deploy::new); - String deployDate = DateUtil.format(resources.getDeployDate(), DatePattern.PURE_DATETIME_PATTERN); - App app = deployInfo.getApp(); - if (app == null) { - sendMsg("应用信息不存在:" + resources.getAppName(), MsgType.ERROR); - throw new BadRequestException("应用信息不存在:" + resources.getAppName()); - } - String backupPath = app.getBackupPath()+FILE_SEPARATOR; - backupPath += resources.getAppName() + FILE_SEPARATOR + deployDate; - //这个是服务器部署路径 - String deployPath = app.getDeployPath(); - String ip = resources.getIp(); - ExecuteShellUtil executeShellUtil = getExecuteShellUtil(ip); - String msg; - - msg = String.format("登陆到服务器:%s", ip); - log.info(msg); - sendMsg(msg, MsgType.INFO); - sendMsg("停止原来应用", MsgType.INFO); - //停止应用 - stopApp(app.getPort(), executeShellUtil); - //删除原来应用 - sendMsg("删除应用", MsgType.INFO); - executeShellUtil.execute("rm -rf " + deployPath + FILE_SEPARATOR + resources.getAppName()); - //还原应用 - sendMsg("还原应用", MsgType.INFO); - executeShellUtil.execute("cp -r " + backupPath + "/. " + deployPath); - sendMsg("启动应用", MsgType.INFO); - executeShellUtil.execute(app.getStartScript()); - sendMsg("应用启动中,请耐心等待启动结果,或者稍后手动查看启动状态", MsgType.INFO); - int i = 0; - boolean result = false; - // 由于启动应用需要时间,所以需要循环获取状态,如果超过30次,则认为是启动失败 - while (i++ < count){ - result = checkIsRunningStatus(app.getPort(), executeShellUtil); - if(result){ - break; - } - // 休眠6秒 - sleep(6); - } - StringBuilder sb = new StringBuilder(); - sb.append("服务器:").append(ip).append("
应用:").append(resources.getAppName()); - sendResultMsg(result, sb); - executeShellUtil.close(); - return ""; - } - - private ExecuteShellUtil getExecuteShellUtil(String ip) { - ServerDeployDto serverDeployDTO = serverDeployService.findByIp(ip); - if (serverDeployDTO == null) { - sendMsg("IP对应服务器信息不存在:" + ip, MsgType.ERROR); - throw new BadRequestException("IP对应服务器信息不存在:" + ip); - } - return new ExecuteShellUtil(ip, serverDeployDTO.getAccount(), serverDeployDTO.getPassword(),serverDeployDTO.getPort()); - } - - private ScpClientUtil getScpClientUtil(String ip) { - ServerDeployDto serverDeployDTO = serverDeployService.findByIp(ip); - if (serverDeployDTO == null) { - sendMsg("IP对应服务器信息不存在:" + ip, MsgType.ERROR); - throw new BadRequestException("IP对应服务器信息不存在:" + ip); - } - return ScpClientUtil.getInstance(ip, serverDeployDTO.getPort(), serverDeployDTO.getAccount(), serverDeployDTO.getPassword()); - } - - private void sendResultMsg(boolean result, StringBuilder sb) { - if (result) { - sb.append("
启动成功!"); - sendMsg(sb.toString(), MsgType.INFO); - } else { - sb.append("
启动失败!"); - sendMsg(sb.toString(), MsgType.ERROR); - } - } - - @Override - public void download(List queryAll, HttpServletResponse response) throws IOException { - List> list = new ArrayList<>(); - for (DeployDto deployDto : queryAll) { - Map map = new LinkedHashMap<>(); - map.put("应用名称", deployDto.getApp().getName()); - map.put("服务器", deployDto.getServers()); - map.put("部署日期", deployDto.getCreateTime()); - list.add(map); - } - FileUtil.downloadExcel(list, response); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/impl/ServerDeployServiceImpl.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/impl/ServerDeployServiceImpl.java deleted file mode 100644 index 63272da..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/impl/ServerDeployServiceImpl.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.service.impl; - -import lombok.RequiredArgsConstructor; -import me.zhengjie.modules.mnt.domain.ServerDeploy; -import me.zhengjie.modules.mnt.repository.ServerDeployRepository; -import me.zhengjie.modules.mnt.service.ServerDeployService; -import me.zhengjie.modules.mnt.service.dto.ServerDeployDto; -import me.zhengjie.modules.mnt.service.dto.ServerDeployQueryCriteria; -import me.zhengjie.modules.mnt.service.mapstruct.ServerDeployMapper; -import me.zhengjie.modules.mnt.util.ExecuteShellUtil; -import me.zhengjie.utils.FileUtil; -import me.zhengjie.utils.PageUtil; -import me.zhengjie.utils.QueryHelp; -import me.zhengjie.utils.ValidationUtil; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.*; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -@Service -@RequiredArgsConstructor -public class ServerDeployServiceImpl implements ServerDeployService { - - private final ServerDeployRepository serverDeployRepository; - private final ServerDeployMapper serverDeployMapper; - - @Override - public Object queryAll(ServerDeployQueryCriteria criteria, Pageable pageable){ - Page page = serverDeployRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable); - return PageUtil.toPage(page.map(serverDeployMapper::toDto)); - } - - @Override - public List queryAll(ServerDeployQueryCriteria criteria){ - return serverDeployMapper.toDto(serverDeployRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder))); - } - - @Override - public ServerDeployDto findById(Long id) { - ServerDeploy server = serverDeployRepository.findById(id).orElseGet(ServerDeploy::new); - ValidationUtil.isNull(server.getId(),"ServerDeploy","id",id); - return serverDeployMapper.toDto(server); - } - - @Override - public ServerDeployDto findByIp(String ip) { - ServerDeploy deploy = serverDeployRepository.findByIp(ip); - return serverDeployMapper.toDto(deploy); - } - - @Override - public Boolean testConnect(ServerDeploy resources) { - ExecuteShellUtil executeShellUtil = null; - try { - executeShellUtil = new ExecuteShellUtil(resources.getIp(), resources.getAccount(), resources.getPassword(),resources.getPort()); - return executeShellUtil.execute("ls")==0; - } catch (Exception e) { - return false; - }finally { - if (executeShellUtil != null) { - executeShellUtil.close(); - } - } - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void create(ServerDeploy resources) { - serverDeployRepository.save(resources); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void update(ServerDeploy resources) { - ServerDeploy serverDeploy = serverDeployRepository.findById(resources.getId()).orElseGet(ServerDeploy::new); - ValidationUtil.isNull( serverDeploy.getId(),"ServerDeploy","id",resources.getId()); - serverDeploy.copy(resources); - serverDeployRepository.save(serverDeploy); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Set ids) { - for (Long id : ids) { - serverDeployRepository.deleteById(id); - } - } - - @Override - public void download(List queryAll, HttpServletResponse response) throws IOException { - List> list = new ArrayList<>(); - for (ServerDeployDto deployDto : queryAll) { - Map map = new LinkedHashMap<>(); - map.put("服务器名称", deployDto.getName()); - map.put("服务器IP", deployDto.getIp()); - map.put("端口", deployDto.getPort()); - map.put("账号", deployDto.getAccount()); - map.put("创建日期", deployDto.getCreateTime()); - list.add(map); - } - FileUtil.downloadExcel(list, response); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/mapstruct/AppMapper.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/mapstruct/AppMapper.java deleted file mode 100644 index fc39eeb..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/mapstruct/AppMapper.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.service.mapstruct; - -import me.zhengjie.base.BaseMapper; -import me.zhengjie.modules.mnt.domain.App; -import me.zhengjie.modules.mnt.service.dto.AppDto; -import org.mapstruct.Mapper; -import org.mapstruct.ReportingPolicy; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -@Mapper(componentModel = "spring",uses = {},unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface AppMapper extends BaseMapper { - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/mapstruct/DatabaseMapper.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/mapstruct/DatabaseMapper.java deleted file mode 100644 index 3cc6e8d..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/mapstruct/DatabaseMapper.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.service.mapstruct; - -import me.zhengjie.base.BaseMapper; -import me.zhengjie.modules.mnt.domain.Database; -import me.zhengjie.modules.mnt.service.dto.DatabaseDto; -import org.mapstruct.Mapper; -import org.mapstruct.ReportingPolicy; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface DatabaseMapper extends BaseMapper { - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/mapstruct/DeployHistoryMapper.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/mapstruct/DeployHistoryMapper.java deleted file mode 100644 index 2522ab0..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/mapstruct/DeployHistoryMapper.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.service.mapstruct; - -import me.zhengjie.base.BaseMapper; -import me.zhengjie.modules.mnt.domain.DeployHistory; -import me.zhengjie.modules.mnt.service.dto.DeployHistoryDto; -import org.mapstruct.Mapper; -import org.mapstruct.ReportingPolicy; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -@Mapper(componentModel = "spring",uses = {},unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface DeployHistoryMapper extends BaseMapper { - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/mapstruct/DeployMapper.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/mapstruct/DeployMapper.java deleted file mode 100644 index cd3edee..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/mapstruct/DeployMapper.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.service.mapstruct; - -import me.zhengjie.base.BaseMapper; -import me.zhengjie.modules.mnt.domain.Deploy; -import me.zhengjie.modules.mnt.service.dto.DeployDto; -import org.mapstruct.Mapper; -import org.mapstruct.ReportingPolicy; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -@Mapper(componentModel = "spring",uses = {AppMapper.class, ServerDeployMapper.class},unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface DeployMapper extends BaseMapper { - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/mapstruct/ServerDeployMapper.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/mapstruct/ServerDeployMapper.java deleted file mode 100644 index 960b25b..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/service/mapstruct/ServerDeployMapper.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.service.mapstruct; - -import me.zhengjie.base.BaseMapper; -import me.zhengjie.modules.mnt.domain.ServerDeploy; -import me.zhengjie.modules.mnt.service.dto.ServerDeployDto; -import org.mapstruct.Mapper; -import org.mapstruct.ReportingPolicy; - -/** -* @author zhanghouying -* @date 2019-08-24 -*/ -@Mapper(componentModel = "spring",uses = {},unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface ServerDeployMapper extends BaseMapper { - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/util/DataTypeEnum.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/util/DataTypeEnum.java deleted file mode 100644 index e104b9e..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/util/DataTypeEnum.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * << - * Davinci - * == - * Copyright (C) 2016 - 2019 EDP - * == - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * >> - * - */ - -package me.zhengjie.modules.mnt.util; -import lombok.extern.slf4j.Slf4j; - -/** - * @author / - */ -@Slf4j -@SuppressWarnings({"unchecked","all"}) -public enum DataTypeEnum { - - /** mysql */ - MYSQL("mysql", "mysql", "com.mysql.jdbc.Driver", "`", "`", "'", "'"), - - /** oracle */ - ORACLE("oracle", "oracle", "oracle.jdbc.driver.OracleDriver", "\"", "\"", "\"", "\""), - - /** sql server */ - SQLSERVER("sqlserver", "sqlserver", "com.microsoft.sqlserver.jdbc.SQLServerDriver", "\"", "\"", "\"", "\""), - - /** h2 */ - H2("h2", "h2", "org.h2.Driver", "`", "`", "\"", "\""), - - /** phoenix */ - PHOENIX("phoenix", "hbase phoenix", "org.apache.phoenix.jdbc.PhoenixDriver", "", "", "\"", "\""), - - /** mongo */ - MONGODB("mongo", "mongodb", "mongodb.jdbc.MongoDriver", "`", "`", "\"", "\""), - - /** sql4es */ - ELASTICSEARCH("sql4es", "elasticsearch", "nl.anchormen.sql4es.jdbc.ESDriver", "", "", "'", "'"), - - /** presto */ - PRESTO("presto", "presto", "com.facebook.presto.jdbc.PrestoDriver", "", "", "\"", "\""), - - /** moonbox */ - MOONBOX("moonbox", "moonbox", "moonbox.jdbc.MbDriver", "`", "`", "`", "`"), - - /** cassandra */ - CASSANDRA("cassandra", "cassandra", "com.github.adejanovski.cassandra.jdbc.CassandraDriver", "", "", "'", "'"), - - /** click house */ - CLICKHOUSE("clickhouse", "clickhouse", "ru.yandex.clickhouse.ClickHouseDriver", "", "", "\"", "\""), - - /** kylin */ - KYLIN("kylin", "kylin", "org.apache.kylin.jdbc.Driver", "\"", "\"", "\"", "\""), - - /** vertica */ - VERTICA("vertica", "vertica", "com.vertica.jdbc.Driver", "", "", "'", "'"), - - /** sap */ - HANA("sap", "sap hana", "com.sap.db.jdbc.Driver", "", "", "'", "'"), - - /** impala */ - IMPALA("impala", "impala", "com.cloudera.impala.jdbc41.Driver", "", "", "'", "'"); - - private String feature; - private String desc; - private String driver; - private String keywordPrefix; - private String keywordSuffix; - private String aliasPrefix; - private String aliasSuffix; - - private static final String JDBC_URL_PREFIX = "jdbc:"; - - DataTypeEnum(String feature, String desc, String driver, String keywordPrefix, String keywordSuffix, String aliasPrefix, String aliasSuffix) { - this.feature = feature; - this.desc = desc; - this.driver = driver; - this.keywordPrefix = keywordPrefix; - this.keywordSuffix = keywordSuffix; - this.aliasPrefix = aliasPrefix; - this.aliasSuffix = aliasSuffix; - } - - public static DataTypeEnum urlOf(String jdbcUrl) { - String url = jdbcUrl.toLowerCase().trim(); - for (DataTypeEnum dataTypeEnum : values()) { - if (url.startsWith(JDBC_URL_PREFIX + dataTypeEnum.feature)) { - try { - Class aClass = Class.forName(dataTypeEnum.getDriver()); - if (null == aClass) { - throw new RuntimeException("Unable to get driver instance for jdbcUrl: " + jdbcUrl); - } - } catch (ClassNotFoundException e) { - throw new RuntimeException("Unable to get driver instance: " + jdbcUrl); - } - return dataTypeEnum; - } - } - return null; - } - - public String getFeature() { - return feature; - } - - public String getDesc() { - return desc; - } - - public String getDriver() { - return driver; - } - - public String getKeywordPrefix() { - return keywordPrefix; - } - - public String getKeywordSuffix() { - return keywordSuffix; - } - - public String getAliasPrefix() { - return aliasPrefix; - } - - public String getAliasSuffix() { - return aliasSuffix; - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/util/ExecuteShellUtil.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/util/ExecuteShellUtil.java deleted file mode 100644 index a5d5b59..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/util/ExecuteShellUtil.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.util; - -import cn.hutool.core.io.IoUtil; -import com.jcraft.jsch.ChannelShell; -import com.jcraft.jsch.JSch; -import com.jcraft.jsch.Session; -import lombok.extern.slf4j.Slf4j; - -import java.io.*; -import java.util.Vector; - -/** - * 执行shell命令 - * - * @author: ZhangHouYing - * @date: 2019/8/10 - */ -@Slf4j -public class ExecuteShellUtil { - - private Vector stdout; - - Session session; - - public ExecuteShellUtil(final String ipAddress, final String username, final String password,int port) { - try { - JSch jsch = new JSch(); - session = jsch.getSession(username, ipAddress, port); - session.setPassword(password); - session.setConfig("StrictHostKeyChecking", "no"); - session.connect(3000); - } catch (Exception e) { - log.error(e.getMessage(),e); - } - - } - - public int execute(final String command) { - int returnCode = 0; - ChannelShell channel = null; - PrintWriter printWriter = null; - BufferedReader input = null; - stdout = new Vector(); - try { - channel = (ChannelShell) session.openChannel("shell"); - channel.connect(); - input = new BufferedReader(new InputStreamReader(channel.getInputStream())); - printWriter = new PrintWriter(channel.getOutputStream()); - printWriter.println(command); - printWriter.println("exit"); - printWriter.flush(); - log.info("The remote command is: "); - String line; - while ((line = input.readLine()) != null) { - stdout.add(line); - System.out.println(line); - } - } catch (Exception e) { - log.error(e.getMessage(),e); - return -1; - }finally { - IoUtil.close(printWriter); - IoUtil.close(input); - if (channel != null) { - channel.disconnect(); - } - } - return returnCode; - } - - public void close(){ - if (session != null) { - session.disconnect(); - } - } - - public String executeForResult(String command) { - execute(command); - StringBuilder sb = new StringBuilder(); - for (String str : stdout) { - sb.append(str); - } - return sb.toString(); - } - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/util/ScpClientUtil.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/util/ScpClientUtil.java deleted file mode 100644 index 7cb83aa..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/util/ScpClientUtil.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.util; - -import ch.ethz.ssh2.Connection; -import ch.ethz.ssh2.SCPClient; -import com.google.common.collect.Maps; - -import java.io.IOException; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * 远程执行linux命令 - * @author: ZhangHouYing - * @date: 2019-08-10 10:06 - */ -public class ScpClientUtil { - - static private Map instance = Maps.newHashMap(); - - static synchronized public ScpClientUtil getInstance(String ip, int port, String username, String password) { - if (instance.get(ip) == null) { - instance.put(ip, new ScpClientUtil(ip, port, username, password)); - } - return instance.get(ip); - } - - public ScpClientUtil(String ip, int port, String username, String password) { - this.ip = ip; - this.port = port; - this.username = username; - this.password = password; - } - - public void getFile(String remoteFile, String localTargetDirectory) { - Connection conn = new Connection(ip, port); - try { - conn.connect(); - boolean isAuthenticated = conn.authenticateWithPassword(username, password); - if (!isAuthenticated) { - System.err.println("authentication failed"); - } - SCPClient client = new SCPClient(conn); - client.get(remoteFile, localTargetDirectory); - } catch (IOException ex) { - Logger.getLogger(SCPClient.class.getName()).log(Level.SEVERE, null, ex); - }finally{ - conn.close(); - } - } - - public void putFile(String localFile, String remoteTargetDirectory) { - putFile(localFile, null, remoteTargetDirectory); - } - - public void putFile(String localFile, String remoteFileName, String remoteTargetDirectory) { - putFile(localFile, remoteFileName, remoteTargetDirectory,null); - } - - public void putFile(String localFile, String remoteFileName, String remoteTargetDirectory, String mode) { - Connection conn = new Connection(ip, port); - try { - conn.connect(); - boolean isAuthenticated = conn.authenticateWithPassword(username, password); - if (!isAuthenticated) { - System.err.println("authentication failed"); - } - SCPClient client = new SCPClient(conn); - if ((mode == null) || (mode.length() == 0)) { - mode = "0600"; - } - if (remoteFileName == null) { - client.put(localFile, remoteTargetDirectory); - } else { - client.put(localFile, remoteFileName, remoteTargetDirectory, mode); - } - } catch (IOException ex) { - Logger.getLogger(ScpClientUtil.class.getName()).log(Level.SEVERE, null, ex); - }finally{ - conn.close(); - } - } - - private String ip; - private int port; - private String username; - private String password; - - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/util/SqlUtils.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/util/SqlUtils.java deleted file mode 100644 index d7e06b1..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/util/SqlUtils.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.util; - -import com.alibaba.druid.pool.DruidDataSource; -import com.alibaba.druid.util.StringUtils; -import com.google.common.collect.Lists; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.utils.CloseUtil; -import javax.sql.DataSource; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; -import java.sql.*; -import java.util.List; - -/** - * @author / - */ -@Slf4j -public class SqlUtils { - - /** - * 获取数据源 - * - * @param jdbcUrl / - * @param userName / - * @param password / - * @return DataSource - */ - private static DataSource getDataSource(String jdbcUrl, String userName, String password) { - DruidDataSource druidDataSource = new DruidDataSource(); - String className; - try { - className = DriverManager.getDriver(jdbcUrl.trim()).getClass().getName(); - } catch (SQLException e) { - throw new RuntimeException("Get class name error: =" + jdbcUrl); - } - if (StringUtils.isEmpty(className)) { - DataTypeEnum dataTypeEnum = DataTypeEnum.urlOf(jdbcUrl); - if (null == dataTypeEnum) { - throw new RuntimeException("Not supported data type: jdbcUrl=" + jdbcUrl); - } - druidDataSource.setDriverClassName(dataTypeEnum.getDriver()); - } else { - druidDataSource.setDriverClassName(className); - } - - - druidDataSource.setUrl(jdbcUrl); - druidDataSource.setUsername(userName); - druidDataSource.setPassword(password); - // 配置获取连接等待超时的时间 - druidDataSource.setMaxWait(3000); - // 配置初始化大小、最小、最大 - druidDataSource.setInitialSize(1); - druidDataSource.setMinIdle(1); - druidDataSource.setMaxActive(1); - - // 如果链接出现异常则直接判定为失败而不是一直重试 - druidDataSource.setBreakAfterAcquireFailure(true); - try { - druidDataSource.init(); - } catch (SQLException e) { - log.error("Exception during pool initialization", e); - throw new RuntimeException(e.getMessage()); - } - - return druidDataSource; - } - - private static Connection getConnection(String jdbcUrl, String userName, String password) { - DataSource dataSource = getDataSource(jdbcUrl, userName, password); - Connection connection = null; - try { - connection = dataSource.getConnection(); - } catch (Exception ignored) {} - try { - int timeOut = 5; - if (null == connection || connection.isClosed() || !connection.isValid(timeOut)) { - log.info("connection is closed or invalid, retry get connection!"); - connection = dataSource.getConnection(); - } - } catch (Exception e) { - log.error("create connection error, jdbcUrl: {}", jdbcUrl); - throw new RuntimeException("create connection error, jdbcUrl: " + jdbcUrl); - } finally { - CloseUtil.close(connection); - } - return connection; - } - - private static void releaseConnection(Connection connection) { - if (null != connection) { - try { - connection.close(); - } catch (Exception e) { - log.error(e.getMessage(),e); - log.error("connection close error:" + e.getMessage()); - } - } - } - - public static boolean testConnection(String jdbcUrl, String userName, String password) { - Connection connection = null; - try { - connection = getConnection(jdbcUrl, userName, password); - if (null != connection) { - return true; - } - } catch (Exception e) { - log.info("Get connection failed:" + e.getMessage()); - } finally { - releaseConnection(connection); - } - return false; - } - - public static String executeFile(String jdbcUrl, String userName, String password, File sqlFile) { - Connection connection = getConnection(jdbcUrl, userName, password); - try { - batchExecute(connection, readSqlList(sqlFile)); - } catch (Exception e) { - log.error("sql脚本执行发生异常:{}",e.getMessage()); - return e.getMessage(); - }finally { - releaseConnection(connection); - } - return "success"; - } - - - /** - * 批量执行sql - * @param connection / - * @param sqlList / - */ - public static void batchExecute(Connection connection, List sqlList) { - Statement st = null; - try { - st = connection.createStatement(); - for (String sql : sqlList) { - if (sql.endsWith(";")) { - sql = sql.substring(0, sql.length() - 1); - } - st.addBatch(sql); - } - st.executeBatch(); - } catch (SQLException throwables) { - throwables.printStackTrace(); - } finally { - CloseUtil.close(st); - } - } - - /** - * 将文件中的sql语句以;为单位读取到列表中 - * @param sqlFile / - * @return / - * @throws Exception e - */ - private static List readSqlList(File sqlFile) throws Exception { - List sqlList = Lists.newArrayList(); - StringBuilder sb = new StringBuilder(); - try (BufferedReader reader = new BufferedReader(new InputStreamReader( - new FileInputStream(sqlFile), StandardCharsets.UTF_8))) { - String tmp; - while ((tmp = reader.readLine()) != null) { - log.info("line:{}", tmp); - if (tmp.endsWith(";")) { - sb.append(tmp); - sqlList.add(sb.toString()); - sb.delete(0, sb.length()); - } else { - sb.append(tmp); - } - } - if (!"".endsWith(sb.toString().trim())) { - sqlList.add(sb.toString()); - } - } - - return sqlList; - } - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/websocket/MsgType.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/websocket/MsgType.java deleted file mode 100644 index 2fc473d..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/websocket/MsgType.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.websocket; - -/** - * @author ZhangHouYing - * @date 2019-08-10 9:56 - */ -public enum MsgType { - /** 连接 */ - CONNECT, - /** 关闭 */ - CLOSE, - /** 信息 */ - INFO, - /** 错误 */ - ERROR -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/websocket/SocketMsg.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/websocket/SocketMsg.java deleted file mode 100644 index ade33a2..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/websocket/SocketMsg.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.websocket; - -import lombok.Data; - -/** - * @author ZhangHouYing - * @date 2019-08-10 9:55 - */ -@Data -public class SocketMsg { - private String msg; - private MsgType msgType; - - public SocketMsg(String msg, MsgType msgType) { - this.msg = msg; - this.msgType = msgType; - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/websocket/WebSocketServer.java b/wjcy-system/src/main/java/me/zhengjie/modules/mnt/websocket/WebSocketServer.java deleted file mode 100644 index 9c92165..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/mnt/websocket/WebSocketServer.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.mnt.websocket; - -import com.alibaba.fastjson.JSONObject; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.websocket.*; -import javax.websocket.server.PathParam; -import javax.websocket.server.ServerEndpoint; -import java.io.IOException; -import java.util.Objects; -import java.util.concurrent.CopyOnWriteArraySet; -/** - * @author ZhangHouYing - * @date 2019-08-10 15:46 - */ -@ServerEndpoint("/webSocket/{sid}") -@Slf4j -@Component -public class WebSocketServer { - - /** - * concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。 - */ - private static CopyOnWriteArraySet webSocketSet = new CopyOnWriteArraySet(); - - /** - * 与某个客户端的连接会话,需要通过它来给客户端发送数据 - */ - private Session session; - - /** - * 接收sid - */ - private String sid=""; - /** - * 连接建立成功调用的方法 - * */ - @OnOpen - public void onOpen(Session session,@PathParam("sid") String sid) { - this.session = session; - //如果存在就先删除一个,防止重复推送消息 - for (WebSocketServer webSocket:webSocketSet) { - if (webSocket.sid.equals(sid)) { - webSocketSet.remove(webSocket); - } - } - webSocketSet.add(this); - this.sid=sid; - } - - /** - * 连接关闭调用的方法 - */ - @OnClose - public void onClose() { - webSocketSet.remove(this); - } - - /** - * 收到客户端消息后调用的方法 - * @param message 客户端发送过来的消息*/ - @OnMessage - public void onMessage(String message, Session session) { - log.info("收到来"+sid+"的信息:"+message); - //群发消息 - for (WebSocketServer item : webSocketSet) { - try { - item.sendMessage(message); - } catch (IOException e) { - log.error(e.getMessage(),e); - } - } - } - - @OnError - public void onError(Session session, Throwable error) { - log.error("发生错误"); - error.printStackTrace(); - } - /** - * 实现服务器主动推送 - */ - private void sendMessage(String message) throws IOException { - this.session.getBasicRemote().sendText(message); - } - - - /** - * 群发自定义消息 - * */ - public static void sendInfo(SocketMsg socketMsg,@PathParam("sid") String sid) throws IOException { - String message = JSONObject.toJSONString(socketMsg); - log.info("推送消息到"+sid+",推送内容:"+message); - for (WebSocketServer item : webSocketSet) { - try { - //这里可以设定只推送给这个sid的,为null则全部推送 - if(sid==null) { - item.sendMessage(message); - }else if(item.sid.equals(sid)){ - item.sendMessage(message); - } - } catch (IOException ignored) { } - } - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - WebSocketServer that = (WebSocketServer) o; - return Objects.equals(session, that.session) && - Objects.equals(sid, that.sid); - } - - @Override - public int hashCode() { - return Objects.hash(session, sid); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/config/JobRunner.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/config/JobRunner.java deleted file mode 100644 index 9b903e9..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/config/JobRunner.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.quartz.config; - -import cn.hutool.json.JSONUtil; -import lombok.RequiredArgsConstructor; -import me.zhengjie.modules.quartz.domain.QuartzJob; -import me.zhengjie.modules.quartz.repository.QuartzJobRepository; -import me.zhengjie.modules.quartz.utils.QuartzManage; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.boot.ApplicationArguments; -import org.springframework.boot.ApplicationRunner; -import org.springframework.stereotype.Component; - -import java.util.List; - -/** - * @author Zheng Jie - * @date 2019-01-07 - */ -@Component -@RequiredArgsConstructor -public class JobRunner implements ApplicationRunner { - private static final Logger log = LoggerFactory.getLogger(JobRunner.class); - private final QuartzJobRepository quartzJobRepository; - private final QuartzManage quartzManage; - - /** - * 项目启动时重新激活启用的定时任务 - * - * @param applicationArguments / - */ - @Override - public void run(ApplicationArguments applicationArguments) { - log.info("--------------------注入定时任务---------------------"); - List quartzJobs = quartzJobRepository.findByIsPauseIsFalse(); - quartzJobs.forEach(quartzManage::addJob); - log.info("--------------------定时任务注入完成---------------------"); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/config/QuartzConfig.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/config/QuartzConfig.java deleted file mode 100644 index 99f2e50..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/config/QuartzConfig.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.quartz.config; - -import org.quartz.spi.TriggerFiredBundle; -import org.springframework.beans.factory.config.AutowireCapableBeanFactory; -import org.springframework.context.annotation.Configuration; -import org.springframework.scheduling.quartz.AdaptableJobFactory; -import org.springframework.stereotype.Component; - -/** - * 定时任务配置 - * @author / - * @date 2019-01-07 - */ -@Configuration -public class QuartzConfig { - - /** - * 解决Job中注入Spring Bean为null的问题 - */ - @Component("quartzJobFactory") - public static class QuartzJobFactory extends AdaptableJobFactory { - - private final AutowireCapableBeanFactory capableBeanFactory; - - public QuartzJobFactory(AutowireCapableBeanFactory capableBeanFactory) { - this.capableBeanFactory = capableBeanFactory; - } - - @Override - protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception { - //调用父类的方法,把Job注入到spring中 - Object jobInstance = super.createJobInstance(bundle); - capableBeanFactory.autowireBean(jobInstance); - return jobInstance; - } - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/domain/QuartzJob.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/domain/QuartzJob.java deleted file mode 100644 index d4048fc..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/domain/QuartzJob.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.quartz.domain; - -import io.swagger.annotations.ApiModelProperty; -import lombok.Getter; -import lombok.Setter; -import me.zhengjie.annotation.Query; -import me.zhengjie.base.BaseEntity; -import javax.persistence.*; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import java.io.Serializable; - -/** - * @author Zheng Jie - * @date 2019-01-07 - */ -@Getter -@Setter -@Entity -@Table(name = "sys_quartz_job") -public class QuartzJob extends BaseEntity implements Serializable { - - public static final String JOB_KEY = "JOB_KEY"; - - @Id - @Column(name = "job_id") - @NotNull(groups = {Update.class}) - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - /** 任务编号 -雪花算法生成 */ - private Long taskNum; - - @ApiModelProperty(value = "类型 1.普通 2.影刀") - private Integer type = 1; - - @Transient - @ApiModelProperty(value = "用于子任务唯一标识", hidden = true) - private String uuid; - - @ApiModelProperty(value = "定时器名称") - private String jobName; - - @NotBlank - @ApiModelProperty(value = "Bean名称") - private String beanName; - - @NotBlank - @ApiModelProperty(value = "方法名称") - private String methodName; - - @ApiModelProperty(value = "参数") - private String params; - - @NotBlank - @ApiModelProperty(value = "cron表达式") - private String cronExpression; - - @ApiModelProperty(value = "状态,暂时或启动") - private Boolean isPause = false; - - @ApiModelProperty(value = "负责人") - private String personInCharge; - - @ApiModelProperty(value = "报警邮箱") - private String email; - - @ApiModelProperty(value = "子任务") - private String subTask; - - @ApiModelProperty(value = "失败后暂停") - private Boolean pauseAfterFailure; - - @NotBlank - @ApiModelProperty(value = "备注") - private String description; -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/domain/QuartzLog.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/domain/QuartzLog.java deleted file mode 100644 index 4dc510b..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/domain/QuartzLog.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.quartz.domain; - -import io.swagger.annotations.ApiModelProperty; -import lombok.Data; -import org.hibernate.annotations.CreationTimestamp; -import javax.persistence.*; -import java.io.Serializable; -import java.sql.Timestamp; - -/** - * @author Zheng Jie - * @date 2019-01-07 - */ -@Entity -@Data -@Table(name = "sys_quartz_log") -public class QuartzLog implements Serializable { - - @Id - @Column(name = "log_id") - @ApiModelProperty(value = "ID", hidden = true) - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ApiModelProperty(value = "任务名称", hidden = true) - private String jobName; - - @ApiModelProperty(value = "类型 1.普通 2.影刀") - private Integer type = 1; - - @ApiModelProperty(value = "bean名称", hidden = true) - private String beanName; - - @ApiModelProperty(value = "方法名称", hidden = true) - private String methodName; - - @ApiModelProperty(value = "参数", hidden = true) - private String params; - - @ApiModelProperty(value = "cron表达式", hidden = true) - private String cronExpression; - - @ApiModelProperty(value = "状态", hidden = true) - private Boolean isSuccess; - - @ApiModelProperty(value = "异常详情", hidden = true) - private String exceptionDetail; - - @ApiModelProperty(value = "执行耗时", hidden = true) - private Long time; - - @CreationTimestamp - @ApiModelProperty(value = "创建时间", hidden = true) - private Timestamp createTime; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/repository/QuartzJobRepository.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/repository/QuartzJobRepository.java deleted file mode 100644 index 79b222b..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/repository/QuartzJobRepository.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.quartz.repository; - -import me.zhengjie.modules.quartz.domain.QuartzJob; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; -import java.util.List; - -/** - * @author Zheng Jie - * @date 2019-01-07 - */ -public interface QuartzJobRepository extends JpaRepository, JpaSpecificationExecutor { - - /** - * 查询启用的任务 - * @return List - */ - List findByIsPauseIsFalse(); -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/repository/QuartzLogRepository.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/repository/QuartzLogRepository.java deleted file mode 100644 index db724aa..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/repository/QuartzLogRepository.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.quartz.repository; - -import me.zhengjie.modules.quartz.domain.QuartzLog; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; - -/** - * @author Zheng Jie - * @date 2019-01-07 - */ -public interface QuartzLogRepository extends JpaRepository, JpaSpecificationExecutor { - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/rest/QuartzJobController.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/rest/QuartzJobController.java deleted file mode 100644 index 7a4a3db..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/rest/QuartzJobController.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.quartz.rest; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.annotation.AnonymousAccess; -import me.zhengjie.annotation.Log; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.modules.quartz.domain.QuartzJob; -import me.zhengjie.modules.quartz.service.QuartzJobService; -import me.zhengjie.modules.quartz.service.dto.JobQueryCriteria; -import org.springframework.data.domain.Pageable; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.Set; - -/** - * @author Zheng Jie - * @date 2019-01-07 - */ -@Slf4j -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/jobs") -@Api(tags = "系统:定时任务管理") -public class QuartzJobController { - - private static final String ENTITY_NAME = "quartzJob"; - private final QuartzJobService quartzJobService; - - @ApiOperation("查询定时任务") - @GetMapping - @PreAuthorize("@el.check('timing:list')") - public ResponseEntity query(JobQueryCriteria criteria, Pageable pageable){ - return new ResponseEntity<>(quartzJobService.queryAll(criteria,pageable), HttpStatus.OK); - } - - @ApiOperation("导出任务数据") - @GetMapping(value = "/download") - @PreAuthorize("@el.check('timing:list')") - public void download(HttpServletResponse response, JobQueryCriteria criteria) throws IOException { - quartzJobService.download(quartzJobService.queryAll(criteria), response); - } - - @ApiOperation("导出日志数据") - @GetMapping(value = "/logs/download") - @PreAuthorize("@el.check('timing:list')") - public void downloadLog(HttpServletResponse response, JobQueryCriteria criteria) throws IOException { - quartzJobService.downloadLog(quartzJobService.queryAllLog(criteria), response); - } - - @ApiOperation("查询任务执行日志") - @GetMapping(value = "/logs") - @PreAuthorize("@el.check('timing:list')") - public ResponseEntity queryJobLog(JobQueryCriteria criteria, Pageable pageable){ - return new ResponseEntity<>(quartzJobService.queryAllLog(criteria,pageable), HttpStatus.OK); - } - - @Log("新增定时任务") - @ApiOperation("新增定时任务") - @PostMapping - @PreAuthorize("@el.check('timing:add')") - public ResponseEntity create(@Validated @RequestBody QuartzJob resources){ - if (resources.getId() != null) { - throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID"); - } - quartzJobService.create(resources); - return new ResponseEntity<>(HttpStatus.CREATED); - } - - @Log("修改定时任务") - @ApiOperation("修改定时任务") - @PutMapping - @PreAuthorize("@el.check('timing:edit')") - public ResponseEntity update(@Validated(QuartzJob.Update.class) @RequestBody QuartzJob resources){ - quartzJobService.update(resources); - return new ResponseEntity<>(HttpStatus.NO_CONTENT); - } - - @Log("更改定时任务状态") - @ApiOperation("更改定时任务状态") - @PutMapping(value = "/{id}") - @PreAuthorize("@el.check('timing:edit')") - public ResponseEntity update(@PathVariable Long id){ - quartzJobService.updateIsPause(quartzJobService.findById(id)); - return new ResponseEntity<>(HttpStatus.NO_CONTENT); - } - - @Log("执行定时任务") - @ApiOperation("执行定时任务") - @PutMapping(value = "/exec/{id}") - @PreAuthorize("@el.check('timing:edit')") - public ResponseEntity execution(@PathVariable Long id){ - quartzJobService.execution(quartzJobService.findById(id)); - return new ResponseEntity<>(HttpStatus.NO_CONTENT); - } - - @Log("删除定时任务") - @ApiOperation("删除定时任务") - @DeleteMapping - @PreAuthorize("@el.check('timing:del')") - public ResponseEntity delete(@RequestBody Set ids){ - quartzJobService.delete(ids); - return new ResponseEntity<>(HttpStatus.OK); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/service/QuartzJobService.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/service/QuartzJobService.java deleted file mode 100644 index 7be008e..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/service/QuartzJobService.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.quartz.service; - -import me.zhengjie.modules.quartz.domain.QuartzJob; -import me.zhengjie.modules.quartz.domain.QuartzLog; -import me.zhengjie.modules.quartz.service.dto.JobQueryCriteria; -import org.springframework.data.domain.Pageable; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.List; -import java.util.Set; - -/** - * @author Zheng Jie - * @date 2019-01-07 - */ -public interface QuartzJobService { - - /** - * 分页查询 - * @param criteria 条件 - * @param pageable 分页参数 - * @return / - */ - Object queryAll(JobQueryCriteria criteria, Pageable pageable); - - /** - * 查询全部 - * @param criteria 条件 - * @return / - */ - List queryAll(JobQueryCriteria criteria); - - /** - * 查询全部 - * @return / - */ - void delAllLog(); - - /** - * 分页查询日志 - * @param criteria 条件 - * @param pageable 分页参数 - * @return / - */ - Object queryAllLog(JobQueryCriteria criteria, Pageable pageable); - - /** - * 查询全部 - * @param criteria 条件 - * @return / - */ - List queryAllLog(JobQueryCriteria criteria); - - /** - * 创建 - * @param resources / - */ - void create(QuartzJob resources); - - /** - * 编辑 - * @param resources / - */ - void update(QuartzJob resources); - - /** - * 删除任务 - * @param ids / - */ - void delete(Set ids); - - /** - * 根据ID查询 - * @param id ID - * @return / - */ - QuartzJob findById(Long id); - - /** - * 更改定时任务状态 - * @param quartzJob / - */ - void updateIsPause(QuartzJob quartzJob); - - /** - * 立即执行定时任务 - * @param quartzJob / - */ - void execution(QuartzJob quartzJob); - - /** - * 导出定时任务 - * @param queryAll 待导出的数据 - * @param response / - * @throws IOException / - */ - void download(List queryAll, HttpServletResponse response) throws IOException; - - /** - * 导出定时任务日志 - * @param queryAllLog 待导出的数据 - * @param response / - * @throws IOException / - */ - void downloadLog(List queryAllLog, HttpServletResponse response) throws IOException; - - /** - * 执行子任务 - * @param tasks / - * @throws InterruptedException / - */ - void executionSubJob(String[] tasks) throws InterruptedException; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/service/SysQuartzJobService.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/service/SysQuartzJobService.java deleted file mode 100644 index d2a58f1..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/service/SysQuartzJobService.java +++ /dev/null @@ -1,77 +0,0 @@ -package me.zhengjie.modules.quartz.service; - -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.service.IService; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.SysQuartzJob; -import me.zhengjie.modules.group.dto.SysQuartzJobAddDTO; -import me.zhengjie.modules.group.dto.SysQuartzJobUpdateDTO; -import me.zhengjie.service.vo.SysQuartzJobListVO; -import me.zhengjie.utils.PageUtils; - -/** - * 定时任务(SysQuartzJob)表服务接口 - * - * @author zhw - * @since 2022-07-21 - */ -public interface SysQuartzJobService extends IService { - - PageUtils searchPageList(IPage page, Wrapper wrapper); - - /** - * 根据任务id修改任务运行状态 - * @param jobId - * @return boolean - */ - Boolean modifyJobStatus(Long jobId); - - /** - * 根据任务id修改任务信息 - * @param dto - * @return boolean - */ - Dto updateQuartzJobById(SysQuartzJobUpdateDTO dto); - - /** - * 根据任务id删除影刀任务 - * @param id - * @return boolean - */ - Boolean deleteQuartzJobById(Long id); - - /** - * 重新新建任务-为了任务失败做的 - * @param sysQuartzJob - * @return - */ - public Boolean reAddQuartzJob(SysQuartzJob sysQuartzJob); - - /** - * 新增影刀任务信息 - * @param dto - * @return boolean - */ - Dto addQuartzJob(SysQuartzJobAddDTO dto); - - /** - * 执行影刀任务信息 - * @param id - * @return boolean - */ - Boolean executionById(Long id); - - /** - * 根据刷单item拼装参数 - */ - String assemblyParamAccordingToItem(String params, String taskName, Long taskNum); - - /** - * 更加任务编号获取任务信息 - * @param taskNum - * @return - */ - SysQuartzJob getByTaskNum(String taskNum); -} - diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/service/dto/JobQueryCriteria.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/service/dto/JobQueryCriteria.java deleted file mode 100644 index 89d8070..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/service/dto/JobQueryCriteria.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.quartz.service.dto; - -import lombok.Data; -import me.zhengjie.annotation.Query; -import java.sql.Timestamp; -import java.util.List; - -/** - * @author Zheng Jie - * @date 2019-6-4 10:33:02 - */ -@Data -public class JobQueryCriteria { - - @Query(type = Query.Type.INNER_LIKE) - private String jobName; - - @Query - private Boolean isSuccess; - - @Query - private Integer type = 1; - - @Query(type = Query.Type.BETWEEN) - private List createTime; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/service/impl/QuartzJobServiceImpl.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/service/impl/QuartzJobServiceImpl.java deleted file mode 100644 index 35c6070..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/service/impl/QuartzJobServiceImpl.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.quartz.service.impl; - -import cn.hutool.core.lang.Snowflake; -import cn.hutool.core.util.IdUtil; -import cn.hutool.core.util.StrUtil; -import lombok.RequiredArgsConstructor; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.modules.quartz.domain.QuartzJob; -import me.zhengjie.modules.quartz.domain.QuartzLog; -import me.zhengjie.modules.quartz.repository.QuartzJobRepository; -import me.zhengjie.modules.quartz.repository.QuartzLogRepository; -import me.zhengjie.modules.quartz.service.QuartzJobService; -import me.zhengjie.modules.quartz.service.dto.JobQueryCriteria; -import me.zhengjie.modules.quartz.utils.QuartzManage; -import me.zhengjie.utils.*; -import org.quartz.CronExpression; -import org.springframework.data.domain.Pageable; -import org.springframework.scheduling.annotation.Async; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.*; - -/** - * @author Zheng Jie - * @date 2019-01-07 - */ -@RequiredArgsConstructor -@Service(value = "quartzJobService") -public class QuartzJobServiceImpl implements QuartzJobService { - - private final QuartzJobRepository quartzJobRepository; - private final QuartzLogRepository quartzLogRepository; - private final QuartzManage quartzManage; - private final RedisUtils redisUtils; - private final Snowflake snowflake; - - @Override - public Object queryAll(JobQueryCriteria criteria, Pageable pageable){ - return PageUtil.toPage(quartzJobRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable)); - } - - @Override - public Object queryAllLog(JobQueryCriteria criteria, Pageable pageable){ - return PageUtil.toPage(quartzLogRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable)); - } - - @Override - public List queryAll(JobQueryCriteria criteria) { - return quartzJobRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)); - } - - @Override - public void delAllLog() { - quartzLogRepository.deleteAll(); - } - - @Override - public List queryAllLog(JobQueryCriteria criteria) { - return quartzLogRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)); - } - - @Override - public QuartzJob findById(Long id) { - QuartzJob quartzJob = quartzJobRepository.findById(id).orElseGet(QuartzJob::new); - ValidationUtil.isNull(quartzJob.getId(),"QuartzJob","id",id); - return quartzJob; - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void create(QuartzJob resources) { - if (!CronExpression.isValidExpression(resources.getCronExpression())){ - throw new BadRequestException("cron表达式格式错误"); - } - resources.setTaskNum(snowflake.nextId()); - resources = quartzJobRepository.save(resources); - quartzManage.addJob(resources); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void update(QuartzJob resources) { - if (!CronExpression.isValidExpression(resources.getCronExpression())){ - throw new BadRequestException("cron表达式格式错误"); - } - if(StringUtils.isNotBlank(resources.getSubTask())){ - List tasks = Arrays.asList(resources.getSubTask().split("[,,]")); - if (tasks.contains(resources.getId().toString())) { - throw new BadRequestException("子任务中不能添加当前任务ID"); - } - } - resources = quartzJobRepository.save(resources); - quartzManage.updateJobCron(resources); - } - - @Override - public void updateIsPause(QuartzJob quartzJob) { - if (quartzJob.getIsPause()) { - quartzManage.resumeJob(quartzJob); - quartzJob.setIsPause(false); - } else { - quartzManage.pauseJob(quartzJob); - quartzJob.setIsPause(true); - } - quartzJobRepository.save(quartzJob); - } - - @Override - public void execution(QuartzJob quartzJob) { - quartzManage.runJobNow(quartzJob); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Set ids) { - for (Long id : ids) { - QuartzJob quartzJob = findById(id); - quartzManage.deleteJob(quartzJob); - quartzJobRepository.delete(quartzJob); - } - } - - @Async - @Override - @Transactional(rollbackFor = Exception.class) - public void executionSubJob(String[] tasks) throws InterruptedException { - for (String id : tasks) { - if (StrUtil.isBlank(id)) { - // 如果是手动清除子任务id,会出现id为空字符串的问题 - continue; - } - QuartzJob quartzJob = findById(Long.parseLong(id)); - // 执行任务 - String uuid = IdUtil.simpleUUID(); - quartzJob.setUuid(uuid); - // 执行任务 - execution(quartzJob); - // 获取执行状态,如果执行失败则停止后面的子任务执行 - Boolean result = (Boolean) redisUtils.get(uuid); - while (result == null) { - // 休眠5秒,再次获取子任务执行情况 - Thread.sleep(5000); - result = (Boolean) redisUtils.get(uuid); - } - if(!result){ - redisUtils.del(uuid); - break; - } - } - } - - @Override - public void download(List quartzJobs, HttpServletResponse response) throws IOException { - List> list = new ArrayList<>(); - for (QuartzJob quartzJob : quartzJobs) { - Map map = new LinkedHashMap<>(); - map.put("任务名称", quartzJob.getJobName()); - map.put("Bean名称", quartzJob.getBeanName()); - map.put("执行方法", quartzJob.getMethodName()); - map.put("参数", quartzJob.getParams()); - map.put("表达式", quartzJob.getCronExpression()); - map.put("状态", quartzJob.getIsPause() ? "暂停中" : "运行中"); - map.put("描述", quartzJob.getDescription()); - map.put("创建日期", quartzJob.getCreateTime()); - list.add(map); - } - FileUtil.downloadExcel(list, response); - } - - @Override - public void downloadLog(List queryAllLog, HttpServletResponse response) throws IOException { - List> list = new ArrayList<>(); - for (QuartzLog quartzLog : queryAllLog) { - Map map = new LinkedHashMap<>(); - map.put("任务名称", quartzLog.getJobName()); - map.put("Bean名称", quartzLog.getBeanName()); - map.put("执行方法", quartzLog.getMethodName()); - map.put("参数", quartzLog.getParams()); - map.put("表达式", quartzLog.getCronExpression()); - map.put("异常详情", quartzLog.getExceptionDetail()); - map.put("耗时/毫秒", quartzLog.getTime()); - map.put("状态", quartzLog.getIsSuccess() ? "成功" : "失败"); - map.put("创建日期", quartzLog.getCreateTime()); - list.add(map); - } - FileUtil.downloadExcel(list, response); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/service/impl/SysQuartzJobServiceImpl.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/service/impl/SysQuartzJobServiceImpl.java deleted file mode 100644 index 45b09bd..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/service/impl/SysQuartzJobServiceImpl.java +++ /dev/null @@ -1,521 +0,0 @@ -package me.zhengjie.modules.quartz.service.impl; - -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.date.DateUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.json.JSONUtil; -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import lombok.RequiredArgsConstructor; -import me.zhengjie.config.SystemConfig; -import me.zhengjie.dao.SysQuartzJobDao; -import me.zhengjie.dto.Dto; -import me.zhengjie.entity.*; -import me.zhengjie.entity.quartz.Boss; -import me.zhengjie.entity.quartz.Param; -import me.zhengjie.entity.quartz.Params; -import me.zhengjie.enums.*; -import me.zhengjie.error.ErrorCodeEnum; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.modules.group.dto.SysQuartzJobAddDTO; -import me.zhengjie.modules.group.dto.SysQuartzJobUpdateDTO; -import me.zhengjie.modules.quartz.domain.QuartzJob; -import me.zhengjie.modules.quartz.service.QuartzJobService; -import me.zhengjie.modules.quartz.service.SysQuartzJobService; -import me.zhengjie.modules.quartz.utils.QuartzManage; -import me.zhengjie.service.*; -import me.zhengjie.service.vo.CtBrowseDetailVO; -import me.zhengjie.service.vo.SysQuartzJobListVO; -import me.zhengjie.service.vo.dhaddcar.DhAddCarListVO; -import me.zhengjie.service.vo.dhaddcar.DhAddCarYdParamsVO; -import me.zhengjie.service.vo.dhcargood.DhCarGoodKeyVO; -import me.zhengjie.service.vo.dhcargood.DhCarGoodLinkVO; -import me.zhengjie.service.vo.dhcarorder.DhCarOrderParamsVO; -import me.zhengjie.utils.PageUtils; -import me.zhengjie.utils.StringUtils; -import org.quartz.CronExpression; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * 定时任务(SysQuartzJob)表服务实现类 - * - * @author rch - * @since 2022-07-20 - */ -@Service -@RequiredArgsConstructor -public class SysQuartzJobServiceImpl extends ServiceImpl implements SysQuartzJobService { - - @Resource - private SysQuartzJobDao sysQuartzJobDao; - @Resource - private QuartzJobService quartzJobService; - @Resource - private CtApplyService ctApplyService; - @Resource - private CtClickFarmingService ctClickFarmingService; - @Resource - private DhAddCarService dhAddCarService; - @Resource - private DhAddCarOrderService dhAddCarOrderService; - @Resource - private CtClickOrderService ctClickOrderService; - @Resource - private CtBrowseService ctBrowseService; - private final QuartzManage quartzManage; - - @Override - public PageUtils searchPageList(IPage page, Wrapper wrapper) { - sysQuartzJobDao.searchPageList(page, wrapper); - return new PageUtils(page.getTotal(), page.getRecords()); - } - - @Override - public Boolean modifyJobStatus(Long jobId) { - SysQuartzJob sysQuartzJobIsExist = getById(jobId); - if (sysQuartzJobIsExist == null) { - return false; - } else { - QuartzJob quartzJob = new QuartzJob(); - BeanUtil.copyProperties(sysQuartzJobIsExist, quartzJob); - quartzJob.setId(sysQuartzJobIsExist.getJobId()); - - quartzJob.setType(TaskTypeEnum.SHADOW_KNIFE.value()); - SysQuartzJob updateSysQuartzJob = new SysQuartzJob(); - updateSysQuartzJob.setJobId(jobId); - - if (sysQuartzJobIsExist.getIsPause() == 1) { - quartzManage.resumeJob(quartzJob); - updateSysQuartzJob.setIsPause(0); - } else { - quartzManage.pauseJob(quartzJob); - updateSysQuartzJob.setIsPause(1); - } - return updateById(updateSysQuartzJob); - } - } - - @Override - public Dto updateQuartzJobById(SysQuartzJobUpdateDTO dto) { - SysQuartzJob sysQuartzJob = getById(dto.getJobId()); - if (sysQuartzJob == null) { - return Dto.getInstance(ErrorCodeEnum.ERROR_NOT_FIND_JOB); - } - if (!CronExpression.isValidExpression(dto.getCronExpression())) { - //hrow new BadRequestException("cron表达式格式错误"); - return Dto.returnErrorResult("cron表达式格式错误"); - } - if (StringUtils.isNotBlank(dto.getSubTask())) { - List tasks = Arrays.asList(dto.getSubTask().split("[,,]")); - if (tasks.contains(dto.getJobId().toString())) { - //throw new BadRequestException("子任务中不能添加当前任务ID"); - return Dto.returnErrorResult("子任务中不能添加当前任务ID"); - } - } - SysQuartzJob updateSysQuartzJob = new SysQuartzJob(); - - updateSysQuartzJob.setJobId(dto.getJobId()); - BeanUtil.copyProperties(dto, updateSysQuartzJob); - CtApply ctApply = ctApplyService.getById(dto.getApplyId()); - updateSysQuartzJob.setBeanName(ctApply.getTaskName()); - updateSysQuartzJob.setMethodName(ctApply.getMethodName()); - updateSysQuartzJob.setUpdateTime(DateUtil.now()); - - - QuartzJob quartzJob = new QuartzJob(); - BeanUtil.copyProperties(updateSysQuartzJob, quartzJob); - quartzJob.setId(dto.getJobId()); - quartzJob.setType(TaskTypeEnum.SHADOW_KNIFE.value()); - - quartzManage.updateJobCron(quartzJob); - return Dto.returnResult(updateById(updateSysQuartzJob)); - } - - - @Override - public Boolean deleteQuartzJobById(Long id) { - QuartzJob quartzJob = quartzJobService.findById(id); - quartzManage.deleteJob(quartzJob); - return removeById(id); - } - - @Override - public Dto addQuartzJob(SysQuartzJobAddDTO dto) { - if (!CronExpression.isValidExpression(dto.getCronExpression())) { - //throw new BadRequestException("cron表达式格式错误"); - return Dto.returnErrorResult("cron表达式格式错误"); - } - SysQuartzJob sysQuartzJob = new SysQuartzJob(); - BeanUtil.copyProperties(dto, sysQuartzJob); - ; - sysQuartzJob.setCreateTime(DateUtil.now()); - sysQuartzJob.setType(TaskTypeEnum.SHADOW_KNIFE.value()); - CtApply ctApply = ctApplyService.getById(dto.getApplyId()); - sysQuartzJob.setBeanName(ctApply.getTaskName()); - sysQuartzJob.setMethodName(ctApply.getMethodName()); - - QuartzJob quartzJob = new QuartzJob(); - quartzJob.setType(TaskTypeEnum.SHADOW_KNIFE.value()); - Boolean returnBoolean = save(sysQuartzJob); - if (returnBoolean) { - BeanUtil.copyProperties(sysQuartzJob, quartzJob); - quartzJob.setId(sysQuartzJob.getJobId()); - quartzManage.addJob(quartzJob); - } - //return returnBoolean; - return Dto.returnResult(returnBoolean); - } - - @Override - public Boolean reAddQuartzJob(SysQuartzJob sysQuartzJob) { - if (!CronExpression.isValidExpression(sysQuartzJob.getCronExpression())) { - throw new BadRequestException("cron表达式格式错误"); - } - sysQuartzJob.setCreateTime(DateUtil.now()); - QuartzJob quartzJob = new QuartzJob(); - quartzJob.setType(TaskTypeEnum.SHADOW_KNIFE.value()); - Boolean returnBoolean = save(sysQuartzJob); - if (returnBoolean) { - BeanUtil.copyProperties(sysQuartzJob, quartzJob); - quartzJob.setId(sysQuartzJob.getJobId()); - quartzManage.addJob(quartzJob); - } - return returnBoolean; - } - - @Override - public Boolean executionById(Long id) { - QuartzJob quartzJob = quartzJobService.findById(id); - quartzManage.runJobNow(quartzJob); - return true; - } - - @Override - public String assemblyParamAccordingToItem(String params, String taskName, Long taskNum) { - if (StringUtils.isEmpty(params) || StringUtils.isEmpty(taskName)) { - return null; - } - // 测试的第一个应用 刷单 拼装params - if (TaskInfoEnum.CLICK_FARMING.getTaskName().equals(taskName)) { - // 刷单 - Params paramsObj = JSONUtil.toBean(params, Params.class); - Boss bossObj = JSONUtil.toBean(params, Boss.class); - CtClickFarming ctClickFarming = ctClickFarmingService.getByIdLock(Long.valueOf(paramsObj.getParams())); - if (ObjectUtil.isEmpty(ctClickFarming)) { - return null; - // 状态 1.待执行 2.执行中 3.执行成功 4.执行失败 5.待支付 - } else if (ClickFarmingStatusEnum.IN_EXECUTION.value().equals(ctClickFarming.getStatus()) || ClickFarmingStatusEnum.EXECUTION_SUCCESS.value().equals(ctClickFarming.getStatus())) { - return null; - } else { - // 关联查询 得到对应传值任务参数 不特殊处理统一返回好了,影刀脚本那边自行判断 - CtClickFarmYdParams ctClickFarmYdParams = ctClickFarmingService.getCtClickFarmYdParams(Long.valueOf(paramsObj.getParams())); - if (ObjectUtil.isEmpty(ctClickFarmYdParams)) { - log.error("根据刷单id关联查询相关信息空值异常!!!"); - return null; - } - List paramList = new ArrayList<>(); - Map maps = BeanUtil.beanToMap(ctClickFarmYdParams); - maps.entrySet().removeIf(entry -> entry.getValue() == null); - - for (Map.Entry map : maps.entrySet()) { - Param ydParam = new Param(); - ydParam.setName(map.getKey()); - ydParam.setValue(map.getValue().toString()); - paramList.add(ydParam); - } - - if (ObjectUtil.isNotEmpty(taskNum)) { - Param ydParam = new Param(); - ydParam.setName("taskNum"); - ydParam.setValue(taskNum.toString()); - paramList.add(ydParam); - } - - // 组装Params - bossObj.setParams(paramList); - return JSONUtil.toJsonStr(bossObj); - } - } else if (TaskInfoEnum.DH_ADD_CAR_FARMING.getTaskName().equals(taskName)) { - // 敦煌 加购 - Params paramsObj = JSONUtil.toBean(params, Params.class); - Boss bossObj = JSONUtil.toBean(params, Boss.class); - DhAddCar dhAddCar = dhAddCarService.getByIdLock(Long.valueOf(paramsObj.getParams())); - if (ObjectUtil.isEmpty(dhAddCar)) { - return null; - } else if (!ClickFarmingStatusEnum.TOBE_EXECUTION.value().equals(dhAddCar.getStatus()) && !ClickFarmingStatusEnum.EXECUTION_FAILE.value().equals(dhAddCar.getStatus())) { - return null; - } else { - // 关联查询 得到对应传值任务参数 不特殊处理统一返回好了,影刀脚本那边自行判断 - DhAddCarYdParamsVO dhAddCarYdParamsVO = dhAddCarService.getAddCarYdParams(Long.valueOf(paramsObj.getParams())); - if (ObjectUtil.isEmpty(dhAddCarYdParamsVO)) { - log.error("根据刷单id关联查询相关信息空值异常!!!"); - return null; - } - List paramList = new ArrayList<>(); - Map maps = BeanUtil.beanToMap(dhAddCarYdParamsVO); - maps.entrySet().removeIf(entry -> entry.getValue() == null); - - for (Map.Entry map : maps.entrySet()) { - Param ydParam = new Param(); - String value = null; - // 特殊处理 - if ("carGoodKeys".equals(map.getKey()) || "carGoodLinks".equals(map.getKey())) { - Object carGoodKeysObj = map.getValue(); - value = JSONUtil.parseArray(carGoodKeysObj).toString(); - } else { - value = map.getValue().toString(); - } - - ydParam.setName(map.getKey()); - ydParam.setValue(value); - paramList.add(ydParam); - } - - if (ObjectUtil.isNotEmpty(taskNum)) { - Param ydParam = new Param(); - ydParam.setName("taskNum"); - ydParam.setValue(taskNum.toString()); - paramList.add(ydParam); - } - - // 组装Params - bossObj.setParams(paramList); - return JSONUtil.toJsonStr(bossObj); - } - } else if (TaskInfoEnum.DH_ADD_CAR_CATCH_ORDER.getTaskName().equals(taskName)) { - // 敦煌 - 抓单 - Params paramsObj = JSONUtil.toBean(params, Params.class); - Boss bossObj = JSONUtil.toBean(params, Boss.class); - DhAddCar dhAddCar = dhAddCarService.getByIdLock(Long.valueOf(paramsObj.getParams())); - if (ObjectUtil.isEmpty(dhAddCar)) { - return null; - } else if (!DhAddCarStatusEnum.TO_BE_CATCH_ORDER.value().equals(dhAddCar.getStatus()) && !DhAddCarStatusEnum.CATCH_ORDER_FAILE.value().equals(dhAddCar.getStatus())) { - return null; - } else { - // 关联查询 得到对应传值任务参数 不特殊处理统一返回好了,影刀脚本那边自行判断 - DhAddCarYdParamsVO dhAddCarYdParamsVO = dhAddCarService.getAddCarYdParams(Long.valueOf(paramsObj.getParams())); - if (ObjectUtil.isEmpty(dhAddCarYdParamsVO)) { - log.error("根据刷单id关联查询相关信息空值异常!!!"); - return null; - } - List paramList = new ArrayList<>(); - Map maps = BeanUtil.beanToMap(dhAddCarYdParamsVO); - maps.entrySet().removeIf(entry -> entry.getValue() == null); - - for (Map.Entry map : maps.entrySet()) { - Param ydParam = new Param(); - String value = null; - // 特殊处理 - if ("carGoodKeys".equals(map.getKey()) || "carGoodLinks".equals(map.getKey())) { - Object carGoodKeysObj = map.getValue(); - value = JSONUtil.parseArray(carGoodKeysObj).toString(); - } else { - value = map.getValue().toString(); - } - - ydParam.setName(map.getKey()); - ydParam.setValue(value); - paramList.add(ydParam); - } - - if (ObjectUtil.isNotEmpty(taskNum)) { - Param ydParam = new Param(); - ydParam.setName("taskNum"); - ydParam.setValue(taskNum.toString()); - paramList.add(ydParam); - } - // 组装Params - bossObj.setParams(paramList); - return JSONUtil.toJsonStr(bossObj); - } - } else if (TaskInfoEnum.CLICK_FARMING_SUPPLE_MENY.getTaskName().equals(taskName)) { - // 补录 - Params paramsObj = JSONUtil.toBean(params, Params.class); - Boss bossObj = JSONUtil.toBean(params, Boss.class); - CtClickFarming ctClickFarming = ctClickFarmingService.getByIdLock(Long.valueOf(paramsObj.getParams())); - if (ObjectUtil.isEmpty(ctClickFarming)) { - return null; - // 状态 1.待执行 2.执行中 3.执行成功 4.执行失败 5.待支付 - } else if (ClickFarmingStatusEnum.IN_EXECUTION.value().equals(ctClickFarming.getStatus()) || ClickFarmingStatusEnum.EXECUTION_SUCCESS.value().equals(ctClickFarming.getStatus())) { - return null; - } else { - CtClickFarmYdParams ctClickFarmYdParams = ctClickFarmingService.getCtClickFarmYdParams(Long.valueOf(paramsObj.getParams())); - if (ObjectUtil.isEmpty(ctClickFarmYdParams)) { - log.error("根据刷单id关联查询相关信息空值异常!!!"); - return null; - } - CtClickFarmSupplyMentYdParams ctClickFarmSupplyMentYdParams = new CtClickFarmSupplyMentYdParams(); - BeanUtil.copyProperties(ctClickFarmYdParams, ctClickFarmSupplyMentYdParams); - - List paramList = new ArrayList<>(); - Map maps = BeanUtil.beanToMap(ctClickFarmSupplyMentYdParams); - maps.entrySet().removeIf(entry -> entry.getValue() == null); - for (Map.Entry map : maps.entrySet()) { - Param ydParam = new Param(); - ydParam.setName(map.getKey()); - ydParam.setValue(map.getValue().toString()); - paramList.add(ydParam); - } - - // 组装Params - bossObj.setParams(paramList); - return JSONUtil.toJsonStr(bossObj); - } - } else if (TaskInfoEnum.WELL_RECEIVED.getTaskName().equals(taskName)) { - // 速卖通好评 - Params paramsObj = JSONUtil.toBean(params, Params.class); - Boss bossObj = JSONUtil.toBean(params, Boss.class); - CtClickOrder ctClickOrder = ctClickOrderService.getByIdLock(Long.valueOf(paramsObj.getParams())); - if (ObjectUtil.isEmpty(ctClickOrder)) { - return null; - // 状态 1.待执行 2.执行中 3.执行成功 4.执行失败 5.待支付 - } else if (ClickOrderStatusEnum.IN_EXECUTION.value().equals(ctClickOrder.getStatus()) || ClickFarmingStatusEnum.EXECUTION_SUCCESS.value().equals(ctClickOrder.getStatus())) { - return null; - } else { - CtClickOrderYdParams ctClickOrderYdParams = new CtClickOrderYdParams(); - CtClickFarmingOrderInfo ctClickFarmingOrderInfo = ctClickOrderService.getClickFarmOrderById(Long.valueOf(paramsObj.getParams())); - if (ObjectUtil.isEmpty(ctClickFarmingOrderInfo)) { - log.error("根据刷单id关联查询相关信息空值异常!!!"); - return null; - } - BeanUtil.copyProperties(ctClickFarmingOrderInfo, ctClickOrderYdParams); - String paths = joinPath(ctClickOrderYdParams.getPaths()); - if (ObjectUtil.isNotEmpty(paths)) { - ctClickOrderYdParams.setPaths(paths); - } - List paramList = new ArrayList<>(); - Map maps = BeanUtil.beanToMap(ctClickOrderYdParams); - maps.entrySet().removeIf(entry -> entry.getValue() == null); - - for (Map.Entry map : maps.entrySet()) { - Param ydParam = new Param(); - ydParam.setName(map.getKey()); - ydParam.setValue(map.getValue().toString()); - paramList.add(ydParam); - } - - // 组装Params - bossObj.setParams(paramList); - return JSONUtil.toJsonStr(bossObj); - } - } else if (TaskInfoEnum.DH_WELL_RECEIVED.getTaskName().equals(taskName)) { - // TODO 敦煌好评 - Params paramsObj = JSONUtil.toBean(params, Params.class); - Boss bossObj = JSONUtil.toBean(params, Boss.class); - DhAddCarOrder dhAddCarOrder = dhAddCarOrderService.getByIdLock(Long.valueOf(paramsObj.getParams())); - if (ObjectUtil.isEmpty(dhAddCarOrder)) { - return null; - // 状态 1.抓单成功才允许 好评 - } else if (!ClickOrderStatusEnum.TOBE_EXECUTION.value().equals(dhAddCarOrder.getStatus()) && !ClickOrderStatusEnum.EXECUTION_FAILE.value().equals(dhAddCarOrder.getStatus())) { - return null; - } else { - - // TODO 拼装好评数据 - DhCarOrderParamsVO dhCarOrderParamsVO = dhAddCarOrderService.getYdParams(Long.valueOf(paramsObj.getParams())); - if (ObjectUtil.isEmpty(dhCarOrderParamsVO)) { - log.error("根据刷单id关联查询相关信息空值异常!!!"); - return null; - } - joinImagePath(dhCarOrderParamsVO); - List paramList = new ArrayList<>(); - Map maps = BeanUtil.beanToMap(dhCarOrderParamsVO); - maps.entrySet().removeIf(entry -> entry.getValue() == null); - - for (Map.Entry map : maps.entrySet()) { - Param ydParam = new Param(); - String value = null; - // 特殊处理 - if ("carGoodKeys".equals(map.getKey()) || "carGoodLinks".equals(map.getKey())) { - Object carGoodKeysObj = map.getValue(); - value = JSONUtil.parseArray(carGoodKeysObj).toString(); - } else { - value = map.getValue().toString(); - } - - ydParam.setName(map.getKey()); - ydParam.setValue(value); - paramList.add(ydParam); - } - - // 组装Params - bossObj.setParams(paramList); - return JSONUtil.toJsonStr(bossObj); - } - } else if (TaskInfoEnum.BROWSE.getTaskName().equals(taskName)) { - // 浏览收藏 - Params paramsObj = JSONUtil.toBean(params, Params.class); - Boss bossObj = JSONUtil.toBean(params, Boss.class); - CtBrowse ctBrowse = ctBrowseService.getByIdLock(Long.valueOf(paramsObj.getParams())); - if (ObjectUtil.isEmpty(ctBrowse)) { - return null; - // 状态 1.待执行 2.执行中 3.执行成功 4.执行失败 5.待支付 - } else if (ClickOrderStatusEnum.IN_EXECUTION.value().equals(ctBrowse.getStatus()) || ClickFarmingStatusEnum.EXECUTION_SUCCESS.value().equals(ctBrowse.getStatus())) { - return null; - } else { - // TODO 好评浏览 待修改 - CtBrowseYdParams ctBrowseYdParams = new CtBrowseYdParams(); - CtBrowseDetailVO ctBrowseDetailVO = ctBrowseService.getBrowseDetailById(Long.valueOf(paramsObj.getParams())); - BeanUtil.copyProperties(ctBrowseDetailVO, ctBrowseYdParams); - List paramList = new ArrayList<>(); - Map maps = BeanUtil.beanToMap(ctBrowseYdParams); - maps.entrySet().removeIf(entry -> entry.getValue() == null); - - for (Map.Entry map : maps.entrySet()) { - Param ydParam = new Param(); - ydParam.setName(map.getKey()); - ydParam.setValue(map.getValue().toString()); - paramList.add(ydParam); - } - - // 组装Params - bossObj.setParams(paramList); - return JSONUtil.toJsonStr(bossObj); - } - } else { - return null; - } - } - - private void joinImagePath(DhCarOrderParamsVO dhCarOrderParamsVO) { - if (ParamsTypeEnum.KEY_WORD.eqValue(dhCarOrderParamsVO.getParamsType()) && ObjectUtil.isNotEmpty(dhCarOrderParamsVO.getCarGoodKeys())) { - for (DhCarGoodKeyVO dhCarGoodKeyVO:dhCarOrderParamsVO.getCarGoodKeys()) { - String paths = dhCarGoodKeyVO.getPaths(); - dhCarGoodKeyVO.setPaths(joinPath(paths)); - } - } else if (ParamsTypeEnum.LINK.eqValue(dhCarOrderParamsVO.getParamsType()) && ObjectUtil.isNotEmpty(dhCarOrderParamsVO.getCarGoodLinks())) { - for (DhCarGoodLinkVO dhCarGoodLinkVO:dhCarOrderParamsVO.getCarGoodLinks()) { - String paths = dhCarGoodLinkVO.getPaths(); - dhCarGoodLinkVO.setPaths(joinPath(paths)); - } - } else { - return ; - } - } - - /** - * 拼接域名 - * @param paths - * @return - */ - private String joinPath(String paths) { - if (ObjectUtil.isEmpty(paths)) { - return null; - } - List pathList = Arrays.asList(paths.split(",")); - return pathList.stream().map(s -> s = SystemConfig.FILE_VISIT_ADDR + s).collect(Collectors.joining(",")); - } - - @Override - public SysQuartzJob getByTaskNum(String taskNum) { - return sysQuartzJobDao.getByTaskNum(taskNum); - } -} - diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/BossTask.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/BossTask.java deleted file mode 100644 index 85c0202..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/BossTask.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.quartz.task; - -import cn.hutool.json.JSONUtil; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.constant.PublicConstant; -import me.zhengjie.entity.quartz.Boss; -import me.zhengjie.service.YdQuartzService; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - -/** - * 测试用-Boss查询岗位 - * @author rch - * @date 2022-07-23 - */ -@Slf4j -@Component -public class BossTask { - - @Resource - private YdQuartzService ydQuartzService; - - public void run(String str) throws Exception { - Boss boss = JSONUtil.toBean(str, Boss.class); - String REBOT_KEY = PublicConstant.getRebotKeyPrefix(boss.getAccountName()); - ydQuartzService.executeOnLock(REBOT_KEY, 1, 1, callBack -> { - try { - return ydQuartzService.exec(str); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); - } -} - diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/BossTask22.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/BossTask22.java deleted file mode 100644 index 4adf48b..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/BossTask22.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.quartz.task; - -import cn.hutool.core.date.DateUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.json.JSONUtil; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.config.YdApiProperties; -import me.zhengjie.constant.PublicConstant; -import me.zhengjie.entity.CtRebot; -import me.zhengjie.entity.quartz.Boss; -import me.zhengjie.entity.quartz.RebotStatu; -import me.zhengjie.entity.quartz.RebotStatuReturn; -import me.zhengjie.entity.quartz.SecreInfo; -import me.zhengjie.enums.YesOrNoEnum; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.service.CtRebotService; -import me.zhengjie.service.redission.LockCallBack; -import me.zhengjie.utils.HttpClientUtil; -import me.zhengjie.utils.RedissonUtil; -import org.redisson.api.RLock; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -/** - * 测试用-Boss查询岗位 - * @author rch - * @date 2022-07-23 - */ -@Slf4j -@Component -public class BossTask22 { - - @Resource - private CtRebotService ctRebotService; - @Resource - private RedissonUtil redissonUtil; - - public final static String REBOT_STATU = "https://api.winrobot360.com/oapi/dispatch/v2/client/query"; - public final static String GET_SECRET = "https://api.winrobot360.com/oapi/token/v2/token/create"; - public final static String STAT_JOB_URL = "https://api.winrobot360.com/oapi/dispatch/v2/job/start"; - - // 测试保证指执行一次 - public static Integer number = 0; - - public void run(){ - try { - Thread.sleep(5000); - log.info("run 执行成功====time:" + DateUtil.now()); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - log.info("run---end!"); - } - - public void run2(String str){ - - number ++; - Boss boss = JSONUtil.toBean(str, Boss.class); - String REBOT_KEY = PublicConstant.getRebotKeyPrefix(boss.getAccountName()); - try { - executeOnLock(REBOT_KEY, 1, 1, callBack -> exec(str)); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - public void run1(){ - log.info("run2 执行成功"); - } - - Object executeOnLock(String lockKey, long time, long timeout, LockCallBack callBack) throws BadRequestException,InterruptedException { - RLock lock = redissonUtil.getRLock(lockKey); - String currentTime = me.zhengjie.utils.DateUtil.getCurrentTime(); - try { - log.info(currentTime+" 获取锁============= {}",lockKey); - if (lock.tryLock(time, timeout, TimeUnit.SECONDS)) { - System.out.println(" run2 ====== lock success"); - return callBack.execute(true); - } else { - System.out.println(" run2 ====== lock fail "); - throw new BadRequestException(" run2 ====== lock fail "); - } - } catch (InterruptedException e) { - throw e; - } finally { - lock.unlock(); - log.info(currentTime+" 释放锁============= {}",lockKey); - } - } - - public Boolean exec(String str) { - Boss boss = JSONUtil.toBean(str, Boss.class); - // 1.根据设备id获取设备信息 for update - CtRebot ctRebot = ctRebotService.getByAccountNameLock(boss.getAccountName()); - System.out.println("run2================================"); - System.out.println(JSONUtil.toJsonStr(ctRebot)); - if (ObjectUtil.isEmpty(ctRebot) || !YesOrNoEnum.NO.eqValue(ctRebot.getStatus())) { - // 有问题 不执行 - log.info("run2 执行成功 - 结束了,设备信息问题,参数为: {}" + str); - return false; - } - - // token - Map params = new HashMap<>(16); - params.put("accessKeyId", YdApiProperties.ACCESS_KEY_ID); - params.put("accessKeySecret", YdApiProperties.ACCESS_KEY_SECRET); - String secretStr = HttpClientUtil.getHttp(GET_SECRET, params); - SecreInfo secreInfo = JSONUtil.toBean(secretStr, SecreInfo.class); - if (!secreInfo.getSuccess()) { - log.info("=========鉴权异常=========="); - return false; - } - String token = secreInfo.getData().getAccessToken(); - Map headers = new HashMap<>(16); - headers.put("Accept", "application/json"); - headers.put("Content-Type", "application/json;charset=utf-8"); - headers.put("authorization", "Bearer " + token); - - // 判断是否在线 - RebotStatu rebotStatu = new RebotStatu(); - rebotStatu.setAccountName(ctRebot.getAccountName()); - rebotStatu.setRobotClientUuid(ctRebot.getRobotClientUuid()); - String returnStr = HttpClientUtil.postJson(REBOT_STATU, headers, JSONUtil.toJsonStr(rebotStatu), "utf-8"); - RebotStatuReturn rebotStatuReturn = JSONUtil.toBean(returnStr, RebotStatuReturn.class); - if ("offline".equals(rebotStatuReturn.getData().getStatus())) { - log.info("=======设备不在线====="); - return false; - } - - // 修改机器人状态 - CtRebot updateCtRebot = new CtRebot(); - updateCtRebot.setId(ctRebot.getId()); - updateCtRebot.setStatus(YesOrNoEnum.YES.value()); - Boolean resultBoolean = ctRebotService.updateById(updateCtRebot); - if (resultBoolean) { - String returnJobStr = HttpClientUtil.postJson(STAT_JOB_URL, headers, JSONUtil.toJsonStr(boss), "utf-8"); - log.info("run2 执行成功,返回结果为: {}" + returnJobStr); - } else { - log.info("run2 执行成功。 但是修改设备状态失败----- 此处该预警"); - } - return true; - } -} - - diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/BrowseTask.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/BrowseTask.java deleted file mode 100644 index 9ca72aa..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/BrowseTask.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.quartz.task; - -import cn.hutool.json.JSONUtil; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.constant.PublicConstant; -import me.zhengjie.entity.quartz.Boss; -import me.zhengjie.service.YdQuartzService; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - -/** - * 浏览收藏任务 - * @author rch - * @date 2022-11-04 - */ -@Slf4j -@Component -public class BrowseTask { - - @Resource - private YdQuartzService ydQuartzService; - - public void run(String str) throws Exception { - System.out.println("================================BrowseTask=========================1"); - Boss boss = JSONUtil.toBean(str, Boss.class); - String REBOT_KEY = PublicConstant.getRebotKeyPrefix(boss.getAccountName()); - System.out.println("================================BrowseTask=========================2"); - ydQuartzService.executeOnLock(REBOT_KEY, 1, 1, callBack -> { - try { - System.out.println("================================BrowseTask=========================3"); - return ydQuartzService.browseTaskExec(str); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); - } -} - diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/ClickFarmSuppleMentTask.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/ClickFarmSuppleMentTask.java deleted file mode 100644 index 654079b..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/ClickFarmSuppleMentTask.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.quartz.task; - -import cn.hutool.json.JSONUtil; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.constant.PublicConstant; -import me.zhengjie.entity.quartz.Boss; -import me.zhengjie.service.YdQuartzService; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - -/** - * 刷单补录任务 - * @author rch - * @date 2022-10-17 - */ -@Slf4j -@Component -public class ClickFarmSuppleMentTask { - - @Resource - private YdQuartzService ydQuartzService; - - public void run(String str) throws Exception { - System.out.println("================================ClickFarmSuppleMentTask=========================1"); - Boss boss = JSONUtil.toBean(str, Boss.class); - String REBOT_KEY = PublicConstant.getRebotKeyPrefix(boss.getAccountName()); - System.out.println("================================ClickFarmSuppleMentTask=========================2"); - ydQuartzService.executeOnLock(REBOT_KEY, 1, 1, callBack -> { - try { - System.out.println("================================ClickFarmSuppleMentTask=========================3"); - return ydQuartzService.clickFarmSuppleMentExec(str); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); - } -} - diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/ClickFarmTask.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/ClickFarmTask.java deleted file mode 100644 index 701e025..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/ClickFarmTask.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.quartz.task; - -import cn.hutool.json.JSONUtil; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.constant.PublicConstant; -import me.zhengjie.entity.quartz.Boss; -import me.zhengjie.service.YdQuartzService; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - -/** - * 刷单任务 - * @author rch - * @date 2022-08-16 - */ -@Slf4j -@Component -public class ClickFarmTask { - - @Resource - private YdQuartzService ydQuartzService; - - public void run(String str) throws Exception { - System.out.println("================================ClickFarmTask=========================1"); - Boss boss = JSONUtil.toBean(str, Boss.class); - String REBOT_KEY = PublicConstant.getRebotKeyPrefix(boss.getAccountName()); - System.out.println("================================ClickFarmTask=========================2"); - ydQuartzService.executeOnLock(REBOT_KEY, 1, 1, callBack -> { - try { - System.out.println("================================ClickFarmTask=========================3"); - return ydQuartzService.clickFarmExec(str); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); - } -} - diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/DhAddCarTask.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/DhAddCarTask.java deleted file mode 100644 index d6f1518..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/DhAddCarTask.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.quartz.task; - -import cn.hutool.json.JSONUtil; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.constant.PublicConstant; -import me.zhengjie.entity.quartz.Boss; -import me.zhengjie.service.YdQuartzService; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - -/** - * 敦煌-加购 - * @author rch - * @date 2022-11-14 - */ -@Slf4j -@Component -public class DhAddCarTask { - - @Resource - private YdQuartzService ydQuartzService; - - public void run(String str) throws Exception { - System.out.println("================================ClickFarmTask=========================1"); - Boss boss = JSONUtil.toBean(str, Boss.class); - String REBOT_KEY = PublicConstant.getRebotKeyPrefix(boss.getAccountName()); - System.out.println("================================ClickFarmTask=========================2"); - ydQuartzService.executeOnLock(REBOT_KEY, 1, 1, callBack -> { - try { - System.out.println("================================ClickFarmTask=========================3"); - return ydQuartzService.addCarExec(str); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); - } -} - diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/DhCatchOrderTask.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/DhCatchOrderTask.java deleted file mode 100644 index 492a6ac..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/DhCatchOrderTask.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.quartz.task; - -import cn.hutool.json.JSONUtil; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.constant.PublicConstant; -import me.zhengjie.entity.quartz.Boss; -import me.zhengjie.service.YdQuartzService; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - -/** - * 敦煌-加购抓单任务 - * @author rch - * @date 2022-08-16 - */ -@Slf4j -@Component -public class DhCatchOrderTask { - - @Resource - private YdQuartzService ydQuartzService; - - public void run(String str) throws Exception { - System.out.println("================================DhCatchOrderTask=========================1"); - Boss boss = JSONUtil.toBean(str, Boss.class); - String REBOT_KEY = PublicConstant.getRebotKeyPrefix(boss.getAccountName()); - System.out.println("================================DhCatchOrderTask=========================2"); - ydQuartzService.executeOnLock(REBOT_KEY, 1, 1, callBack -> { - try { - System.out.println("================================DhCatchOrderTask=========================3"); - return ydQuartzService.catchOrderExec(str); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); - } -} - diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/DhPayTask.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/DhPayTask.java deleted file mode 100644 index 6a44236..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/DhPayTask.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.quartz.task; - -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.service.CtDhPayService; -import me.zhengjie.service.CtOrderService; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - -/** - * 敦煌 支付 定时器 - * 计划 每10s 执行一次 -串行 - * @author rch - * @date 2022-07-28 - */ -@Slf4j -@Component -public class DhPayTask { - - @Resource - private CtDhPayService ctDhPayService; - - public void dhPayTaskRun(){ - try { - ctDhPayService.toPay(); - log.info("敦煌 支付 定时器---DhPayTask---dhPayTaskRun---执行成功"); - } catch (Exception e) { - e.printStackTrace(); - } - log.info("run---end!"); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/DhWellReceivedTask.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/DhWellReceivedTask.java deleted file mode 100644 index 79baee7..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/DhWellReceivedTask.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.quartz.task; - -import cn.hutool.json.JSONUtil; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.constant.PublicConstant; -import me.zhengjie.entity.quartz.Boss; -import me.zhengjie.service.YdQuartzService; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - -/** - * 敦煌-好评 - * @author rch - * @date 2022-11-14 - */ -@Slf4j -@Component -public class DhWellReceivedTask { - - @Resource - private YdQuartzService ydQuartzService; - - public void run(String str) throws Exception { - System.out.println("================================DhWellReceivedTask=========================1"); - Boss boss = JSONUtil.toBean(str, Boss.class); - String REBOT_KEY = PublicConstant.getRebotKeyPrefix(boss.getAccountName()); - System.out.println("================================DhWellReceivedTask=========================2"); - ydQuartzService.executeOnLock(REBOT_KEY, 1, 1, callBack -> { - try { - System.out.println("================================DhWellReceivedTask=========================3"); - return ydQuartzService.dhWellReceivedExec(str); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); - } -} - diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/ExcelToOrderTask.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/ExcelToOrderTask.java deleted file mode 100644 index 6ce201d..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/ExcelToOrderTask.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.quartz.task; - -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.service.CtOrderService; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - -/** - * Excel 数据转换存储到订单表里 Order 一对多 - * 计划 每10s 执行一次 -串行 - * @author rch - * @date 2022-06-23 - */ -@Slf4j -@Component -public class ExcelToOrderTask { - - @Resource - private CtOrderService ctOrderService; - - public void excelToOrderRun(){ - try { - ctOrderService.excelToOrder(); - log.info("Excel 数据转换存储到订单表里 Order---ExcelToOrderTask---excelToOrderRun---执行成功"); - } catch (Exception e) { - e.printStackTrace(); - } - log.info("run---end!"); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/ExcelmportTask.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/ExcelmportTask.java deleted file mode 100644 index 79e5068..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/ExcelmportTask.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.quartz.task; - -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.service.CtExcelImportInfoService; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - -/** - * Excel 数据导入到Mysql定时器 - * 计划 每10s 执行一次 -串行 - * @author rch - * @date 2022-06-23 - */ -@Slf4j -@Component -public class ExcelmportTask { - - @Resource - private CtExcelImportInfoService ctExcelImportInfoService; - - public void importRun(){ - try { - ctExcelImportInfoService.importExcel(); - log.info("Excel数据导入到Mysql定时器---ExcelmportTask---importRun---执行成功"); - } catch (Exception e) { - e.printStackTrace(); - } - log.info("run---end!"); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/OrderToPayTask.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/OrderToPayTask.java deleted file mode 100644 index e62c8bd..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/OrderToPayTask.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.quartz.task; - -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.service.CtOrderService; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - -/** - * 订单表里Order支付 定时器 - * 计划 每8s 执行一次 -串行 - * @author rch - * @date 2022-06-23 - */ -@Slf4j -@Component -public class OrderToPayTask { - - @Resource - private CtOrderService ctOrderService; - - public void orderToPayRun(){ - try { - ctOrderService.toPay(); - log.info("订单表里Order支付---OrderToPayTask---orderToPayRun---执行成功"); - } catch (Exception e) { - e.printStackTrace(); - } - log.info("run---end!"); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/RebotStatusTask.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/RebotStatusTask.java deleted file mode 100644 index 6266f5e..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/RebotStatusTask.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.quartz.task; - -import cn.hutool.core.date.DateUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.json.JSONUtil; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.config.YdApiProperties; -import me.zhengjie.constant.Constants; -import me.zhengjie.entity.CtRebot; -import me.zhengjie.entity.quartz.RebotStatu; -import me.zhengjie.entity.quartz.RebotStatuReturn; -import me.zhengjie.entity.quartz.SecreInfo; -import me.zhengjie.enums.CtReboteStatusEnum; -import me.zhengjie.enums.RobotStatusEnum; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.service.CtRebotService; -import me.zhengjie.utils.HttpClientUtil; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * 机器人状态定时检测 - * @author rch - * @date 2022-08-06 - */ -@Slf4j -@Component -public class RebotStatusTask { - - @Resource - private CtRebotService ctRebotService; - - /** - * 计划20s执行一次 等到真的脚本写好了,就多点时间根据实际情况 - */ - public void run(){ - try { - // TODO 获取占用状态的机器人信息 然后定时调用接口 根据结果修改机器人状态 - QueryWrapper ctRebotQueryWrapper = new QueryWrapper<>(); - ctRebotQueryWrapper.eq("status", CtReboteStatusEnum.OCCUPY.value()); - - List ctRebotList = ctRebotService.list(ctRebotQueryWrapper); - - // token - Map params = new HashMap<>(16); - params.put("accessKeyId", YdApiProperties.ACCESS_KEY_ID); - params.put("accessKeySecret", YdApiProperties.ACCESS_KEY_SECRET); - SecreInfo secreInfo = JSONUtil.toBean(HttpClientUtil.getHttp(Constants.GET_SECRET, params), SecreInfo.class); - if (!secreInfo.getSuccess()) { - log.info("=========鉴权异常=========="); - throw new BadRequestException("请求影刀鉴权异常!"); - } - String token = secreInfo.getData().getAccessToken(); - Map headers = new HashMap<>(16); - headers.put("Accept", "application/json"); - headers.put("Content-Type", "application/json;charset=utf-8"); - headers.put("authorization", "Bearer " + token); - for (CtRebot ctRebot:ctRebotList) { - // 判断是否在线 - RebotStatu rebotStatu = new RebotStatu(ctRebot.getRobotClientUuid(), ctRebot.getAccountName()); - String returnStr = HttpClientUtil.postJson(Constants.REBOT_STATU, headers, JSONUtil.toJsonStr(rebotStatu), "utf-8"); - RebotStatuReturn rebotStatuReturn = JSONUtil.toBean(returnStr, RebotStatuReturn.class); - - if (ObjectUtil.isNotEmpty(rebotStatuReturn.getData()) && RobotStatusEnum.IDLE.value().equals(rebotStatuReturn.getData().getStatus())) { - Boolean result = ctRebotService.updateNewStatusByOldStatus(ctRebot.getId(), CtReboteStatusEnum.UNOCCUPIED.value(), ctRebot.getStatus()); - log.info("=======修改设备空闲状态=====ctRebot:{} --oldStatus:{}, ---newStatus{} --result:{}", JSONUtil.toJsonStr(ctRebot), ctRebot.getStatus(), CtReboteStatusEnum.UNOCCUPIED.value(), result); - } - } - - log.info("run 执行成功====time:" + DateUtil.now()); - } catch (Exception e) { - e.printStackTrace(); - } - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/TestTask.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/TestTask.java deleted file mode 100644 index 5ec4a14..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/TestTask.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.quartz.task; - -import cn.hutool.core.date.DateUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -/** - * 测试用 - * @author Zheng Jie - * @date 2019-01-08 - */ -@Slf4j -@Component -public class TestTask { - - public void run(){ - try { - Thread.sleep(5000); - log.info("run 执行成功====time:" + DateUtil.now()); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - log.info("run---end!"); - } - - public void run1(String str){ - log.info("run1 执行成功,参数为: {}" + str); - } - - public void run2(){ - log.info("run2 执行成功"); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/WellReceivedTask.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/WellReceivedTask.java deleted file mode 100644 index eaab091..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/task/WellReceivedTask.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.quartz.task; - -import cn.hutool.json.JSONUtil; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.constant.PublicConstant; -import me.zhengjie.entity.quartz.Boss; -import me.zhengjie.service.YdQuartzService; -import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; - -import javax.annotation.Resource; - -/** - * 刷单任务 - * @author rch - * @date 2022-10-17 - */ -@Slf4j -@Component -public class WellReceivedTask { - - @Resource - private YdQuartzService ydQuartzService; - - public void run(String str) throws Exception { - System.out.println("================================WellReceivedTask=========================1"); - Boss boss = JSONUtil.toBean(str, Boss.class); - String REBOT_KEY = PublicConstant.getRebotKeyPrefix(boss.getAccountName()); - System.out.println("================================WellReceivedTask=========================2"); - ydQuartzService.executeOnLock(REBOT_KEY, 1, 1, callBack -> { - try { - System.out.println("================================WellReceivedTask=========================3"); - return ydQuartzService.wellReceivedExec(str); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); - } -} - diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/utils/ExecutionJob.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/utils/ExecutionJob.java deleted file mode 100644 index 267f20b..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/utils/ExecutionJob.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.quartz.utils; - -import cn.hutool.extra.template.Template; -import cn.hutool.extra.template.TemplateConfig; -import cn.hutool.extra.template.TemplateEngine; -import cn.hutool.extra.template.TemplateUtil; -import me.zhengjie.config.thread.ThreadPoolExecutorUtil; -import me.zhengjie.domain.vo.EmailVo; -import me.zhengjie.modules.quartz.domain.QuartzJob; -import me.zhengjie.modules.quartz.domain.QuartzLog; -import me.zhengjie.modules.quartz.repository.QuartzLogRepository; -import me.zhengjie.modules.quartz.service.QuartzJobService; -import me.zhengjie.service.EmailService; -import me.zhengjie.utils.RedisUtils; -import me.zhengjie.utils.SpringContextHolder; -import me.zhengjie.utils.StringUtils; -import me.zhengjie.utils.ThrowableUtil; -import org.quartz.DisallowConcurrentExecution; -import org.quartz.JobExecutionContext; -import org.springframework.scheduling.quartz.QuartzJobBean; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Future; -import java.util.concurrent.ThreadPoolExecutor; - -/** - * 参考人人开源,https://gitee.com/renrenio/renren-security - * @author / - * @date 2019-01-07 - */ -//@Async -@DisallowConcurrentExecution -public class ExecutionJob extends QuartzJobBean { - - /** 该处仅供参考 */ - private final static ThreadPoolExecutor EXECUTOR = ThreadPoolExecutorUtil.getPoll(); - - @Override - public void executeInternal(JobExecutionContext context) { - QuartzJob quartzJob = (QuartzJob) context.getMergedJobDataMap().get(QuartzJob.JOB_KEY); - // 获取spring bean - QuartzLogRepository quartzLogRepository = SpringContextHolder.getBean(QuartzLogRepository.class); - QuartzJobService quartzJobService = SpringContextHolder.getBean(QuartzJobService.class); - RedisUtils redisUtils = SpringContextHolder.getBean(RedisUtils.class); - - String uuid = quartzJob.getUuid(); - - QuartzLog log = new QuartzLog(); - log.setJobName(quartzJob.getJobName()); - log.setBeanName(quartzJob.getBeanName()); - log.setMethodName(quartzJob.getMethodName()); - log.setParams(quartzJob.getParams()); - log.setType(quartzJob.getType()); - long startTime = System.currentTimeMillis(); - log.setCronExpression(quartzJob.getCronExpression()); - try { - // 执行任务 - System.out.println("--------------------------------------------------------------"); - System.out.println("任务开始执行,任务名称:" + quartzJob.getJobName()); - QuartzRunnable task = new QuartzRunnable(quartzJob.getBeanName(), quartzJob.getMethodName(), - quartzJob.getParams()); - Future future = EXECUTOR.submit(task); - future.get(); - long times = System.currentTimeMillis() - startTime; - log.setTime(times); - if(StringUtils.isNotBlank(uuid)) { - redisUtils.set(uuid, true); - } - // 任务状态 - log.setIsSuccess(true); - System.out.println("任务执行完毕,任务名称:" + quartzJob.getJobName() + ", 执行时间:" + times + "毫秒"); - System.out.println("--------------------------------------------------------------"); - // 判断是否存在子任务 - if(StringUtils.isNotBlank(quartzJob.getSubTask())){ - String[] tasks = quartzJob.getSubTask().split("[,,]"); - // 执行子任务 - quartzJobService.executionSubJob(tasks); - } - } catch (Exception e) { - if(StringUtils.isNotBlank(uuid)) { - redisUtils.set(uuid, false); - } - System.out.println("任务执行失败,任务名称:" + quartzJob.getJobName()); - System.out.println("--------------------------------------------------------------"); - long times = System.currentTimeMillis() - startTime; - log.setTime(times); - // 任务状态 0:成功 1:失败 - log.setIsSuccess(false); - log.setExceptionDetail(ThrowableUtil.getStackTrace(e)); - // 任务如果失败了则暂停 - if(quartzJob.getPauseAfterFailure() != null && quartzJob.getPauseAfterFailure()){ - quartzJob.setIsPause(false); - //更新状态 - quartzJobService.updateIsPause(quartzJob); - } - if(quartzJob.getEmail() != null){ - EmailService emailService = SpringContextHolder.getBean(EmailService.class); - // 邮箱报警 - if(StringUtils.isNoneBlank(quartzJob.getEmail())){ - EmailVo emailVo = taskAlarm(quartzJob, ThrowableUtil.getStackTrace(e)); - emailService.send(emailVo, emailService.find()); - } - } - } finally { - quartzLogRepository.save(log); - } - } - - private EmailVo taskAlarm(QuartzJob quartzJob, String msg) { - EmailVo emailVo = new EmailVo(); - emailVo.setSubject("定时任务【"+ quartzJob.getJobName() +"】执行失败,请尽快处理!"); - Map data = new HashMap<>(16); - data.put("task", quartzJob); - data.put("msg", msg); - TemplateEngine engine = TemplateUtil.createEngine(new TemplateConfig("template", TemplateConfig.ResourceMode.CLASSPATH)); - Template template = engine.getTemplate("email/taskAlarm.ftl"); - emailVo.setContent(template.render(data)); - List emails = Arrays.asList(quartzJob.getEmail().split("[,,]")); - emailVo.setTos(emails); - return emailVo; - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/utils/QuartzManage.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/utils/QuartzManage.java deleted file mode 100644 index e0cf1e0..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/utils/QuartzManage.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.quartz.utils; - -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.modules.quartz.domain.QuartzJob; -import org.quartz.*; -import org.quartz.impl.triggers.CronTriggerImpl; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import javax.annotation.Resource; -import java.util.Date; -import static org.quartz.TriggerBuilder.newTrigger; - -/** - * @author Zheng Jie - * @date 2019-01-07 - */ -@Slf4j -@Component -public class QuartzManage { - - private static final String JOB_NAME = "TASK_"; - - @Resource - private Scheduler scheduler; - - public void addJob(QuartzJob quartzJob){ - try { - // 构建job信息 - JobDetail jobDetail = JobBuilder.newJob(ExecutionJob.class). - withIdentity(JOB_NAME + quartzJob.getId()).build(); - - //通过触发器名和cron 表达式创建 Trigger - Trigger cronTrigger = newTrigger() - .withIdentity(JOB_NAME + quartzJob.getId()) - .startNow() - .withSchedule(CronScheduleBuilder.cronSchedule(quartzJob.getCronExpression())) - .build(); - - cronTrigger.getJobDataMap().put(QuartzJob.JOB_KEY, quartzJob); - - //重置启动时间 - ((CronTriggerImpl)cronTrigger).setStartTime(new Date()); - - //执行定时任务 - scheduler.scheduleJob(jobDetail,cronTrigger); - - // 暂停任务 - if (quartzJob.getIsPause()) { - pauseJob(quartzJob); - } - } catch (Exception e){ - log.error("创建定时任务失败", e); - throw new BadRequestException("创建定时任务失败"); - } - } - - /** - * 更新job cron表达式 - * @param quartzJob / - */ - public void updateJobCron(QuartzJob quartzJob){ - try { - TriggerKey triggerKey = TriggerKey.triggerKey(JOB_NAME + quartzJob.getId()); - CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); - // 如果不存在则创建一个定时任务 - if(trigger == null){ - addJob(quartzJob); - trigger = (CronTrigger) scheduler.getTrigger(triggerKey); - } - CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzJob.getCronExpression()); - trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build(); - //重置启动时间 - ((CronTriggerImpl)trigger).setStartTime(new Date()); - trigger.getJobDataMap().put(QuartzJob.JOB_KEY,quartzJob); - - scheduler.rescheduleJob(triggerKey, trigger); - // 暂停任务 - if (quartzJob.getIsPause()) { - pauseJob(quartzJob); - } - } catch (Exception e){ - log.error("更新定时任务失败", e); - throw new BadRequestException("更新定时任务失败"); - } - - } - - /** - * 删除一个job - * @param quartzJob / - */ - public void deleteJob(QuartzJob quartzJob){ - try { - JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId()); - scheduler.pauseJob(jobKey); - scheduler.deleteJob(jobKey); - } catch (Exception e){ - log.error("删除定时任务失败", e); - throw new BadRequestException("删除定时任务失败"); - } - } - - /** - * 恢复一个job - * @param quartzJob / - */ - public void resumeJob(QuartzJob quartzJob){ - try { - TriggerKey triggerKey = TriggerKey.triggerKey(JOB_NAME + quartzJob.getId()); - CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); - // 如果不存在则创建一个定时任务 - if(trigger == null) { - addJob(quartzJob); - } - JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId()); - scheduler.resumeJob(jobKey); - } catch (Exception e){ - log.error("恢复定时任务失败", e); - throw new BadRequestException("恢复定时任务失败"); - } - } - - /** - * 立即执行job - * @param quartzJob / - */ - public void runJobNow(QuartzJob quartzJob){ - try { - TriggerKey triggerKey = TriggerKey.triggerKey(JOB_NAME + quartzJob.getId()); - CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); - // 如果不存在则创建一个定时任务 - if(trigger == null) { - addJob(quartzJob); - } - JobDataMap dataMap = new JobDataMap(); - dataMap.put(QuartzJob.JOB_KEY, quartzJob); - JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId()); - scheduler.triggerJob(jobKey,dataMap); - } catch (Exception e){ - log.error("定时任务执行失败", e); - throw new BadRequestException("定时任务执行失败"); - } - } - - /** - * 暂停一个job - * @param quartzJob / - */ - public void pauseJob(QuartzJob quartzJob){ - try { - JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId()); - scheduler.pauseJob(jobKey); - } catch (Exception e){ - log.error("定时任务暂停失败", e); - throw new BadRequestException("定时任务暂停失败"); - } - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/utils/QuartzRunnable.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/utils/QuartzRunnable.java deleted file mode 100644 index faf334c..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/utils/QuartzRunnable.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.quartz.utils; - -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.utils.SpringContextHolder; -import org.apache.commons.lang3.StringUtils; -import org.springframework.util.ReflectionUtils; -import java.lang.reflect.Method; -import java.util.concurrent.Callable; - -/** - * 执行定时任务 - * @author / - */ -@Slf4j -public class QuartzRunnable implements Callable { - - private final Object target; - private final Method method; - private final String params; - - QuartzRunnable(String beanName, String methodName, String params) - throws NoSuchMethodException, SecurityException { - this.target = SpringContextHolder.getBean(beanName); - this.params = params; - - if (StringUtils.isNotBlank(params)) { - this.method = target.getClass().getDeclaredMethod(methodName, String.class); - } else { - this.method = target.getClass().getDeclaredMethod(methodName); - } - } - - @Override - public Object call() throws Exception { - ReflectionUtils.makeAccessible(method); - if (StringUtils.isNotBlank(params)) { - method.invoke(target, params); - } else { - method.invoke(target); - } - return null; - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/utils/YdApiUtil.java b/wjcy-system/src/main/java/me/zhengjie/modules/quartz/utils/YdApiUtil.java deleted file mode 100644 index 228ca67..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/quartz/utils/YdApiUtil.java +++ /dev/null @@ -1,31 +0,0 @@ -package me.zhengjie.modules.quartz.utils; - -import cn.hutool.json.JSONUtil; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.config.BeanFactory; -import me.zhengjie.constant.Constants; -import me.zhengjie.entity.CtApply; -import me.zhengjie.entity.CtRebot; -import me.zhengjie.entity.quartz.RebotStatu; -import me.zhengjie.entity.quartz.RebotStatuReturn; -import me.zhengjie.entity.quartz.SecreInfo; -import me.zhengjie.enums.RobotStatusEnum; -import me.zhengjie.enums.YesOrNoEnum; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.service.CtRebotService; -import me.zhengjie.utils.HttpClientUtil; - -import java.util.HashMap; -import java.util.Map; - -/** - * 调用影刀发起Api请求工具类 - * - * @author rch - * @create 2022-08-01 - */ -@Slf4j -public class YdApiUtil { - - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/security/config/ConfigBeanConfiguration.java b/wjcy-system/src/main/java/me/zhengjie/modules/security/config/ConfigBeanConfiguration.java deleted file mode 100644 index 8cbc88d..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/security/config/ConfigBeanConfiguration.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2019-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.security.config; - -import me.zhengjie.modules.security.config.bean.LoginProperties; -import me.zhengjie.modules.security.config.bean.SecurityProperties; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * @apiNote 配置文件转换Pojo类的 统一配置 类 - * @author: liaojinlong - * @date: 2020/6/10 19:04 - */ -@Configuration -public class ConfigBeanConfiguration { - - @Bean - @ConfigurationProperties(prefix = "login") - public LoginProperties loginProperties() { - return new LoginProperties(); - } - - @Bean - @ConfigurationProperties(prefix = "jwt") - public SecurityProperties securityProperties() { - return new SecurityProperties(); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/security/config/SecurityConfig.java b/wjcy-system/src/main/java/me/zhengjie/modules/security/config/SecurityConfig.java deleted file mode 100644 index 9067f1c..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/security/config/SecurityConfig.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.security.config; - -import lombok.RequiredArgsConstructor; -import me.zhengjie.annotation.AnonymousAccess; -import me.zhengjie.config.PropertiesConfig; -import me.zhengjie.modules.security.config.bean.SecurityProperties; -import me.zhengjie.modules.security.security.JwtAccessDeniedHandler; -import me.zhengjie.modules.security.security.JwtAuthenticationEntryPoint; -import me.zhengjie.modules.security.security.TokenConfigurer; -import me.zhengjie.modules.security.security.TokenProvider; -import me.zhengjie.modules.security.service.OnlineUserService; -import me.zhengjie.modules.security.service.UserCacheClean; -import me.zhengjie.service.LoginIpService; -import me.zhengjie.utils.enums.RequestMethodEnum; -import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.HttpMethod; -import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.config.core.GrantedAuthorityDefaults; -import org.springframework.security.config.http.SessionCreationPolicy; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.filter.CorsFilter; -import org.springframework.web.method.HandlerMethod; -import org.springframework.web.servlet.mvc.method.RequestMappingInfo; -import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; - -import javax.annotation.Resource; -import java.util.*; - -/** - * @author Zheng Jie - */ -@Configuration -@EnableWebSecurity -@RequiredArgsConstructor -@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) -public class SecurityConfig extends WebSecurityConfigurerAdapter { - - private final TokenProvider tokenProvider; - private final CorsFilter corsFilter; - private final JwtAuthenticationEntryPoint authenticationErrorHandler; - private final JwtAccessDeniedHandler jwtAccessDeniedHandler; - private final ApplicationContext applicationContext; - private final SecurityProperties properties; - private final OnlineUserService onlineUserService; - private final UserCacheClean userCacheClean; - private final LoginIpService loginIpService; - @Resource - private PropertiesConfig propertiesConfig; - - @Bean - GrantedAuthorityDefaults grantedAuthorityDefaults() { - // 去除 ROLE_ 前缀 - return new GrantedAuthorityDefaults(""); - } - - @Bean - public PasswordEncoder passwordEncoder() { - // 密码加密方式 - return new BCryptPasswordEncoder(); - } - - @Override - protected void configure(HttpSecurity httpSecurity) throws Exception { - // 搜寻匿名标记 url: @AnonymousAccess - // Map handlerMethodMap = applicationContext.getBean(RequestMappingHandlerMapping.class).getHandlerMethods(); - RequestMappingHandlerMapping requestMappingHandlerMapping = (RequestMappingHandlerMapping) applicationContext.getBean("requestMappingHandlerMapping"); - Map handlerMethodMap = requestMappingHandlerMapping.getHandlerMethods(); - - // 获取匿名标记 - Map> anonymousUrls = getAnonymousUrl(handlerMethodMap); - httpSecurity - // 禁用 CSRF - .csrf().disable() - .addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class) - // 授权异常 - .exceptionHandling() - .authenticationEntryPoint(authenticationErrorHandler) - .accessDeniedHandler(jwtAccessDeniedHandler) - // 防止iframe 造成跨域 - .and() - .headers() - .frameOptions() - .disable() - // 不创建会话 - .and() - .sessionManagement() - .sessionCreationPolicy(SessionCreationPolicy.STATELESS) - .and() - .authorizeRequests() - // 静态资源等等 - .antMatchers( - HttpMethod.GET, - "/*.html", - "/**/*.html", - "/**/*.css", - "/**/*.js", - "/webSocket/**" - ).permitAll() - // swagger 文档 - .antMatchers("/swagger-ui.html").permitAll() - .antMatchers("/doc.html").permitAll() - .antMatchers("/swagger-resources/**").permitAll() - .antMatchers("/webjars/**").permitAll() - .antMatchers("/*/api-docs").permitAll() - // 文件 - .antMatchers("/avatar/**").permitAll() - .antMatchers("/file/**").permitAll() - // 图片上传 - .antMatchers("/api/file/**").permitAll() - // 静态资源访问 - .antMatchers(propertiesConfig.getUploadPrefix()+"/**").permitAll() - // 阿里巴巴 druid - .antMatchers("/druid/**").permitAll() - // 放行OPTIONS请求 - .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() - // 代理后台 - .antMatchers("/proxyAdmin/**").permitAll() - // 自定义匿名访问所有url放行:允许匿名和带Token访问,细腻化到每个 Request 类型 - // GET - .antMatchers(HttpMethod.GET, anonymousUrls.get(RequestMethodEnum.GET.getType()).toArray(new String[0])).permitAll() - // POST - .antMatchers(HttpMethod.POST, anonymousUrls.get(RequestMethodEnum.POST.getType()).toArray(new String[0])).permitAll() - // PUT - .antMatchers(HttpMethod.PUT, anonymousUrls.get(RequestMethodEnum.PUT.getType()).toArray(new String[0])).permitAll() - // PATCH - .antMatchers(HttpMethod.PATCH, anonymousUrls.get(RequestMethodEnum.PATCH.getType()).toArray(new String[0])).permitAll() - // DELETE - .antMatchers(HttpMethod.DELETE, anonymousUrls.get(RequestMethodEnum.DELETE.getType()).toArray(new String[0])).permitAll() - // 所有类型的接口都放行 - .antMatchers(anonymousUrls.get(RequestMethodEnum.ALL.getType()).toArray(new String[0])).permitAll() - // 所有请求都需要认证 - .anyRequest().authenticated() - .and().apply(securityConfigurerAdapter()); - } - - private Map> getAnonymousUrl(Map handlerMethodMap) { - Map> anonymousUrls = new HashMap<>(6); - Set get = new HashSet<>(); - Set post = new HashSet<>(); - Set put = new HashSet<>(); - Set patch = new HashSet<>(); - Set delete = new HashSet<>(); - Set all = new HashSet<>(); - for (Map.Entry infoEntry : handlerMethodMap.entrySet()) { - HandlerMethod handlerMethod = infoEntry.getValue(); - AnonymousAccess anonymousAccess = handlerMethod.getMethodAnnotation(AnonymousAccess.class); - if (null != anonymousAccess) { - List requestMethods = new ArrayList<>(infoEntry.getKey().getMethodsCondition().getMethods()); - RequestMethodEnum request = RequestMethodEnum.find(requestMethods.size() == 0 ? RequestMethodEnum.ALL.getType() : requestMethods.get(0).name()); - switch (Objects.requireNonNull(request)) { - case GET: - get.addAll(infoEntry.getKey().getPatternsCondition().getPatterns()); - break; - case POST: - post.addAll(infoEntry.getKey().getPatternsCondition().getPatterns()); - break; - case PUT: - put.addAll(infoEntry.getKey().getPatternsCondition().getPatterns()); - break; - case PATCH: - patch.addAll(infoEntry.getKey().getPatternsCondition().getPatterns()); - break; - case DELETE: - delete.addAll(infoEntry.getKey().getPatternsCondition().getPatterns()); - break; - default: - all.addAll(infoEntry.getKey().getPatternsCondition().getPatterns()); - break; - } - } - } - anonymousUrls.put(RequestMethodEnum.GET.getType(), get); - anonymousUrls.put(RequestMethodEnum.POST.getType(), post); - anonymousUrls.put(RequestMethodEnum.PUT.getType(), put); - anonymousUrls.put(RequestMethodEnum.PATCH.getType(), patch); - anonymousUrls.put(RequestMethodEnum.DELETE.getType(), delete); - anonymousUrls.put(RequestMethodEnum.ALL.getType(), all); - return anonymousUrls; - } - - private TokenConfigurer securityConfigurerAdapter() { - return new TokenConfigurer(tokenProvider, properties, onlineUserService, userCacheClean,loginIpService); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/security/config/bean/LoginCode.java b/wjcy-system/src/main/java/me/zhengjie/modules/security/config/bean/LoginCode.java deleted file mode 100644 index fefd252..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/security/config/bean/LoginCode.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2019-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.security.config.bean; - -import lombok.Data; - -/** - * 登录验证码配置信息 - * - * @author liaojinlong - * @date 2020/6/10 18:53 - */ -@Data -public class LoginCode { - - /** - * 验证码配置 - */ - private LoginCodeEnum codeType; - /** - * 验证码有效期 分钟 - */ - private Long expiration = 2L; - /** - * 验证码内容长度 - */ - private int length = 2; - /** - * 验证码宽度 - */ - private int width = 111; - /** - * 验证码高度 - */ - private int height = 36; - /** - * 验证码字体 - */ - private String fontName; - /** - * 字体大小 - */ - private int fontSize = 25; - - public LoginCodeEnum getCodeType() { - return codeType; - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/security/config/bean/LoginCodeEnum.java b/wjcy-system/src/main/java/me/zhengjie/modules/security/config/bean/LoginCodeEnum.java deleted file mode 100644 index 9ff398f..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/security/config/bean/LoginCodeEnum.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2019-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.security.config.bean; - -/** - * 验证码配置枚举 - * - * @author: liaojinlong - * @date: 2020/6/10 17:40 - */ - -public enum LoginCodeEnum { - /** - * 算数 - */ - arithmetic, - /** - * 中文 - */ - chinese, - /** - * 中文闪图 - */ - chinese_gif, - /** - * 闪图 - */ - gif, - spec -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/security/config/bean/LoginProperties.java b/wjcy-system/src/main/java/me/zhengjie/modules/security/config/bean/LoginProperties.java deleted file mode 100644 index b13f173..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/security/config/bean/LoginProperties.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2019-2020 the original author or authors. - * - * Licensed under the Apache License, Version loginCode.length.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-loginCode.length.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.security.config.bean; - -import com.wf.captcha.*; -import com.wf.captcha.base.Captcha; -import lombok.Data; -import me.zhengjie.exception.BadConfigurationException; -import me.zhengjie.utils.StringUtils; - -import java.awt.*; -import java.util.Objects; - -/** - * 配置文件读取 - * - * @author liaojinlong - * @date loginCode.length0loginCode.length0/6/10 17:loginCode.length6 - */ -@Data -public class LoginProperties { - - /** - * 账号单用户 登录 - */ - private boolean singleLogin = false; - - private LoginCode loginCode; - - /** - * 用户登录信息缓存 - */ - private boolean cacheEnable; - - public boolean isSingleLogin() { - return singleLogin; - } - - public boolean isCacheEnable() { - return cacheEnable; - } - - /** - * 获取验证码生产类 - * - * @return / - */ - public Captcha getCaptcha() { - if (Objects.isNull(loginCode)) { - loginCode = new LoginCode(); - if (Objects.isNull(loginCode.getCodeType())) { - loginCode.setCodeType(LoginCodeEnum.arithmetic); - } - } - return switchCaptcha(loginCode); - } - - /** - * 依据配置信息生产验证码 - * - * @param loginCode 验证码配置信息 - * @return / - */ - private Captcha switchCaptcha(LoginCode loginCode) { - Captcha captcha; - synchronized (this) { - switch (loginCode.getCodeType()) { - case arithmetic: - // 算术类型 https://gitee.com/whvse/EasyCaptcha - captcha = new FixedArithmeticCaptcha(loginCode.getWidth(), loginCode.getHeight()); - // 几位数运算,默认是两位 - captcha.setLen(loginCode.getLength()); - break; - case chinese: - captcha = new ChineseCaptcha(loginCode.getWidth(), loginCode.getHeight()); - captcha.setLen(loginCode.getLength()); - break; - case chinese_gif: - captcha = new ChineseGifCaptcha(loginCode.getWidth(), loginCode.getHeight()); - captcha.setLen(loginCode.getLength()); - break; - case gif: - captcha = new GifCaptcha(loginCode.getWidth(), loginCode.getHeight()); - captcha.setLen(loginCode.getLength()); - break; - case spec: - captcha = new SpecCaptcha(loginCode.getWidth(), loginCode.getHeight()); - captcha.setLen(loginCode.getLength()); - break; - default: - throw new BadConfigurationException("验证码配置信息错误!正确配置查看 LoginCodeEnum "); - } - } - if(StringUtils.isNotBlank(loginCode.getFontName())){ - captcha.setFont(new Font(loginCode.getFontName(), Font.PLAIN, loginCode.getFontSize())); - } - return captcha; - } - - static class FixedArithmeticCaptcha extends ArithmeticCaptcha { - public FixedArithmeticCaptcha(int width, int height) { - super(width, height); - } - - @Override - protected char[] alphas() { - // 生成随机数字和运算符 - int n1 = num(1, 10), n2 = num(1, 10); - int opt = num(3); - - // 计算结果 - int res = new int[]{n1 + n2, n1 - n2, n1 * n2}[opt]; - // 转换为字符运算符 - char optChar = "+-x".charAt(opt); - - this.setArithmeticString(String.format("%s%c%s=?", n1, optChar, n2)); - this.chars = String.valueOf(res); - - return chars.toCharArray(); - } - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/security/config/bean/SecurityProperties.java b/wjcy-system/src/main/java/me/zhengjie/modules/security/config/bean/SecurityProperties.java deleted file mode 100644 index 16ec3cf..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/security/config/bean/SecurityProperties.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.security.config.bean; - -import lombok.Data; - -/** - * Jwt参数配置 - * - * @author Zheng Jie - * @date 2019年11月28日 - */ -@Data -public class SecurityProperties { - - /** - * Request Headers : Authorization - */ - private String header; - - /** - * 令牌前缀,最后留个空格 Bearer - */ - private String tokenStartWith; - - /** - * 必须使用最少88位的Base64对该令牌进行编码 - */ - private String base64Secret; - - /** - * 令牌过期时间 此处单位/毫秒 - */ - private Long tokenValidityInSeconds; - - /** - * 在线用户 key,根据 key 查询 redis 中在线用户的数据 - */ - private String onlineKey; - - /** - * 验证码 key - */ - private String codeKey; - - /** - * token 续期检查 - */ - private Long detect; - - /** - * 续期时间 - */ - private Long renew; - - public String getTokenStartWith() { - return tokenStartWith + " "; - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/security/rest/AuthorizationController.java b/wjcy-system/src/main/java/me/zhengjie/modules/security/rest/AuthorizationController.java deleted file mode 100644 index c9180cf..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/security/rest/AuthorizationController.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.security.rest; - -import cn.hutool.core.map.MapUtil; -import cn.hutool.core.util.IdUtil; -import cn.hutool.core.util.ObjectUtil; -import com.wf.captcha.base.Captcha; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.annotation.Log; -import me.zhengjie.annotation.rest.AnonymousDeleteMapping; -import me.zhengjie.annotation.rest.AnonymousGetMapping; -import me.zhengjie.annotation.rest.AnonymousPostMapping; -import me.zhengjie.annotation.type.LogActionType; -import me.zhengjie.config.RsaProperties; -import me.zhengjie.dto.Dto; -import me.zhengjie.error.ErrorCodeEnum; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.modules.security.config.bean.LoginCodeEnum; -import me.zhengjie.modules.security.config.bean.LoginProperties; -import me.zhengjie.modules.security.config.bean.SecurityProperties; -import me.zhengjie.modules.security.security.TokenProvider; -import me.zhengjie.modules.security.service.OnlineUserService; -import me.zhengjie.modules.security.service.dto.AuthUserDto; -import me.zhengjie.modules.security.service.dto.JwtUserDto; -import me.zhengjie.modules.utils.GoogleAuthenticatorUtil; -import me.zhengjie.service.LoginIpService; -import me.zhengjie.service.SettingSiteService; -import me.zhengjie.utils.*; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -import static me.zhengjie.error.ErrorCodeEnum.LOGIN_PWD_ERROR; - -/** - * @author Zheng Jie - * @date 2018-11-23 - * 授权、根据token获取用户详细信息 - */ -@Slf4j -@RestController -@RequestMapping("/api/auth") -@RequiredArgsConstructor -@Api(tags = "系统:系统授权接口") -public class AuthorizationController { - private final SecurityProperties properties; - private final RedisUtils redisUtils; - private final OnlineUserService onlineUserService; - private final TokenProvider tokenProvider; - private final AuthenticationManagerBuilder authenticationManagerBuilder; - private final LoginIpService loginIpService; - - @Resource - private LoginProperties loginProperties; - @Resource - private SettingSiteService settingSiteService; - - @Log(value = "用户登录", type = LogActionType.LOGIN) - @ApiOperation("登录授权") - @AnonymousPostMapping(value = "/login") - public Object login(@Validated @RequestBody AuthUserDto authUser, HttpServletRequest request) throws Exception { - String ip = StringUtils.getIp(request); - if (!loginIpService.whiteListFlag(ip)) { - return Dto.getInstance(ErrorCodeEnum.BLOCKED_LOGIN_IP_ERROR); - } - - String BLOCKED_ACCOUNT = String.format(RedisUtils.BLOCKED_ACCOUNT, authUser.getUsername()); - Object obj = redisUtils.get(BLOCKED_ACCOUNT); - if (ObjectUtil.isNotEmpty(obj)) { - return Dto.getInstance(ErrorCodeEnum.BLOCKED_ACCOUNT_ERROR); - } - - // 如果Google Auth开启使用google Auth 验证 - if (settingSiteService.getGooleAuthSwitch()) { - // 第二个参数是 host -TODO 待确认 request.getRemoteHost() 是否是符合要求的域 - if (!GoogleAuthenticatorUtil.authcode(authUser.getCode(), GoogleAuthenticatorUtil.genSecret(authUser.getUsername(), request.getRemoteHost()))) { -// throw new BadRequestException("验证码错误"); - return Dto.getInstance(ErrorCodeEnum.ERROR_2222); - } - } else { - // 查询验证码 - String code = (String) redisUtils.get(authUser.getUuid()); - // 清除验证码 - redisUtils.del(authUser.getUuid()); - if (StringUtils.isBlank(code)) { - return Dto.getInstance(ErrorCodeEnum.ERROR_2223); - } - if (StringUtils.isBlank(authUser.getCode()) || !authUser.getCode().equalsIgnoreCase(code)) { - return Dto.getInstance(ErrorCodeEnum.ERROR_2222); - } - } - - // 密码解密 - Authentication authentication = null; - try { - - String password = RsaUtils.decryptByPrivateKey(RsaProperties.privateKey, authUser.getPassword()); - - UsernamePasswordAuthenticationToken authenticationToken = - new UsernamePasswordAuthenticationToken(authUser.getUsername(), password); - authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken); - SecurityContextHolder.getContext().setAuthentication(authentication); - } catch (Exception e) { - String key = String.format(RedisUtils.LOGIN_FAIL_COUNT, authUser.getUsername()); - Long count = redisUtils.incrAndExpire(key, 300); - if (count >=3) { - // 冻结账户,24小时内不允许登录 - Map map = MapUtil.of("time", DateUtil.getCurrentTime()); - redisUtils.set(BLOCKED_ACCOUNT, map, 3600 * 24); - redisUtils.del(key); - } - - return Dto.getInstance(LOGIN_PWD_ERROR); - } - - - // 生成令牌与第三方系统获取令牌方式 - // UserDetails userDetails = userDetailsService.loadUserByUsername(userInfo.getUsername()); - // Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); - // SecurityContextHolder.getContext().setAuthentication(authentication); - String token = tokenProvider.createToken(authentication); - final JwtUserDto jwtUserDto = (JwtUserDto) authentication.getPrincipal(); - // 保存在线信息 - onlineUserService.save(jwtUserDto, token, request); - // 返回 token 与 用户信息 - Map authInfo = new HashMap(2) {{ - put("token", properties.getTokenStartWith() + token); - put("user", jwtUserDto); - }}; - if (loginProperties.isSingleLogin()) { - //踢掉之前已经登录的token - onlineUserService.checkLoginOnUser(authUser.getUsername(), token); - } - return ResponseEntity.ok(authInfo); - } - - @ApiOperation("获取用户信息") - @GetMapping(value = "/info") - public ResponseEntity getUserInfo() { - return ResponseEntity.ok(SecurityUtils.getCurrentUser()); - } - - @ApiOperation("获取验证码") - @AnonymousGetMapping(value = "/code") - public ResponseEntity getCode() { - // 获取运算的结果 - Captcha captcha = loginProperties.getCaptcha(); - String uuid = properties.getCodeKey() + IdUtil.simpleUUID(); - //当验证码类型为 arithmetic时且长度 >= 2 时,captcha.text()的结果有几率为浮点型 - String captchaValue = captcha.text(); - if (captcha.getCharType() - 1 == LoginCodeEnum.arithmetic.ordinal() && captchaValue.contains(".")) { - captchaValue = captchaValue.split("\\.")[0]; - } - // 保存 - redisUtils.set(uuid, captchaValue, loginProperties.getLoginCode().getExpiration(), TimeUnit.MINUTES); - // 验证码信息 - Map imgResult = new HashMap(2) {{ - put("img", captcha.toBase64()); - put("uuid", uuid); - }}; - return ResponseEntity.ok(imgResult); - } - - @ApiOperation("退出登录") - @AnonymousDeleteMapping(value = "/logout") - public ResponseEntity logout(HttpServletRequest request) { - onlineUserService.logout(tokenProvider.getToken(request)); - return new ResponseEntity<>(HttpStatus.OK); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/security/rest/OnlineController.java b/wjcy-system/src/main/java/me/zhengjie/modules/security/rest/OnlineController.java deleted file mode 100644 index 016f06f..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/security/rest/OnlineController.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.security.rest; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import lombok.RequiredArgsConstructor; -import me.zhengjie.modules.security.service.OnlineUserService; -import me.zhengjie.utils.EncryptUtils; -import org.springframework.data.domain.Pageable; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.Set; - -/** - * @author Zheng Jie - */ -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/online") -@Api(tags = "系统:在线用户管理") -public class OnlineController { - - private final OnlineUserService onlineUserService; - - @ApiOperation("查询在线用户") - @GetMapping - @PreAuthorize("@el.check()") - public ResponseEntity query(String filter, Pageable pageable){ - return new ResponseEntity<>(onlineUserService.getAll(filter, pageable),HttpStatus.OK); - } - - @ApiOperation("导出数据") - @GetMapping(value = "/download") - @PreAuthorize("@el.check()") - public void download(HttpServletResponse response, String filter) throws IOException { - onlineUserService.download(onlineUserService.getAll(filter), response); - } - - @ApiOperation("踢出用户") - @DeleteMapping - @PreAuthorize("@el.check()") - public ResponseEntity delete(@RequestBody Set keys) throws Exception { - for (String key : keys) { - // 解密Key - key = EncryptUtils.desDecrypt(key); - onlineUserService.kickOut(key); - } - return new ResponseEntity<>(HttpStatus.OK); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/security/security/JwtAccessDeniedHandler.java b/wjcy-system/src/main/java/me/zhengjie/modules/security/security/JwtAccessDeniedHandler.java deleted file mode 100644 index 8b3f8c1..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/security/security/JwtAccessDeniedHandler.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.security.security; - -import org.springframework.security.access.AccessDeniedException; -import org.springframework.security.web.access.AccessDeniedHandler; -import org.springframework.stereotype.Component; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * @author Zheng Jie - */ -@Component -public class JwtAccessDeniedHandler implements AccessDeniedHandler { - - @Override - public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException { - //当用户在没有授权的情况下访问受保护的REST资源时,将调用此方法发送403 Forbidden响应 - response.sendError(HttpServletResponse.SC_FORBIDDEN, accessDeniedException.getMessage()); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/security/security/JwtAuthenticationEntryPoint.java b/wjcy-system/src/main/java/me/zhengjie/modules/security/security/JwtAuthenticationEntryPoint.java deleted file mode 100644 index f881586..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/security/security/JwtAuthenticationEntryPoint.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.security.security; - -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.web.AuthenticationEntryPoint; -import org.springframework.stereotype.Component; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * @author Zheng Jie - */ -@Component -public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint { - - @Override - public void commence(HttpServletRequest request, - HttpServletResponse response, - AuthenticationException authException) throws IOException { - // 当用户尝试访问安全的REST资源而不提供任何凭据时,将调用此方法发送401 响应 - response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException==null?"Unauthorized":authException.getMessage()); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/security/security/TokenConfigurer.java b/wjcy-system/src/main/java/me/zhengjie/modules/security/security/TokenConfigurer.java deleted file mode 100644 index 9e4e533..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/security/security/TokenConfigurer.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.security.security; - -import lombok.RequiredArgsConstructor; -import me.zhengjie.modules.security.config.bean.SecurityProperties; -import me.zhengjie.modules.security.service.OnlineUserService; -import me.zhengjie.modules.security.service.UserCacheClean; -import me.zhengjie.service.LoginIpService; -import org.springframework.security.config.annotation.SecurityConfigurerAdapter; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.web.DefaultSecurityFilterChain; -import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; - -/** - * @author / - */ -@RequiredArgsConstructor -public class TokenConfigurer extends SecurityConfigurerAdapter { - - private final TokenProvider tokenProvider; - private final SecurityProperties properties; - private final OnlineUserService onlineUserService; - private final UserCacheClean userCacheClean; - private final LoginIpService loginIpService; - - @Override - public void configure(HttpSecurity http) { - TokenFilter customFilter = new TokenFilter(tokenProvider, properties, onlineUserService, userCacheClean,loginIpService); - http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/security/security/TokenFilter.java b/wjcy-system/src/main/java/me/zhengjie/modules/security/security/TokenFilter.java deleted file mode 100644 index db96094..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/security/security/TokenFilter.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.security.security; - -import cn.hutool.core.util.StrUtil; -import io.jsonwebtoken.ExpiredJwtException; -import lombok.RequiredArgsConstructor; -import me.zhengjie.modules.security.config.bean.SecurityProperties; -import me.zhengjie.modules.security.service.OnlineUserService; -import me.zhengjie.modules.security.service.UserCacheClean; -import me.zhengjie.modules.security.service.dto.OnlineUserDto; -import me.zhengjie.service.LoginIpService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.util.StringUtils; -import org.springframework.web.filter.GenericFilterBean; - -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import java.io.IOException; -import java.util.Objects; - -/** - * @author / - */ -@RequiredArgsConstructor -public class TokenFilter extends GenericFilterBean { - private static final Logger log = LoggerFactory.getLogger(TokenFilter.class); - - - private final TokenProvider tokenProvider; - private final SecurityProperties properties; - private final OnlineUserService onlineUserService; - private final UserCacheClean userCacheClean; - private final LoginIpService loginIpService; - - @Override - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) - throws IOException, ServletException { - HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; - // 验证 -// String ip = me.zhengjie.utils.StringUtils.getIp(httpServletRequest); -// if (!loginIpService.whiteListFlag(ip)) { -// Dto dto = Dto.getInstance(ErrorCodeEnum.BLOCKED_LOGIN_IP_ERROR); -//// throw new BadRequestException(ErrorCodeEnum.BLOCKED_LOGIN_IP_ERROR); -// servletResponse.setContentType("application/json;charset=UTF-8"); -// servletResponse.getWriter().write(JSONUtil.toJsonStr(dto)); -// -// return; -// } - - String token = resolveToken(httpServletRequest); - // 对于 Token 为空的不需要去查 Redis - if (StrUtil.isNotBlank(token)) { - OnlineUserDto onlineUserDto = null; - boolean cleanUserCache = false; - try { - onlineUserDto = onlineUserService.getOne(properties.getOnlineKey() + token); - } catch (ExpiredJwtException e) { - log.error(e.getMessage()); - cleanUserCache = true; - } finally { - if (cleanUserCache || Objects.isNull(onlineUserDto)) { - userCacheClean.cleanUserCache(String.valueOf(tokenProvider.getClaims(token).get(TokenProvider.AUTHORITIES_KEY))); - } - } - if (onlineUserDto != null && StringUtils.hasText(token)) { - Authentication authentication = tokenProvider.getAuthentication(token); - SecurityContextHolder.getContext().setAuthentication(authentication); - // Token 续期 -// tokenProvider.checkRenewal(token); - } - } - filterChain.doFilter(servletRequest, servletResponse); - } - - /** - * 初步检测Token - * - * @param request / - * @return / - */ - private String resolveToken(HttpServletRequest request) { - String bearerToken = request.getHeader(properties.getHeader()); - if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(properties.getTokenStartWith())) { - // 去掉令牌前缀 - return bearerToken.replace(properties.getTokenStartWith(), ""); - } else { - log.debug("非法Token:{}", bearerToken); - } - return null; - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/security/security/TokenProvider.java b/wjcy-system/src/main/java/me/zhengjie/modules/security/security/TokenProvider.java deleted file mode 100644 index db98fba..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/security/security/TokenProvider.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.security.security; - -import cn.hutool.core.date.DateField; -import cn.hutool.core.date.DateUtil; -import cn.hutool.core.util.IdUtil; -import io.jsonwebtoken.*; -import io.jsonwebtoken.io.Decoders; -import io.jsonwebtoken.security.Keys; -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.modules.security.config.bean.SecurityProperties; -import me.zhengjie.utils.RedisUtils; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.userdetails.User; -import org.springframework.stereotype.Component; -import javax.servlet.http.HttpServletRequest; -import java.security.Key; -import java.util.*; -import java.util.concurrent.TimeUnit; - -/** - * @author / - */ -@Slf4j -@Component -public class TokenProvider implements InitializingBean { - - private final SecurityProperties properties; - private final RedisUtils redisUtils; - public static final String AUTHORITIES_KEY = "user"; - private JwtParser jwtParser; - private JwtBuilder jwtBuilder; - - public TokenProvider(SecurityProperties properties, RedisUtils redisUtils) { - this.properties = properties; - this.redisUtils = redisUtils; - } - - @Override - public void afterPropertiesSet() { - byte[] keyBytes = Decoders.BASE64.decode(properties.getBase64Secret()); - Key key = Keys.hmacShaKeyFor(keyBytes); - jwtParser = Jwts.parserBuilder() - .setSigningKey(key) - .build(); - jwtBuilder = Jwts.builder() - .signWith(key, SignatureAlgorithm.HS512); - } - - /** - * 创建Token 设置永不过期, - * Token 的时间有效性转到Redis 维护 - * - * @param authentication / - * @return / - */ - public String createToken(Authentication authentication) { - return jwtBuilder - // 加入ID确保生成的 Token 都不一致 - .setId(IdUtil.simpleUUID()) - .claim(AUTHORITIES_KEY, authentication.getName()) - .setSubject(authentication.getName()) - .compact(); - } - - /** - * 依据Token 获取鉴权信息 - * - * @param token / - * @return / - */ - Authentication getAuthentication(String token) { - Claims claims = getClaims(token); - User principal = new User(claims.getSubject(), "******", new ArrayList<>()); - return new UsernamePasswordAuthenticationToken(principal, token, new ArrayList<>()); - } - - public Claims getClaims(String token) { - return jwtParser - .parseClaimsJws(token) - .getBody(); - } - - /** - * @param token 需要检查的token - */ - public void checkRenewal(String token) { - // 判断是否续期token,计算token的过期时间 - long time = redisUtils.getExpire(properties.getOnlineKey() + token) * 1000; - Date expireDate = DateUtil.offset(new Date(), DateField.MILLISECOND, (int) time); - // 判断当前时间与过期时间的时间差 - long differ = expireDate.getTime() - System.currentTimeMillis(); - // 如果在续期检查的范围内,则续期 - if (differ <= properties.getDetect()) { - long renew = time + properties.getRenew(); - redisUtils.expire(properties.getOnlineKey() + token, renew, TimeUnit.MILLISECONDS); - } - } - - public String getToken(HttpServletRequest request) { - final String requestHeader = request.getHeader(properties.getHeader()); - if (requestHeader != null && requestHeader.startsWith(properties.getTokenStartWith())) { - return requestHeader.substring(7); - } - return null; - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/security/service/OnlineUserService.java b/wjcy-system/src/main/java/me/zhengjie/modules/security/service/OnlineUserService.java deleted file mode 100644 index 96ebec4..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/security/service/OnlineUserService.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.security.service; - -import lombok.extern.slf4j.Slf4j; -import me.zhengjie.modules.security.config.bean.SecurityProperties; -import me.zhengjie.modules.security.service.dto.JwtUserDto; -import me.zhengjie.modules.security.service.dto.OnlineUserDto; -import me.zhengjie.utils.*; -import org.springframework.data.domain.Pageable; -import org.springframework.scheduling.annotation.Async; -import org.springframework.stereotype.Service; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.*; - -/** - * @author Zheng Jie - * @date 2019年10月26日21:56:27 - */ -@Service -@Slf4j -public class OnlineUserService { - - private final SecurityProperties properties; - private final RedisUtils redisUtils; - - public OnlineUserService(SecurityProperties properties, RedisUtils redisUtils) { - this.properties = properties; - this.redisUtils = redisUtils; - } - - /** - * 保存在线用户信息 - * @param jwtUserDto / - * @param token / - * @param request / - */ - public void save(JwtUserDto jwtUserDto, String token, HttpServletRequest request){ - String dept = /*jwtUserDto.getUser().getDept().getName();*/null; - String ip = StringUtils.getIp(request); - String browser = StringUtils.getBrowser(request); -// String address = StringUtils.getCityInfo(ip); - OnlineUserDto onlineUserDto = null; - try { - onlineUserDto = new OnlineUserDto(jwtUserDto.getUsername(), jwtUserDto.getUser().getNickName(), dept, browser , ip, null, EncryptUtils.desEncrypt(token), new Date()); - } catch (Exception e) { - log.error(e.getMessage(),e); - } - redisUtils.set(properties.getOnlineKey() + token, onlineUserDto, properties.getTokenValidityInSeconds()/1000); - } - - /** - * 查询全部数据 - * @param filter / - * @param pageable / - * @return / - */ - public Map getAll(String filter, Pageable pageable){ - List onlineUserDtos = getAll(filter); - return PageUtil.toPage( - PageUtil.toPage(pageable.getPageNumber(),pageable.getPageSize(), onlineUserDtos), - onlineUserDtos.size() - ); - } - - /** - * 查询全部数据,不分页 - * @param filter / - * @return / - */ - public List getAll(String filter){ - List keys = redisUtils.scan(properties.getOnlineKey() + "*"); - Collections.reverse(keys); - List onlineUserDtos = new ArrayList<>(); - for (String key : keys) { - OnlineUserDto onlineUserDto = (OnlineUserDto) redisUtils.get(key); - if(StringUtils.isNotBlank(filter)){ - if(onlineUserDto.toString().contains(filter)){ - onlineUserDtos.add(onlineUserDto); - } - } else { - onlineUserDtos.add(onlineUserDto); - } - } - onlineUserDtos.sort((o1, o2) -> o2.getLoginTime().compareTo(o1.getLoginTime())); - return onlineUserDtos; - } - - /** - * 踢出用户 - * @param key / - */ - public void kickOut(String key){ - key = properties.getOnlineKey() + key; - redisUtils.del(key); - } - - /** - * 退出登录 - * @param token / - */ - public void logout(String token) { - String key = properties.getOnlineKey() + token; - redisUtils.del(key); - } - - /** - * 导出 - * @param all / - * @param response / - * @throws IOException / - */ - public void download(List all, HttpServletResponse response) throws IOException { - List> list = new ArrayList<>(); - for (OnlineUserDto user : all) { - Map map = new LinkedHashMap<>(); - map.put("用户名", user.getUserName()); - map.put("部门", user.getDept()); - map.put("登录IP", user.getIp()); - map.put("登录地点", user.getAddress()); - map.put("浏览器", user.getBrowser()); - map.put("登录日期", user.getLoginTime()); - list.add(map); - } - FileUtil.downloadExcel(list, response); - } - - /** - * 查询用户 - * @param key / - * @return / - */ - public OnlineUserDto getOne(String key) { - return (OnlineUserDto)redisUtils.get(key); - } - - /** - * 检测用户是否在之前已经登录,已经登录踢下线 - * @param userName 用户名 - */ - public void checkLoginOnUser(String userName, String igoreToken){ - List onlineUserDtos = getAll(userName); - if(onlineUserDtos ==null || onlineUserDtos.isEmpty()){ - return; - } - for(OnlineUserDto onlineUserDto : onlineUserDtos){ - if(onlineUserDto.getUserName().equals(userName)){ - try { - String token =EncryptUtils.desDecrypt(onlineUserDto.getKey()); - if(StringUtils.isNotBlank(igoreToken)&&!igoreToken.equals(token)){ - this.kickOut(token); - }else if(StringUtils.isBlank(igoreToken)){ - this.kickOut(token); - } - } catch (Exception e) { - log.error("checkUser is error",e); - } - } - } - } - - /** - * 根据用户名强退用户 - * @param username / - */ - @Async - public void kickOutForUsername(String username) throws Exception { - List onlineUsers = getAll(username); - for (OnlineUserDto onlineUser : onlineUsers) { - if (onlineUser.getUserName().equals(username)) { - String token =EncryptUtils.desDecrypt(onlineUser.getKey()); - kickOut(token); - } - } - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/security/service/UserCacheClean.java b/wjcy-system/src/main/java/me/zhengjie/modules/security/service/UserCacheClean.java deleted file mode 100644 index 3f9fe5b..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/security/service/UserCacheClean.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2019-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package me.zhengjie.modules.security.service; - -import me.zhengjie.utils.StringUtils; -import org.springframework.stereotype.Component; - -/** - * @author: liaojinlong - * @date: 2020/6/11 18:01 - * @apiNote: 用于清理 用户登录信息缓存,为防止Spring循环依赖与安全考虑 ,单独构成工具类 - */ -@Component -public class UserCacheClean { - - /** - * 清理特定用户缓存信息
- * 用户信息变更时 - * - * @param userName / - */ - public void cleanUserCache(String userName) { - if (StringUtils.isNotEmpty(userName)) { - UserDetailsServiceImpl.userDtoCache.remove(userName); - } - } - - /** - * 清理所有用户的缓存信息
- * ,如发生角色授权信息变化,可以简便的全部失效缓存 - */ - public void cleanAll() { - UserDetailsServiceImpl.userDtoCache.clear(); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/security/service/UserDetailsServiceImpl.java b/wjcy-system/src/main/java/me/zhengjie/modules/security/service/UserDetailsServiceImpl.java deleted file mode 100644 index c3657d1..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/security/service/UserDetailsServiceImpl.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.security.service; - -import lombok.RequiredArgsConstructor; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.exception.EntityNotFoundException; -import me.zhengjie.modules.security.config.bean.LoginProperties; -import me.zhengjie.modules.security.service.dto.JwtUserDto; -import me.zhengjie.modules.system.service.DataService; -import me.zhengjie.modules.system.service.RoleService; -import me.zhengjie.modules.system.service.UserService; -import me.zhengjie.modules.system.service.dto.UserDto; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * @author Zheng Jie - * @date 2018-11-22 - */ -@RequiredArgsConstructor -@Service("userDetailsService") -public class UserDetailsServiceImpl implements UserDetailsService { - private final UserService userService; - private final RoleService roleService; - private final DataService dataService; - private final LoginProperties loginProperties; - - public void setEnableCache(boolean enableCache) { - this.loginProperties.setCacheEnable(enableCache); - } - - /** - * 用户信息缓存 - * - * @see {@link UserCacheClean} - */ - static Map userDtoCache = new ConcurrentHashMap<>(); - - @Override - public JwtUserDto loadUserByUsername(String username) { - boolean searchDb = true; - JwtUserDto jwtUserDto = null; - if (loginProperties.isCacheEnable() && userDtoCache.containsKey(username)) { - jwtUserDto = userDtoCache.get(username); - // 检查dataScope是否修改 - List dataScopes = jwtUserDto.getDataScopes(); - dataScopes.clear(); - dataScopes.addAll(dataService.getDeptIds(jwtUserDto.getUser())); - searchDb = false; - } - if (searchDb) { - UserDto user; - try { - user = userService.findByName(username); - } catch (EntityNotFoundException e) { - // SpringSecurity会自动转换UsernameNotFoundException为BadCredentialsException - throw new UsernameNotFoundException("", e); - } - if (user == null) { - throw new UsernameNotFoundException(""); - } else { - if (!user.getEnabled()) { - throw new BadRequestException("账号未激活!"); - } - jwtUserDto = new JwtUserDto( - user, - dataService.getDeptIds(user), - roleService.mapToGrantedAuthorities(user) - ); - userDtoCache.put(username, jwtUserDto); - } - } - return jwtUserDto; - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/security/service/dto/AuthUserDto.java b/wjcy-system/src/main/java/me/zhengjie/modules/security/service/dto/AuthUserDto.java deleted file mode 100644 index 5219fc5..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/security/service/dto/AuthUserDto.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.security.service.dto; - -import lombok.Getter; -import lombok.Setter; -import javax.validation.constraints.NotBlank; - -/** - * @author Zheng Jie - * @date 2018-11-30 - */ -@Getter -@Setter -public class AuthUserDto { - - @NotBlank - private String username; - - @NotBlank - private String password; - - private String code; - - private String uuid = ""; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/security/service/dto/JwtUserDto.java b/wjcy-system/src/main/java/me/zhengjie/modules/security/service/dto/JwtUserDto.java deleted file mode 100644 index 00f4372..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/security/service/dto/JwtUserDto.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.security.service.dto; - -import com.alibaba.fastjson.annotation.JSONField; -import lombok.AllArgsConstructor; -import lombok.Getter; -import me.zhengjie.modules.system.service.dto.UserDto; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.userdetails.UserDetails; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * @author Zheng Jie - * @date 2018-11-23 - */ -@Getter -@AllArgsConstructor -public class JwtUserDto implements UserDetails { - - private final UserDto user; - - private final List dataScopes; - - @JSONField(serialize = false) - private final List authorities; - - public Set getRoles() { - return authorities.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toSet()); - } - - @Override - @JSONField(serialize = false) - public String getPassword() { - return user.getPassword(); - } - - @Override - @JSONField(serialize = false) - public String getUsername() { - return user.getUsername(); - } - - @JSONField(serialize = false) - @Override - public boolean isAccountNonExpired() { - return true; - } - - @JSONField(serialize = false) - @Override - public boolean isAccountNonLocked() { - return true; - } - - @JSONField(serialize = false) - @Override - public boolean isCredentialsNonExpired() { - return true; - } - - @Override - @JSONField(serialize = false) - public boolean isEnabled() { - return user.getEnabled(); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/security/service/dto/OnlineUserDto.java b/wjcy-system/src/main/java/me/zhengjie/modules/security/service/dto/OnlineUserDto.java deleted file mode 100644 index 290ab6d..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/security/service/dto/OnlineUserDto.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.security.service.dto; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import java.util.Date; - -/** - * 在线用户 - * @author Zheng Jie - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class OnlineUserDto { - - /** - * 用户名 - */ - private String userName; - - /** - * 昵称 - */ - private String nickName; - - /** - * 岗位 - */ - private String dept; - - /** - * 浏览器 - */ - private String browser; - - /** - * IP - */ - private String ip; - - /** - * 地址 - */ - private String address; - - /** - * token - */ - private String key; - - /** - * 登录时间 - */ - private Date loginTime; - - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/domain/Dept.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/domain/Dept.java deleted file mode 100644 index 9f28af2..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/domain/Dept.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.domain; - -import com.alibaba.fastjson.annotation.JSONField; -import io.swagger.annotations.ApiModelProperty; -import lombok.Getter; -import lombok.Setter; -import me.zhengjie.base.BaseEntity; -import javax.persistence.*; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import java.io.Serializable; -import java.util.Objects; -import java.util.Set; - -/** -* @author Zheng Jie -* @date 2019-03-25 -*/ -@Entity -@Getter -@Setter -@Table(name="sys_dept") -public class Dept extends BaseEntity implements Serializable { - - @Id - @Column(name = "dept_id") - @NotNull(groups = Update.class) - @ApiModelProperty(value = "ID", hidden = true) - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @JSONField(serialize = false) - @ManyToMany(mappedBy = "depts") - @ApiModelProperty(value = "角色") - private Set roles; - - @ApiModelProperty(value = "排序") - private Integer deptSort; - - @NotBlank - @ApiModelProperty(value = "部门名称") - private String name; - - @NotNull - @ApiModelProperty(value = "是否启用") - private Boolean enabled; - - @ApiModelProperty(value = "上级部门") - private Long pid; - - @ApiModelProperty(value = "子节点数目", hidden = true) - private Integer subCount = 0; - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - Dept dept = (Dept) o; - return Objects.equals(id, dept.id) && - Objects.equals(name, dept.name); - } - - @Override - public int hashCode() { - return Objects.hash(id, name); - } -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/domain/Dict.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/domain/Dict.java deleted file mode 100644 index 689cf2e..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/domain/Dict.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.domain; - -import io.swagger.annotations.ApiModelProperty; -import lombok.Getter; -import lombok.Setter; -import me.zhengjie.base.BaseEntity; -import javax.persistence.*; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import java.io.Serializable; -import java.util.List; - -/** -* @author Zheng Jie -* @date 2019-04-10 -*/ -@Entity -@Getter -@Setter -@Table(name="sys_dict") -public class Dict extends BaseEntity implements Serializable { - - @Id - @Column(name = "dict_id") - @NotNull(groups = Update.class) - @ApiModelProperty(value = "ID", hidden = true) - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @OneToMany(mappedBy = "dict",cascade={CascadeType.PERSIST,CascadeType.REMOVE}) - private List dictDetails; - - @NotBlank - @ApiModelProperty(value = "名称") - private String name; - - @ApiModelProperty(value = "描述") - private String description; -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/domain/DictDetail.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/domain/DictDetail.java deleted file mode 100644 index 554dde6..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/domain/DictDetail.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.domain; - -import io.swagger.annotations.ApiModelProperty; -import lombok.Getter; -import lombok.Setter; -import me.zhengjie.base.BaseEntity; -import javax.persistence.*; -import javax.validation.constraints.NotNull; -import java.io.Serializable; - -/** -* @author Zheng Jie -* @date 2019-04-10 -*/ -@Entity -@Getter -@Setter -@Table(name="sys_dict_detail") -public class DictDetail extends BaseEntity implements Serializable { - - @Id - @Column(name = "detail_id") - @NotNull(groups = Update.class) - @ApiModelProperty(value = "ID", hidden = true) - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @JoinColumn(name = "dict_id") - @ManyToOne(fetch=FetchType.LAZY) - @ApiModelProperty(value = "字典", hidden = true) - private Dict dict; - - @ApiModelProperty(value = "字典标签") - private String label; - - @ApiModelProperty(value = "字典值") - private String value; - - @ApiModelProperty(value = "排序") - private Integer dictSort = 999; -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/domain/Job.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/domain/Job.java deleted file mode 100644 index f2d358a..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/domain/Job.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.domain; - -import io.swagger.annotations.ApiModelProperty; -import lombok.Getter; -import lombok.Setter; -import me.zhengjie.base.BaseEntity; -import javax.persistence.*; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import java.io.Serializable; -import java.util.Objects; - -/** -* @author Zheng Jie -* @date 2019-03-29 -*/ -@Entity -@Getter -@Setter -@Table(name="sys_job") -public class Job extends BaseEntity implements Serializable { - - @Id - @Column(name = "job_id") - @NotNull(groups = Update.class) - @ApiModelProperty(value = "ID", hidden = true) - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @NotBlank - @ApiModelProperty(value = "岗位名称") - private String name; - - @NotNull - @ApiModelProperty(value = "岗位排序") - private Long jobSort; - - @NotNull - @ApiModelProperty(value = "是否启用") - private Boolean enabled; - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - Job job = (Job) o; - return Objects.equals(id, job.id); - } - - @Override - public int hashCode() { - return Objects.hash(id); - } -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/domain/Menu.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/domain/Menu.java deleted file mode 100644 index b2ea225..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/domain/Menu.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.domain; - -import com.alibaba.fastjson.annotation.JSONField; -import io.swagger.annotations.ApiModelProperty; -import lombok.Getter; -import lombok.Setter; -import me.zhengjie.base.BaseEntity; - -import javax.persistence.*; -import javax.validation.constraints.NotNull; -import java.io.Serializable; -import java.util.Objects; -import java.util.Set; - -/** - * @author Zheng Jie - * @date 2018-12-17 - */ -@Entity -@Getter -@Setter -@Table(name = "sys_menu") -public class Menu extends BaseEntity implements Serializable { - - @Id - @Column(name = "menu_id") - @NotNull(groups = {Update.class}) - @ApiModelProperty(value = "ID", hidden = true) - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @JSONField(serialize = false) - @ManyToMany(mappedBy = "menus") - @ApiModelProperty(value = "菜单角色") - private Set roles; - - @ApiModelProperty(value = "菜单标题") - private String title; - - @Column(name = "name") - @ApiModelProperty(value = "菜单组件名称") - private String componentName; - - @ApiModelProperty(value = "排序") - private Integer menuSort = 999; - - @ApiModelProperty(value = "组件路径") - private String component; - - @ApiModelProperty(value = "路由地址") - private String path; - - @ApiModelProperty(value = "菜单类型,目录、菜单、按钮") - private Integer type; - - @ApiModelProperty(value = "权限标识") - private String permission; - - @ApiModelProperty(value = "菜单图标") - private String icon; - - @Column(columnDefinition = "bit(1) default 0") - @ApiModelProperty(value = "缓存") - private Boolean cache; - - @Column(columnDefinition = "bit(1) default 0") - @ApiModelProperty(value = "是否隐藏") - private Boolean hidden; - - @ApiModelProperty(value = "上级菜单") - private Long pid; - - @ApiModelProperty(value = "子节点数目", hidden = true) - private Integer subCount = 0; - - @ApiModelProperty(value = "外链菜单") - private Boolean iFrame; - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - Menu menu = (Menu) o; - return Objects.equals(id, menu.id); - } - - @Override - public int hashCode() { - return Objects.hash(id); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/domain/Role.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/domain/Role.java deleted file mode 100644 index 8b3ad19..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/domain/Role.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.domain; - -import com.alibaba.fastjson.annotation.JSONField; -import io.swagger.annotations.ApiModelProperty; -import lombok.Getter; -import lombok.Setter; -import me.zhengjie.base.BaseEntity; -import me.zhengjie.utils.enums.DataScopeEnum; - -import javax.persistence.*; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import java.io.Serializable; -import java.util.Objects; -import java.util.Set; - -/** - * 角色 - * @author Zheng Jie - * @date 2018-11-22 - */ -@Getter -@Setter -@Entity -@Table(name = "sys_role") -public class Role extends BaseEntity implements Serializable { - - @Id - @Column(name = "role_id") - @NotNull(groups = {Update.class}) - @GeneratedValue(strategy = GenerationType.IDENTITY) - @ApiModelProperty(value = "ID", hidden = true) - private Long id; - - @JSONField(serialize = false) - @ManyToMany(mappedBy = "roles") - @ApiModelProperty(value = "用户", hidden = true) - private Set users; - - @ManyToMany - @JoinTable(name = "sys_roles_menus", - joinColumns = {@JoinColumn(name = "role_id",referencedColumnName = "role_id")}, - inverseJoinColumns = {@JoinColumn(name = "menu_id",referencedColumnName = "menu_id")}) - @ApiModelProperty(value = "菜单", hidden = true) - private Set menus; - - @ManyToMany - @JoinTable(name = "sys_roles_depts", - joinColumns = {@JoinColumn(name = "role_id",referencedColumnName = "role_id")}, - inverseJoinColumns = {@JoinColumn(name = "dept_id",referencedColumnName = "dept_id")}) - @ApiModelProperty(value = "部门", hidden = true) - private Set depts; - - @NotBlank - @ApiModelProperty(value = "名称", hidden = true) - private String name; - - @ApiModelProperty(value = "数据权限,全部 、 本级 、 自定义") - private String dataScope = DataScopeEnum.THIS_LEVEL.getValue(); - - @Column(name = "level") - @ApiModelProperty(value = "级别,数值越小,级别越大") - private Integer level = 3; - - @ApiModelProperty(value = "描述") - private String description; - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - Role role = (Role) o; - return Objects.equals(id, role.id); - } - - @Override - public int hashCode() { - return Objects.hash(id); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/domain/User.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/domain/User.java deleted file mode 100644 index c496c91..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/domain/User.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.domain; - -import io.swagger.annotations.ApiModelProperty; -import lombok.Getter; -import lombok.Setter; -import me.zhengjie.annotation.CheckPwd; -import me.zhengjie.base.BaseEntity; -import javax.persistence.*; -import javax.validation.constraints.Email; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Null; -import java.io.Serializable; -import java.util.Date; -import java.util.Objects; -import java.util.Set; - -/** - * @author Zheng Jie - * @date 2018-11-22 - */ -@Entity -@Getter -@Setter -@Table(name="sys_user") -public class User extends BaseEntity implements Serializable { - - @Id - @Column(name = "user_id") - @NotNull(groups = Update.class) - @GeneratedValue(strategy = GenerationType.IDENTITY) - @ApiModelProperty(value = "ID", hidden = true) - private Long id; - - @ManyToMany - @ApiModelProperty(value = "用户角色") - @JoinTable(name = "sys_users_roles", - joinColumns = {@JoinColumn(name = "user_id",referencedColumnName = "user_id")}, - inverseJoinColumns = {@JoinColumn(name = "role_id",referencedColumnName = "role_id")}) - private Set roles; - - @ManyToMany - @ApiModelProperty(value = "用户岗位") - @JoinTable(name = "sys_users_jobs", - joinColumns = {@JoinColumn(name = "user_id",referencedColumnName = "user_id")}, - inverseJoinColumns = {@JoinColumn(name = "job_id",referencedColumnName = "job_id")}) - private Set jobs; - - @OneToOne - @JoinColumn(name = "dept_id") - @ApiModelProperty(value = "用户部门") - private Dept dept; - - @NotBlank(groups = Create.class) - @Column(unique = true) - @ApiModelProperty(value = "用户名称") - private String username; - - @NotBlank(groups = Create.class) - @ApiModelProperty(value = "用户昵称") - private String nickName; - - @Email(groups = Create.class) - @NotBlank(groups = Create.class) - @ApiModelProperty(value = "邮箱") - private String email; - - @NotBlank(groups = Create.class) - @ApiModelProperty(value = "电话号码") - private String phone; - - @ApiModelProperty(value = "用户性别") - private String gender; - - @ApiModelProperty(value = "头像真实名称",hidden = true) - private String avatarName; - - @ApiModelProperty(value = "头像存储的路径", hidden = true) - private String avatarPath; - - @NotBlank(groups = Create.class) - @CheckPwd(groups = Create.class) - @ApiModelProperty(value = "密码") - private String password; - - @NotNull(groups = Create.class) - @ApiModelProperty(value = "是否启用") - private Boolean enabled; - - @ApiModelProperty(value = "是否为admin账号", hidden = true) - private Boolean isAdmin = false; - - @Column(name = "pwd_reset_time") - @ApiModelProperty(value = "最后修改密码的时间", hidden = true) - private Date pwdResetTime; - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - User user = (User) o; - return Objects.equals(id, user.id) && - Objects.equals(username, user.username); - } - - @Override - public int hashCode() { - return Objects.hash(id, username); - } -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/domain/vo/MenuMetaVo.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/domain/vo/MenuMetaVo.java deleted file mode 100644 index 647baa8..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/domain/vo/MenuMetaVo.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.domain.vo; - -import lombok.AllArgsConstructor; -import lombok.Data; -import java.io.Serializable; - -/** - * @author Zheng Jie - * @date 2018-12-20 - */ -@Data -@AllArgsConstructor -public class MenuMetaVo implements Serializable { - - private String title; - - private String icon; - - private Boolean noCache; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/domain/vo/MenuVo.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/domain/vo/MenuVo.java deleted file mode 100644 index 82fc0cc..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/domain/vo/MenuVo.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.domain.vo; - -import com.fasterxml.jackson.annotation.JsonInclude; -import lombok.Data; -import java.io.Serializable; -import java.util.List; - -/** - * 构建前端路由时用到 - * @author Zheng Jie - * @date 2018-12-20 - */ -@Data -@JsonInclude(JsonInclude.Include.NON_EMPTY) -public class MenuVo implements Serializable { - - private String name; - - private String path; - - private Boolean hidden; - - private String redirect; - - private String component; - - private Boolean alwaysShow; - - private MenuMetaVo meta; - - private List children; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/domain/vo/UserPassVo.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/domain/vo/UserPassVo.java deleted file mode 100644 index e92d472..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/domain/vo/UserPassVo.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.domain.vo; - -import lombok.Data; -import me.zhengjie.annotation.CheckPwd; - -import javax.validation.constraints.NotBlank; - -/** - * 修改密码的 Vo 类 - * @author Zheng Jie - * @date 2019年7月11日13:59:49 - */ -@Data -public class UserPassVo { - - private String oldPass; - - // 注:这里传的是加密后的字符串 - @NotBlank -// @CheckPwd - private String newPass; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/repository/DeptRepository.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/repository/DeptRepository.java deleted file mode 100644 index 9858322..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/repository/DeptRepository.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.repository; - -import me.zhengjie.modules.system.domain.Dept; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; -import org.springframework.data.jpa.repository.Modifying; -import org.springframework.data.jpa.repository.Query; -import java.util.List; -import java.util.Set; - -/** -* @author Zheng Jie -* @date 2019-03-25 -*/ -public interface DeptRepository extends JpaRepository, JpaSpecificationExecutor { - - /** - * 根据 PID 查询 - * @param id pid - * @return / - */ - List findByPid(Long id); - - /** - * 获取顶级部门 - * @return / - */ - List findByPidIsNull(); - - /** - * 根据角色ID 查询 - * @param roleId 角色ID - * @return / - */ - @Query(value = "select d.* from sys_dept d, sys_roles_depts r where " + - "d.dept_id = r.dept_id and r.role_id = ?1", nativeQuery = true) - Set findByRoleId(Long roleId); - - /** - * 判断是否存在子节点 - * @param pid / - * @return / - */ - int countByPid(Long pid); - - /** - * 根据ID更新sub_count - * @param count / - * @param id / - */ - @Modifying - @Query(value = " update sys_dept set sub_count = ?1 where dept_id = ?2 ",nativeQuery = true) - void updateSubCntById(Integer count, Long id); -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/repository/DictDetailRepository.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/repository/DictDetailRepository.java deleted file mode 100644 index d80b970..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/repository/DictDetailRepository.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.repository; - -import me.zhengjie.modules.system.domain.DictDetail; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; - -import java.util.List; - -/** -* @author Zheng Jie -* @date 2019-04-10 -*/ -public interface DictDetailRepository extends JpaRepository, JpaSpecificationExecutor { - - /** - * 根据字典名称查询 - * @param name / - * @return / - */ - List findByDictName(String name); -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/repository/DictRepository.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/repository/DictRepository.java deleted file mode 100644 index f09b6d1..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/repository/DictRepository.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.repository; - -import me.zhengjie.modules.system.domain.Dict; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; - -import java.util.List; -import java.util.Set; - -/** -* @author Zheng Jie -* @date 2019-04-10 -*/ -public interface DictRepository extends JpaRepository, JpaSpecificationExecutor { - - /** - * 删除 - * @param ids / - */ - void deleteByIdIn(Set ids); - - /** - * 查询 - * @param ids / - * @return / - */ - List findByIdIn(Set ids); -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/repository/JobRepository.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/repository/JobRepository.java deleted file mode 100644 index e39ebf0..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/repository/JobRepository.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.repository; - -import me.zhengjie.modules.system.domain.Job; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; - -import java.util.Set; - -/** -* @author Zheng Jie -* @date 2019-03-29 -*/ -public interface JobRepository extends JpaRepository, JpaSpecificationExecutor { - - /** - * 根据名称查询 - * @param name 名称 - * @return / - */ - Job findByName(String name); - - /** - * 根据Id删除 - * @param ids / - */ - void deleteAllByIdIn(Set ids); -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/repository/MenuRepository.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/repository/MenuRepository.java deleted file mode 100644 index 0907606..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/repository/MenuRepository.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.repository; - -import me.zhengjie.modules.system.domain.Menu; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; -import org.springframework.data.jpa.repository.Modifying; -import org.springframework.data.jpa.repository.Query; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; - -/** - * @author Zheng Jie - * @date 2018-12-17 - */ -public interface MenuRepository extends JpaRepository, JpaSpecificationExecutor { - - /** - * 根据菜单标题查询 - * @param title 菜单标题 - * @return / - */ - Menu findByTitle(String title); - - /** - * 根据组件名称查询 - * @param name 组件名称 - * @return / - */ - Menu findByComponentName(String name); - - /** - * 根据菜单的 PID 查询 - * @param pid / - * @return / - */ - List findByPid(long pid); - - /** - * 查询顶级菜单 - * @return / - */ - List findByPidIsNull(); - - /** - * 根据角色ID与菜单类型查询菜单 - * @param roleIds roleIDs - * @param type 类型 - * @return / - */ - @Query(value = "SELECT m.* FROM sys_menu m, sys_roles_menus r WHERE " + - "m.menu_id = r.menu_id AND r.role_id IN ?1 AND type != ?2 order by m.menu_sort asc",nativeQuery = true) - LinkedHashSet findByRoleIdsAndTypeNot(Set roleIds, int type); - - /** - * 获取节点数量 - * @param id / - * @return / - */ - int countByPid(Long id); - - /** - * 更新节点数目 - * @param count / - * @param menuId / - */ - @Modifying - @Query(value = " update sys_menu set sub_count = ?1 where menu_id = ?2 ",nativeQuery = true) - void updateSubCntById(int count, Long menuId); -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/repository/RoleRepository.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/repository/RoleRepository.java deleted file mode 100644 index 8e76cc5..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/repository/RoleRepository.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.repository; - -import me.zhengjie.modules.system.domain.Role; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; -import org.springframework.data.jpa.repository.Modifying; -import org.springframework.data.jpa.repository.Query; - -import java.util.List; -import java.util.Set; - -/** - * @author Zheng Jie - * @date 2018-12-03 - */ -public interface RoleRepository extends JpaRepository, JpaSpecificationExecutor { - - /** - * 根据名称查询 - * @param name / - * @return / - */ - Role findByName(String name); - - /** - * 删除多个角色 - * @param ids / - */ - void deleteAllByIdIn(Set ids); - - /** - * 根据用户ID查询 - * @param id 用户ID - * @return / - */ - @Query(value = "SELECT r.* FROM sys_role r, sys_users_roles u WHERE " + - "r.role_id = u.role_id AND u.user_id = ?1",nativeQuery = true) - Set findByUserId(Long id); - - /** - * 解绑角色菜单 - * @param id 菜单ID - */ - @Modifying - @Query(value = "delete from sys_roles_menus where menu_id = ?1",nativeQuery = true) - void untiedMenu(Long id); - - /** - * 根据部门查询 - * @param deptIds / - * @return / - */ - @Query(value = "select count(1) from sys_role r, sys_roles_depts d where " + - "r.role_id = d.role_id and d.dept_id in ?1",nativeQuery = true) - int countByDepts(Set deptIds); - - /** - * 根据菜单Id查询 - * @param menuIds / - * @return / - */ - @Query(value = "SELECT r.* FROM sys_role r, sys_roles_menus m WHERE " + - "r.role_id = m.role_id AND m.menu_id in ?1",nativeQuery = true) - List findInMenuId(List menuIds); -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/repository/UserRepository.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/repository/UserRepository.java deleted file mode 100644 index c5c88a8..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/repository/UserRepository.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.repository; - -import me.zhengjie.modules.system.domain.User; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; -import org.springframework.data.jpa.repository.Modifying; -import org.springframework.data.jpa.repository.Query; -import java.util.Date; -import java.util.List; -import java.util.Set; - -/** - * @author Zheng Jie - * @date 2018-11-22 - */ -public interface UserRepository extends JpaRepository, JpaSpecificationExecutor { - - /** - * 根据用户名查询 - * @param username 用户名 - * @return / - */ - User findByUsername(String username); - - /** - * 根据邮箱查询 - * @param email 邮箱 - * @return / - */ - User findByEmail(String email); - - /** - * 根据手机号查询 - * @param phone 手机号 - * @return / - */ - User findByPhone(String phone); - - /** - * 修改密码 - * @param username 用户名 - * @param pass 密码 - * @param lastPasswordResetTime / - */ - @Modifying - @Query(value = "update sys_user set password = ?2 , pwd_reset_time = ?3 where username = ?1",nativeQuery = true) - void updatePass(String username, String pass, Date lastPasswordResetTime); - - /** - * 修改邮箱 - * @param username 用户名 - * @param email 邮箱 - */ - @Modifying - @Query(value = "update sys_user set email = ?2 where username = ?1",nativeQuery = true) - void updateEmail(String username, String email); - - /** - * 根据角色查询用户 - * @param roleId / - * @return / - */ - @Query(value = "SELECT u.* FROM sys_user u, sys_users_roles r WHERE" + - " u.user_id = r.user_id AND r.role_id = ?1", nativeQuery = true) - List findByRoleId(Long roleId); - - /** - * 根据角色中的部门查询 - * @param deptId / - * @return / - */ - @Query(value = "SELECT u.* FROM sys_user u, sys_users_roles r, sys_roles_depts d WHERE " + - "u.user_id = r.user_id AND r.role_id = d.role_id AND d.dept_id = ?1 group by u.user_id", nativeQuery = true) - List findByRoleDeptId(Long deptId); - - /** - * 根据菜单查询 - * @param id 菜单ID - * @return / - */ - @Query(value = "SELECT u.* FROM sys_user u, sys_users_roles ur, sys_roles_menus rm WHERE\n" + - "u.user_id = ur.user_id AND ur.role_id = rm.role_id AND rm.menu_id = ?1 group by u.user_id", nativeQuery = true) - List findByMenuId(Long id); - - /** - * 根据Id删除 - * @param ids / - */ - void deleteAllByIdIn(Set ids); - - /** - * 根据岗位查询 - * @param ids / - * @return / - */ - @Query(value = "SELECT count(1) FROM sys_user u, sys_users_jobs j WHERE u.user_id = j.user_id AND j.job_id IN ?1", nativeQuery = true) - int countByJobs(Set ids); - - /** - * 根据部门查询 - * @param deptIds / - * @return / - */ - @Query(value = "SELECT count(1) FROM sys_user u WHERE u.dept_id IN ?1", nativeQuery = true) - int countByDepts(Set deptIds); - - /** - * 根据角色查询 - * @param ids / - * @return / - */ - @Query(value = "SELECT count(1) FROM sys_user u, sys_users_roles r WHERE " + - "u.user_id = r.user_id AND r.role_id in ?1", nativeQuery = true) - int countByRoles(Set ids); -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/rest/DeptController.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/rest/DeptController.java deleted file mode 100644 index 9b3b0ef..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/rest/DeptController.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.rest; - -import cn.hutool.core.collection.CollectionUtil; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import lombok.RequiredArgsConstructor; -import me.zhengjie.annotation.Log; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.modules.system.domain.Dept; -import me.zhengjie.modules.system.service.DeptService; -import me.zhengjie.modules.system.service.dto.DeptDto; -import me.zhengjie.modules.system.service.dto.DeptQueryCriteria; -import me.zhengjie.utils.PageUtil; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; -import javax.servlet.http.HttpServletResponse; -import java.util.*; - -/** -* @author Zheng Jie -* @date 2019-03-25 -*/ -@RestController -@RequiredArgsConstructor -@Api(tags = "系统:部门管理") -@RequestMapping("/api/dept") -public class DeptController { - - private final DeptService deptService; - private static final String ENTITY_NAME = "dept"; - - @ApiOperation("导出部门数据") - @GetMapping(value = "/download") - @PreAuthorize("@el.check('dept:list')") - public void download(HttpServletResponse response, DeptQueryCriteria criteria) throws Exception { - deptService.download(deptService.queryAll(criteria, false), response); - } - - @ApiOperation("查询部门") - @GetMapping - @PreAuthorize("@el.check('user:list','dept:list')") - public ResponseEntity query(DeptQueryCriteria criteria) throws Exception { - List deptDtos = deptService.queryAll(criteria, true); - return new ResponseEntity<>(PageUtil.toPage(deptDtos, deptDtos.size()),HttpStatus.OK); - } - - @ApiOperation("查询部门:根据ID获取同级与上级数据") - @PostMapping("/superior") - @PreAuthorize("@el.check('user:list','dept:list')") - public ResponseEntity getSuperior(@RequestBody List ids) { - Set deptDtos = new LinkedHashSet<>(); - for (Long id : ids) { - DeptDto deptDto = deptService.findById(id); - List depts = deptService.getSuperior(deptDto, new ArrayList<>()); - deptDtos.addAll(depts); - } - return new ResponseEntity<>(deptService.buildTree(new ArrayList<>(deptDtos)),HttpStatus.OK); - } - - @Log("新增部门") - @ApiOperation("新增部门") - @PostMapping - @PreAuthorize("@el.check('dept:add')") - public ResponseEntity create(@Validated @RequestBody Dept resources){ - if (resources.getId() != null) { - throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID"); - } - deptService.create(resources); - return new ResponseEntity<>(HttpStatus.CREATED); - } - - @Log("修改部门") - @ApiOperation("修改部门") - @PutMapping - @PreAuthorize("@el.check('dept:edit')") - public ResponseEntity update(@Validated(Dept.Update.class) @RequestBody Dept resources){ - deptService.update(resources); - return new ResponseEntity<>(HttpStatus.NO_CONTENT); - } - - @Log("删除部门") - @ApiOperation("删除部门") - @DeleteMapping - @PreAuthorize("@el.check('dept:del')") - public ResponseEntity delete(@RequestBody Set ids){ - Set deptDtos = new HashSet<>(); - for (Long id : ids) { - List deptList = deptService.findByPid(id); - deptDtos.add(deptService.findById(id)); - if(CollectionUtil.isNotEmpty(deptList)){ - deptDtos = deptService.getDeleteDepts(deptList, deptDtos); - } - } - // 验证是否被角色或用户关联 - deptService.verification(deptDtos); - deptService.delete(deptDtos); - return new ResponseEntity<>(HttpStatus.OK); - } -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/rest/DictController.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/rest/DictController.java deleted file mode 100644 index f1e4d58..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/rest/DictController.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.rest; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import lombok.RequiredArgsConstructor; -import me.zhengjie.annotation.Log; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.modules.system.domain.Dict; -import me.zhengjie.modules.system.service.DictService; -import me.zhengjie.modules.system.service.dto.DictQueryCriteria; -import org.springframework.data.domain.Pageable; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.Set; - -/** -* @author Zheng Jie -* @date 2019-04-10 -*/ -@RestController -@RequiredArgsConstructor -@Api(tags = "系统:字典管理") -@RequestMapping("/api/dict") -public class DictController { - - private final DictService dictService; - private static final String ENTITY_NAME = "dict"; - - @ApiOperation("导出字典数据") - @GetMapping(value = "/download") - @PreAuthorize("@el.check('dict:list')") - public void download(HttpServletResponse response, DictQueryCriteria criteria) throws IOException { - dictService.download(dictService.queryAll(criteria), response); - } - - @ApiOperation("查询字典") - @GetMapping(value = "/all") - @PreAuthorize("@el.check('dict:list')") - public ResponseEntity queryAll(){ - return new ResponseEntity<>(dictService.queryAll(new DictQueryCriteria()),HttpStatus.OK); - } - - @ApiOperation("查询字典") - @GetMapping - @PreAuthorize("@el.check('dict:list')") - public ResponseEntity query(DictQueryCriteria resources, Pageable pageable){ - return new ResponseEntity<>(dictService.queryAll(resources,pageable),HttpStatus.OK); - } - - @Log("新增字典") - @ApiOperation("新增字典") - @PostMapping - @PreAuthorize("@el.check('dict:add')") - public ResponseEntity create(@Validated @RequestBody Dict resources){ - if (resources.getId() != null) { - throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID"); - } - dictService.create(resources); - return new ResponseEntity<>(HttpStatus.CREATED); - } - - @Log("修改字典") - @ApiOperation("修改字典") - @PutMapping - @PreAuthorize("@el.check('dict:edit')") - public ResponseEntity update(@Validated(Dict.Update.class) @RequestBody Dict resources){ - dictService.update(resources); - return new ResponseEntity<>(HttpStatus.NO_CONTENT); - } - - @Log("删除字典") - @ApiOperation("删除字典") - @DeleteMapping - @PreAuthorize("@el.check('dict:del')") - public ResponseEntity delete(@RequestBody Set ids){ - dictService.delete(ids); - return new ResponseEntity<>(HttpStatus.OK); - } -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/rest/DictDetailController.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/rest/DictDetailController.java deleted file mode 100644 index 92f65fd..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/rest/DictDetailController.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.rest; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import lombok.RequiredArgsConstructor; -import me.zhengjie.annotation.Log; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.modules.system.domain.DictDetail; -import me.zhengjie.modules.system.service.DictDetailService; -import me.zhengjie.modules.system.service.dto.DictDetailDto; -import me.zhengjie.modules.system.service.dto.DictDetailQueryCriteria; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.data.web.PageableDefault; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** -* @author Zheng Jie -* @date 2019-04-10 -*/ -@RestController -@RequiredArgsConstructor -@Api(tags = "系统:字典详情管理") -@RequestMapping("/api/dictDetail") -public class DictDetailController { - - private final DictDetailService dictDetailService; - private static final String ENTITY_NAME = "dictDetail"; - - @ApiOperation("查询字典详情") - @GetMapping - public ResponseEntity query(DictDetailQueryCriteria criteria, - @PageableDefault(sort = {"dictSort"}, direction = Sort.Direction.ASC) Pageable pageable){ - return new ResponseEntity<>(dictDetailService.queryAll(criteria,pageable),HttpStatus.OK); - } - - @ApiOperation("查询多个字典详情") - @GetMapping(value = "/map") - public ResponseEntity getDictDetailMaps(@RequestParam String dictName){ - String[] names = dictName.split("[,,]"); - Map> dictMap = new HashMap<>(16); - for (String name : names) { - dictMap.put(name, dictDetailService.getDictByName(name)); - } - return new ResponseEntity<>(dictMap, HttpStatus.OK); - } - - @Log("新增字典详情") - @ApiOperation("新增字典详情") - @PostMapping - @PreAuthorize("@el.check('dict:add')") - public ResponseEntity create(@Validated @RequestBody DictDetail resources){ - if (resources.getId() != null) { - throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID"); - } - dictDetailService.create(resources); - return new ResponseEntity<>(HttpStatus.CREATED); - } - - @Log("修改字典详情") - @ApiOperation("修改字典详情") - @PutMapping - @PreAuthorize("@el.check('dict:edit')") - public ResponseEntity update(@Validated(DictDetail.Update.class) @RequestBody DictDetail resources){ - dictDetailService.update(resources); - return new ResponseEntity<>(HttpStatus.NO_CONTENT); - } - - @Log("删除字典详情") - @ApiOperation("删除字典详情") - @DeleteMapping(value = "/{id}") - @PreAuthorize("@el.check('dict:del')") - public ResponseEntity delete(@PathVariable Long id){ - dictDetailService.delete(id); - return new ResponseEntity<>(HttpStatus.OK); - } -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/rest/JobController.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/rest/JobController.java deleted file mode 100644 index cac14c0..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/rest/JobController.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.rest; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import lombok.RequiredArgsConstructor; -import me.zhengjie.annotation.Log; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.modules.system.domain.Job; -import me.zhengjie.modules.system.service.JobService; -import me.zhengjie.modules.system.service.dto.JobQueryCriteria; -import org.springframework.data.domain.Pageable; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.Set; - -/** -* @author Zheng Jie -* @date 2019-03-29 -*/ -@RestController -@RequiredArgsConstructor -@Api(tags = "系统:岗位管理") -@RequestMapping("/api/job") -public class JobController { - - private final JobService jobService; - private static final String ENTITY_NAME = "job"; - - @ApiOperation("导出岗位数据") - @GetMapping(value = "/download") - @PreAuthorize("@el.check('job:list')") - public void download(HttpServletResponse response, JobQueryCriteria criteria) throws IOException { - jobService.download(jobService.queryAll(criteria), response); - } - - @ApiOperation("查询岗位") - @GetMapping - @PreAuthorize("@el.check('job:list','user:list')") - public ResponseEntity query(JobQueryCriteria criteria, Pageable pageable){ - return new ResponseEntity<>(jobService.queryAll(criteria, pageable),HttpStatus.OK); - } - - @Log("新增岗位") - @ApiOperation("新增岗位") - @PostMapping - @PreAuthorize("@el.check('job:add')") - public ResponseEntity create(@Validated @RequestBody Job resources){ - if (resources.getId() != null) { - throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID"); - } - jobService.create(resources); - return new ResponseEntity<>(HttpStatus.CREATED); - } - - @Log("修改岗位") - @ApiOperation("修改岗位") - @PutMapping - @PreAuthorize("@el.check('job:edit')") - public ResponseEntity update(@Validated(Job.Update.class) @RequestBody Job resources){ - jobService.update(resources); - return new ResponseEntity<>(HttpStatus.NO_CONTENT); - } - - @Log("删除岗位") - @ApiOperation("删除岗位") - @DeleteMapping - @PreAuthorize("@el.check('job:del')") - public ResponseEntity delete(@RequestBody Set ids){ - // 验证是否被用户关联 - jobService.verification(ids); - jobService.delete(ids); - return new ResponseEntity<>(HttpStatus.OK); - } -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/rest/LimitController.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/rest/LimitController.java deleted file mode 100644 index 329c5ac..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/rest/LimitController.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.rest; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import me.zhengjie.annotation.Limit; -import me.zhengjie.annotation.rest.AnonymousGetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import java.util.concurrent.atomic.AtomicInteger; - -/** - * @author / - * 接口限流测试类 - */ -@RestController -@RequestMapping("/api/limit") -@Api(tags = "系统:限流测试管理") -public class LimitController { - - private static final AtomicInteger ATOMIC_INTEGER = new AtomicInteger(); - - /** - * 测试限流注解,下面配置说明该接口 60秒内最多只能访问 10次,保存到redis的键名为 limit_test, - */ - @AnonymousGetMapping - @ApiOperation("测试") - @Limit(key = "test", period = 60, count = 10, name = "testLimit", prefix = "limit") - public int test() { - return ATOMIC_INTEGER.incrementAndGet(); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/rest/MenuController.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/rest/MenuController.java deleted file mode 100644 index d5461a2..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/rest/MenuController.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.rest; - -import cn.hutool.core.collection.CollectionUtil; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import lombok.RequiredArgsConstructor; -import me.zhengjie.annotation.Log; -import me.zhengjie.modules.system.domain.Menu; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.modules.system.service.MenuService; -import me.zhengjie.modules.system.service.dto.MenuDto; -import me.zhengjie.modules.system.service.dto.MenuQueryCriteria; -import me.zhengjie.modules.system.service.mapstruct.MenuMapper; -import me.zhengjie.utils.PageUtil; -import me.zhengjie.utils.SecurityUtils; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; -import javax.servlet.http.HttpServletResponse; -import java.util.*; -import java.util.stream.Collectors; - -/** - * @author Zheng Jie - * @date 2018-12-03 - */ - -@RestController -@RequiredArgsConstructor -@Api(tags = "系统:菜单管理") -@RequestMapping("/api/menus") -public class MenuController { - - private final MenuService menuService; - private final MenuMapper menuMapper; - private static final String ENTITY_NAME = "menu"; - - @ApiOperation("导出菜单数据") - @GetMapping(value = "/download") - @PreAuthorize("@el.check('menu:list')") - public void download(HttpServletResponse response, MenuQueryCriteria criteria) throws Exception { - menuService.download(menuService.queryAll(criteria, false), response); - } - - @GetMapping(value = "/build") - @ApiOperation("获取前端所需菜单") - public ResponseEntity buildMenus(){ - List menuDtoList = menuService.findByUser(SecurityUtils.getCurrentUserId()); - List menuDtos = menuService.buildTree(menuDtoList); - return new ResponseEntity<>(menuService.buildMenus(menuDtos),HttpStatus.OK); - } - - @ApiOperation("返回全部的菜单") - @GetMapping(value = "/lazy") - @PreAuthorize("@el.check('menu:list','roles:list')") - public ResponseEntity query(@RequestParam Long pid){ - return new ResponseEntity<>(menuService.getMenus(pid),HttpStatus.OK); - } - - @ApiOperation("根据菜单ID返回所有子节点ID,包含自身ID") - @GetMapping(value = "/child") - @PreAuthorize("@el.check('menu:list','roles:list')") - public ResponseEntity child(@RequestParam Long id){ - Set menuSet = new HashSet<>(); - List menuList = menuService.getMenus(id); - menuSet.add(menuService.findOne(id)); - menuSet = menuService.getChildMenus(menuMapper.toEntity(menuList), menuSet); - Set ids = menuSet.stream().map(Menu::getId).collect(Collectors.toSet()); - return new ResponseEntity<>(ids,HttpStatus.OK); - } - - @GetMapping - @ApiOperation("查询菜单") - @PreAuthorize("@el.check('menu:list')") - public ResponseEntity query(MenuQueryCriteria criteria) throws Exception { - List menuDtoList = menuService.queryAll(criteria, true); - return new ResponseEntity<>(PageUtil.toPage(menuDtoList, menuDtoList.size()),HttpStatus.OK); - } - - @ApiOperation("查询菜单:根据ID获取同级与上级数据") - @PostMapping("/superior") - @PreAuthorize("@el.check('menu:list')") - public ResponseEntity getSuperior(@RequestBody List ids) { - Set menuDtos = new LinkedHashSet<>(); - if(CollectionUtil.isNotEmpty(ids)){ - for (Long id : ids) { - MenuDto menuDto = menuService.findById(id); - menuDtos.addAll(menuService.getSuperior(menuDto, new ArrayList<>())); - } - return new ResponseEntity<>(menuService.buildTree(new ArrayList<>(menuDtos)),HttpStatus.OK); - } - return new ResponseEntity<>(menuService.getMenus(null),HttpStatus.OK); - } - - @Log("新增菜单") - @ApiOperation("新增菜单") - @PostMapping - @PreAuthorize("@el.check('menu:add')") - public ResponseEntity create(@Validated @RequestBody Menu resources){ - if (resources.getId() != null) { - throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID"); - } - menuService.create(resources); - return new ResponseEntity<>(HttpStatus.CREATED); - } - - @Log("修改菜单") - @ApiOperation("修改菜单") - @PutMapping - @PreAuthorize("@el.check('menu:edit')") - public ResponseEntity update(@Validated(Menu.Update.class) @RequestBody Menu resources){ - menuService.update(resources); - return new ResponseEntity<>(HttpStatus.NO_CONTENT); - } - - @Log("删除菜单") - @ApiOperation("删除菜单") - @DeleteMapping - @PreAuthorize("@el.check('menu:del')") - public ResponseEntity delete(@RequestBody Set ids){ - Set menuSet = new HashSet<>(); - for (Long id : ids) { - List menuList = menuService.getMenus(id); - menuSet.add(menuService.findOne(id)); - menuSet = menuService.getChildMenus(menuMapper.toEntity(menuList), menuSet); - } - menuService.delete(menuSet); - return new ResponseEntity<>(HttpStatus.OK); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/rest/MonitorController.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/rest/MonitorController.java deleted file mode 100644 index 35ac0c5..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/rest/MonitorController.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.rest; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import lombok.RequiredArgsConstructor; -import me.zhengjie.modules.system.service.MonitorService; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; - -/** - * @author Zheng Jie - * @date 2020-05-02 - */ -@RestController -@RequiredArgsConstructor -@Api(tags = "系统-服务监控管理") -@RequestMapping("/api/monitor") -public class MonitorController { - - private final MonitorService serverService; - - @GetMapping - @ApiOperation("查询服务监控") - @PreAuthorize("@el.check('monitor:list')") - public ResponseEntity query(){ - return new ResponseEntity<>(serverService.getServers(),HttpStatus.OK); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/rest/RoleController.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/rest/RoleController.java deleted file mode 100644 index a1edc93..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/rest/RoleController.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.rest; - -import cn.hutool.core.lang.Dict; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import lombok.RequiredArgsConstructor; -import me.zhengjie.annotation.Log; -import me.zhengjie.modules.system.domain.Role; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.modules.system.service.RoleService; -import me.zhengjie.modules.system.service.dto.RoleDto; -import me.zhengjie.modules.system.service.dto.RoleQueryCriteria; -import me.zhengjie.modules.system.service.dto.RoleSmallDto; -import me.zhengjie.utils.SecurityUtils; -import org.springframework.data.domain.Pageable; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * @author Zheng Jie - * @date 2018-12-03 - */ -@RestController -@RequiredArgsConstructor -@Api(tags = "系统:角色管理") -@RequestMapping("/api/roles") -public class RoleController { - - private final RoleService roleService; - - private static final String ENTITY_NAME = "role"; - - @ApiOperation("获取单个role") - @GetMapping(value = "/{id}") - @PreAuthorize("@el.check('roles:list')") - public ResponseEntity query(@PathVariable Long id){ - return new ResponseEntity<>(roleService.findById(id), HttpStatus.OK); - } - - @ApiOperation("导出角色数据") - @GetMapping(value = "/download") - @PreAuthorize("@el.check('role:list')") - public void download(HttpServletResponse response, RoleQueryCriteria criteria) throws IOException { - roleService.download(roleService.queryAll(criteria), response); - } - - @ApiOperation("返回全部的角色") - @GetMapping(value = "/all") - @PreAuthorize("@el.check('roles:list','user:add','user:edit')") - public ResponseEntity query(){ - return new ResponseEntity<>(roleService.queryAll(),HttpStatus.OK); - } - - @ApiOperation("查询角色") - @GetMapping - @PreAuthorize("@el.check('roles:list')") - public ResponseEntity query(RoleQueryCriteria criteria, Pageable pageable){ - return new ResponseEntity<>(roleService.queryAll(criteria,pageable),HttpStatus.OK); - } - - @ApiOperation("获取用户级别") - @GetMapping(value = "/level") - public ResponseEntity getLevel(){ - return new ResponseEntity<>(Dict.create().set("level", getLevels(null)),HttpStatus.OK); - } - - @Log("新增角色") - @ApiOperation("新增角色") - @PostMapping - @PreAuthorize("@el.check('roles:add')") - public ResponseEntity create(@Validated @RequestBody Role resources){ - if (resources.getId() != null) { - throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID"); - } - getLevels(resources.getLevel()); - roleService.create(resources); - return new ResponseEntity<>(HttpStatus.CREATED); - } - - @Log("修改角色") - @ApiOperation("修改角色") - @PutMapping - @PreAuthorize("@el.check('roles:edit')") - public ResponseEntity update(@Validated(Role.Update.class) @RequestBody Role resources){ - getLevels(resources.getLevel()); - roleService.update(resources); - return new ResponseEntity<>(HttpStatus.NO_CONTENT); - } - - @Log("修改角色菜单") - @ApiOperation("修改角色菜单") - @PutMapping(value = "/menu") - @PreAuthorize("@el.check('roles:edit')") - public ResponseEntity updateMenu(@RequestBody Role resources){ - RoleDto role = roleService.findById(resources.getId()); - getLevels(role.getLevel()); - roleService.updateMenu(resources,role); - return new ResponseEntity<>(HttpStatus.NO_CONTENT); - } - - @Log("删除角色") - @ApiOperation("删除角色") - @DeleteMapping - @PreAuthorize("@el.check('roles:del')") - public ResponseEntity delete(@RequestBody Set ids){ - for (Long id : ids) { - RoleDto role = roleService.findById(id); - getLevels(role.getLevel()); - } - // 验证是否被用户关联 - roleService.verification(ids); - roleService.delete(ids); - return new ResponseEntity<>(HttpStatus.OK); - } - - /** - * 获取用户的角色级别 - * @return / - */ - private int getLevels(Integer level){ - List levels = roleService.findByUsersId(SecurityUtils.getCurrentUserId()).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList()); - int min = Collections.min(levels); - if(level != null){ - if(level < min){ - throw new BadRequestException("权限不足,你的角色级别:" + min + ",低于操作的角色级别:" + level); - } - } - return min; - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/rest/UserController.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/rest/UserController.java deleted file mode 100644 index a5e6dca..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/rest/UserController.java +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.rest; - -import cn.hutool.core.collection.CollectionUtil; -import cn.hutool.core.util.ObjectUtil; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import lombok.RequiredArgsConstructor; -import me.zhengjie.annotation.Log; -import me.zhengjie.base.BaseEntity; -import me.zhengjie.config.RsaProperties; -import me.zhengjie.dto.Dto; -import me.zhengjie.modules.system.domain.Dept; -import me.zhengjie.modules.system.service.DataService; -import me.zhengjie.modules.system.domain.User; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.modules.system.domain.vo.UserPassVo; -import me.zhengjie.modules.system.service.DeptService; -import me.zhengjie.modules.system.service.RoleService; -import me.zhengjie.modules.system.service.dto.RoleSmallDto; -import me.zhengjie.modules.system.service.dto.UserDto; -import me.zhengjie.modules.system.service.dto.UserQueryCriteria; -import me.zhengjie.modules.system.service.VerifyService; -import me.zhengjie.utils.*; -import me.zhengjie.modules.system.service.UserService; -import me.zhengjie.utils.enums.CodeEnum; -import org.springframework.data.domain.Pageable; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.util.CollectionUtils; -import org.springframework.util.ObjectUtils; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.*; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -/** - * @author Zheng Jie - * @date 2018-11-23 - */ -@Api(tags = "系统:用户管理") -@RestController -@RequestMapping("/api/users") -@RequiredArgsConstructor -public class UserController { - - private final PasswordEncoder passwordEncoder; - private final UserService userService; - private final DataService dataService; - private final DeptService deptService; - private final RoleService roleService; - private final VerifyService verificationCodeService; - private final RedisUtils redisUtils; - - @ApiOperation("导出用户数据") - @GetMapping(value = "/download") - @PreAuthorize("@el.check('user:list')") - public void download(HttpServletResponse response, UserQueryCriteria criteria) throws IOException { - userService.download(userService.queryAll(criteria), response); - } - - @ApiOperation("查询用户") - @GetMapping - @PreAuthorize("@el.check('user:list')") - public ResponseEntity query(UserQueryCriteria criteria, Pageable pageable){ - if (!ObjectUtils.isEmpty(criteria.getDeptId())) { - criteria.getDeptIds().add(criteria.getDeptId()); - // 先查找是否存在子节点 - List data = deptService.findByPid(criteria.getDeptId()); - // 然后把子节点的ID都加入到集合中 - criteria.getDeptIds().addAll(deptService.getDeptChildren(data)); - } - // 数据权限 - List dataScopes = dataService.getDeptIds(userService.findByName(SecurityUtils.getCurrentUsername())); - // criteria.getDeptIds() 不为空并且数据权限不为空则取交集 - if (!CollectionUtils.isEmpty(criteria.getDeptIds()) && !CollectionUtils.isEmpty(dataScopes)){ - // 取交集 - criteria.getDeptIds().retainAll(dataScopes); - if(!CollectionUtil.isEmpty(criteria.getDeptIds())){ - return new ResponseEntity<>(userService.queryAll(criteria,pageable),HttpStatus.OK); - } - } else { - // 否则取并集 - criteria.getDeptIds().addAll(dataScopes); - return new ResponseEntity<>(userService.queryAll(criteria,pageable),HttpStatus.OK); - } - return new ResponseEntity<>(PageUtil.toPage(null,0),HttpStatus.OK); - } - - /** - * 解冻账号 - * @author: zeng - */ - @GetMapping("/unfreeze") - @PreAuthorize("@el.check('user:list')") - public Dto unfreeze(String username) { - if (ObjectUtil.isEmpty(username)) { - return Dto.returnResult(null); - } - String key = String.format(RedisUtils.BLOCKED_ACCOUNT, username); - redisUtils.del(key); - return Dto.returnResult(true); - } - - @Log("新增用户") - @ApiOperation("新增用户") - @PostMapping - @PreAuthorize("@el.check('user:add')") - public ResponseEntity create(@Validated(BaseEntity.Create.class) @RequestBody User resources){ - checkLevel(resources); - // 默认密码 123456 - resources.setPassword(passwordEncoder.encode(resources.getPassword())); - userService.create(resources); - return new ResponseEntity<>(HttpStatus.CREATED); - } - - @Log("修改用户") - @ApiOperation("修改用户") - @PutMapping - @PreAuthorize("@el.check('user:edit')") - public ResponseEntity update(@Validated(User.Update.class) @RequestBody User resources) throws Exception { - checkLevel(resources); - userService.update(resources); - return new ResponseEntity<>(HttpStatus.NO_CONTENT); - } - - @Log("修改用户:个人中心") - @ApiOperation("修改用户:个人中心") - @PutMapping(value = "center") - public ResponseEntity center(@Validated(User.Update.class) @RequestBody User resources){ - if(!resources.getId().equals(SecurityUtils.getCurrentUserId())){ - throw new BadRequestException("不能修改他人资料"); - } - userService.updateCenter(resources); - return new ResponseEntity<>(HttpStatus.NO_CONTENT); - } - - @Log("删除用户") - @ApiOperation("删除用户") - @DeleteMapping - @PreAuthorize("@el.check('user:del')") - public ResponseEntity delete(@RequestBody Set ids){ - for (Long id : ids) { - Integer currentLevel = Collections.min(roleService.findByUsersId(SecurityUtils.getCurrentUserId()).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList())); - Integer optLevel = Collections.min(roleService.findByUsersId(id).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList())); - if (currentLevel > optLevel) { - throw new BadRequestException("角色权限不足,不能删除:" + userService.findById(id).getUsername()); - } - } - userService.delete(ids); - return new ResponseEntity<>(HttpStatus.OK); - } - - /** - * 修改密码 - * @param passVo 修改密码DTO - * @return - * @throws Exception - */ - @ApiOperation("修改密码") - @PostMapping(value = "/updatePass") - public ResponseEntity updatePass(@RequestBody @Validated UserPassVo passVo) throws Exception { - String oldPass = RsaUtils.decryptByPrivateKey(RsaProperties.privateKey,passVo.getOldPass()); - String newPass = RsaUtils.decryptByPrivateKey(RsaProperties.privateKey,passVo.getNewPass()); - UserDto user = userService.findByName(SecurityUtils.getCurrentUsername()); - if(!passwordEncoder.matches(oldPass, user.getPassword())){ - throw new BadRequestException("修改失败,旧密码错误"); - } - if(passwordEncoder.matches(newPass, user.getPassword())){ - throw new BadRequestException("新密码不能与旧密码相同"); - } - if (!Pattern.matches(CheckPwdValidator.p, newPass)) { - throw new BadRequestException("密码格式错误,必须包含大小写字母、数子、英文特殊符号,且长度在16~64之间!"); - } - userService.updatePass(user.getUsername(),passwordEncoder.encode(newPass)); - return new ResponseEntity<>(HttpStatus.OK); - } - - @ApiOperation("修改头像") - @PostMapping(value = "/updateAvatar") - public ResponseEntity updateAvatar(@RequestParam MultipartFile avatar){ - return new ResponseEntity<>(userService.updateAvatar(avatar), HttpStatus.OK); - } - - @Log("修改邮箱") - @ApiOperation("修改邮箱") - @PostMapping(value = "/updateEmail/{code}") - public ResponseEntity updateEmail(@PathVariable String code,@RequestBody User user) throws Exception { - String password = RsaUtils.decryptByPrivateKey(RsaProperties.privateKey,user.getPassword()); - UserDto userDto = userService.findByName(SecurityUtils.getCurrentUsername()); - if(!passwordEncoder.matches(password, userDto.getPassword())){ - throw new BadRequestException("密码错误"); - } - verificationCodeService.validated(CodeEnum.EMAIL_RESET_EMAIL_CODE.getKey() + user.getEmail(), code); - userService.updateEmail(userDto.getUsername(),user.getEmail()); - return new ResponseEntity<>(HttpStatus.OK); - } - - /** - * 如果当前用户的角色级别低于创建用户的角色级别,则抛出权限不足的错误 - * @param resources / - */ - private void checkLevel(User resources) { - Integer currentLevel = Collections.min(roleService.findByUsersId(SecurityUtils.getCurrentUserId()).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList())); - Integer optLevel = roleService.findByRoles(resources.getRoles()); - if (currentLevel > optLevel) { - throw new BadRequestException("角色权限不足"); - } - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/rest/VerifyController.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/rest/VerifyController.java deleted file mode 100644 index 09ba44b..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/rest/VerifyController.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.rest; - -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import lombok.RequiredArgsConstructor; -import me.zhengjie.domain.vo.EmailVo; -import me.zhengjie.service.EmailService; -import me.zhengjie.modules.system.service.VerifyService; -import me.zhengjie.utils.enums.CodeBiEnum; -import me.zhengjie.utils.enums.CodeEnum; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; -import java.util.Objects; - -/** - * @author Zheng Jie - * @date 2018-12-26 - */ -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/code") -@Api(tags = "系统:验证码管理") -public class VerifyController { - - private final VerifyService verificationCodeService; - private final EmailService emailService; - - @PostMapping(value = "/resetEmail") - @ApiOperation("重置邮箱,发送验证码") - public ResponseEntity resetEmail(@RequestParam String email){ - EmailVo emailVo = verificationCodeService.sendEmail(email, CodeEnum.EMAIL_RESET_EMAIL_CODE.getKey()); - emailService.send(emailVo,emailService.find()); - return new ResponseEntity<>(HttpStatus.OK); - } - - @PostMapping(value = "/email/resetPass") - @ApiOperation("重置密码,发送验证码") - public ResponseEntity resetPass(@RequestParam String email){ - EmailVo emailVo = verificationCodeService.sendEmail(email, CodeEnum.EMAIL_RESET_PWD_CODE.getKey()); - emailService.send(emailVo,emailService.find()); - return new ResponseEntity<>(HttpStatus.OK); - } - - @GetMapping(value = "/validated") - @ApiOperation("验证码验证") - public ResponseEntity validated(@RequestParam String email, @RequestParam String code, @RequestParam Integer codeBi){ - CodeBiEnum biEnum = CodeBiEnum.find(codeBi); - switch (Objects.requireNonNull(biEnum)){ - case ONE: - verificationCodeService.validated(CodeEnum.EMAIL_RESET_EMAIL_CODE.getKey() + email ,code); - break; - case TWO: - verificationCodeService.validated(CodeEnum.EMAIL_RESET_PWD_CODE.getKey() + email ,code); - break; - default: - break; - } - return new ResponseEntity<>(HttpStatus.OK); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/DataService.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/DataService.java deleted file mode 100644 index 10258d9..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/DataService.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service; - -import me.zhengjie.modules.system.service.dto.UserDto; -import java.util.List; - -/** - * 数据权限服务类 - * @author Zheng Jie - * @date 2020-05-07 - */ -public interface DataService { - - /** - * 获取数据权限 - * @param user / - * @return / - */ - List getDeptIds(UserDto user); -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/DeptService.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/DeptService.java deleted file mode 100644 index d589bf8..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/DeptService.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service; - -import me.zhengjie.modules.system.domain.Dept; -import me.zhengjie.modules.system.service.dto.DeptDto; -import me.zhengjie.modules.system.service.dto.DeptQueryCriteria; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.List; -import java.util.Set; - -/** -* @author Zheng Jie -* @date 2019-03-25 -*/ -public interface DeptService { - - /** - * 查询所有数据 - * @param criteria 条件 - * @param isQuery / - * @throws Exception / - * @return / - */ - List queryAll(DeptQueryCriteria criteria, Boolean isQuery) throws Exception; - - /** - * 根据ID查询 - * @param id / - * @return / - */ - DeptDto findById(Long id); - - /** - * 创建 - * @param resources / - */ - void create(Dept resources); - - /** - * 编辑 - * @param resources / - */ - void update(Dept resources); - - /** - * 删除 - * @param deptDtos / - * - */ - void delete(Set deptDtos); - - /** - * 根据PID查询 - * @param pid / - * @return / - */ - List findByPid(long pid); - - /** - * 根据角色ID查询 - * @param id / - * @return / - */ - Set findByRoleId(Long id); - - /** - * 导出数据 - * @param queryAll 待导出的数据 - * @param response / - * @throws IOException / - */ - void download(List queryAll, HttpServletResponse response) throws IOException; - - /** - * 获取待删除的部门 - * @param deptList / - * @param deptDtos / - * @return / - */ - Set getDeleteDepts(List deptList, Set deptDtos); - - /** - * 根据ID获取同级与上级数据 - * @param deptDto / - * @param depts / - * @return / - */ - List getSuperior(DeptDto deptDto, List depts); - - /** - * 构建树形数据 - * @param deptDtos / - * @return / - */ - Object buildTree(List deptDtos); - - /** - * 获取 - * @param deptList - * @return - */ - List getDeptChildren(List deptList); - - /** - * 验证是否被角色或用户关联 - * @param deptDtos / - */ - void verification(Set deptDtos); -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/DictDetailService.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/DictDetailService.java deleted file mode 100644 index 3912a47..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/DictDetailService.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service; - -import me.zhengjie.modules.system.domain.DictDetail; -import me.zhengjie.modules.system.service.dto.DictDetailDto; -import me.zhengjie.modules.system.service.dto.DictDetailQueryCriteria; -import org.springframework.data.domain.Pageable; -import java.util.List; -import java.util.Map; - -/** -* @author Zheng Jie -* @date 2019-04-10 -*/ -public interface DictDetailService { - - /** - * 创建 - * @param resources / - */ - void create(DictDetail resources); - - /** - * 编辑 - * @param resources / - */ - void update(DictDetail resources); - - /** - * 删除 - * @param id / - */ - void delete(Long id); - - /** - * 分页查询 - * @param criteria 条件 - * @param pageable 分页参数 - * @return / - */ - Map queryAll(DictDetailQueryCriteria criteria, Pageable pageable); - - /** - * 根据字典名称获取字典详情 - * @param name 字典名称 - * @return / - */ - List getDictByName(String name); -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/DictService.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/DictService.java deleted file mode 100644 index 9a89e4c..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/DictService.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service; - -import me.zhengjie.modules.system.domain.Dict; -import me.zhengjie.modules.system.service.dto.DictDto; -import me.zhengjie.modules.system.service.dto.DictQueryCriteria; -import org.springframework.data.domain.Pageable; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** -* @author Zheng Jie -* @date 2019-04-10 -*/ -public interface DictService { - - /** - * 分页查询 - * @param criteria 条件 - * @param pageable 分页参数 - * @return / - */ - Map queryAll(DictQueryCriteria criteria, Pageable pageable); - - /** - * 查询全部数据 - * @param dict / - * @return / - */ - List queryAll(DictQueryCriteria dict); - - /** - * 创建 - * @param resources / - * @return / - */ - void create(Dict resources); - - /** - * 编辑 - * @param resources / - */ - void update(Dict resources); - - /** - * 删除 - * @param ids / - */ - void delete(Set ids); - - /** - * 导出数据 - * @param queryAll 待导出的数据 - * @param response / - * @throws IOException / - */ - void download(List queryAll, HttpServletResponse response) throws IOException; -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/JobService.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/JobService.java deleted file mode 100644 index 21c1c98..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/JobService.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service; - -import me.zhengjie.modules.system.domain.Job; -import me.zhengjie.modules.system.service.dto.JobDto; -import me.zhengjie.modules.system.service.dto.JobQueryCriteria; -import org.springframework.data.domain.Pageable; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** -* @author Zheng Jie -* @date 2019-03-29 -*/ -public interface JobService { - - /** - * 根据ID查询 - * @param id / - * @return / - */ - JobDto findById(Long id); - - /** - * 创建 - * @param resources / - * @return / - */ - void create(Job resources); - - /** - * 编辑 - * @param resources / - */ - void update(Job resources); - - /** - * 删除 - * @param ids / - */ - void delete(Set ids); - - /** - * 删除 - */ - void delete(); - - /** - * 分页查询 - * @param criteria 条件 - * @param pageable 分页参数 - * @return / - */ - Map queryAll(JobQueryCriteria criteria, Pageable pageable); - - /** - * 查询全部数据 - * @param criteria / - * @return / - */ - List queryAll(JobQueryCriteria criteria); - - /** - * 导出数据 - * @param queryAll 待导出的数据 - * @param response / - * @throws IOException / - */ - void download(List queryAll, HttpServletResponse response) throws IOException; - - /** - * 验证是否被用户关联 - * @param ids / - */ - void verification(Set ids); -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/MenuService.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/MenuService.java deleted file mode 100644 index f7b8ece..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/MenuService.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service; - -import me.zhengjie.modules.system.domain.Menu; -import me.zhengjie.modules.system.service.dto.MenuDto; -import me.zhengjie.modules.system.service.dto.MenuQueryCriteria; - -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.List; -import java.util.Set; - -/** - * @author Zheng Jie - * @date 2018-12-17 - */ -public interface MenuService { - - /** - * 查询全部数据 - * @param criteria 条件 - * @param isQuery / - * @throws Exception / - * @return / - */ - List queryAll(MenuQueryCriteria criteria, Boolean isQuery) throws Exception; - - /** - * 根据ID查询 - * @param id / - * @return / - */ - MenuDto findById(long id); - - /** - * 创建 - * @param resources / - */ - void create(Menu resources); - - /** - * 编辑 - * @param resources / - */ - void update(Menu resources); - - /** - * 获取所有子节点,包含自身ID - * @param menuList / - * @param menuSet / - * @return / - */ - Set getChildMenus(List menuList, Set menuSet); - - /** - * 构建菜单树 - * @param menuDtos 原始数据 - * @return / - */ - List buildTree(List menuDtos); - - /** - * 构建菜单树 - * @param menuDtos / - * @return / - */ - Object buildMenus(List menuDtos); - - /** - * 根据ID查询 - * @param id / - * @return / - */ - Menu findOne(Long id); - - /** - * 删除 - * @param menuSet / - */ - void delete(Set menuSet); - - /** - * 导出 - * @param queryAll 待导出的数据 - * @param response / - * @throws IOException / - */ - void download(List queryAll, HttpServletResponse response) throws IOException; - - /** - * 懒加载菜单数据 - * @param pid / - * @return / - */ - List getMenus(Long pid); - - /** - * 根据ID获取同级与上级数据 - * @param menuDto / - * @param objects / - * @return / - */ - List getSuperior(MenuDto menuDto, List objects); - - /** - * 根据当前用户获取菜单 - * @param currentUserId / - * @return / - */ - List findByUser(Long currentUserId); -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/MonitorService.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/MonitorService.java deleted file mode 100644 index 478225a..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/MonitorService.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service; - -import java.util.Map; - -/** - * @author Zheng Jie - * @date 2020-05-02 - */ -public interface MonitorService { - - /** - * 查询数据分页 - * @return Map - */ - Map getServers(); -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/RoleService.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/RoleService.java deleted file mode 100644 index 65e4f58..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/RoleService.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service; - -import me.zhengjie.modules.system.domain.Role; -import me.zhengjie.modules.system.service.dto.RoleDto; -import me.zhengjie.modules.system.service.dto.RoleQueryCriteria; -import me.zhengjie.modules.system.service.dto.RoleSmallDto; -import me.zhengjie.modules.system.service.dto.UserDto; -import org.springframework.data.domain.Pageable; -import org.springframework.security.core.GrantedAuthority; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.List; -import java.util.Set; - -/** - * @author Zheng Jie - * @date 2018-12-03 - */ -public interface RoleService { - - /** - * 查询全部数据 - * @return / - */ - List queryAll(); - - /** - * 根据ID查询 - * @param id / - * @return / - */ - RoleDto findById(long id); - - /** - * 创建 - * @param resources / - */ - void create(Role resources); - - /** - * 编辑 - * @param resources / - */ - void update(Role resources); - - /** - * 删除 - * @param ids / - */ - void delete(Set ids); - - /** - * 根据用户ID查询 - * @param id 用户ID - * @return / - */ - List findByUsersId(Long id); - - /** - * 根据角色查询角色级别 - * @param roles / - * @return / - */ - Integer findByRoles(Set roles); - - /** - * 修改绑定的菜单 - * @param resources / - * @param roleDTO / - */ - void updateMenu(Role resources, RoleDto roleDTO); - - /** - * 解绑菜单 - * @param id / - */ - void untiedMenu(Long id); - - /** - * 待条件分页查询 - * @param criteria 条件 - * @param pageable 分页参数 - * @return / - */ - Object queryAll(RoleQueryCriteria criteria, Pageable pageable); - - /** - * 查询全部 - * @param criteria 条件 - * @return / - */ - List queryAll(RoleQueryCriteria criteria); - - /** - * 导出数据 - * @param queryAll 待导出的数据 - * @param response / - * @throws IOException / - */ - void download(List queryAll, HttpServletResponse response) throws IOException; - - /** - * 获取用户权限信息 - * @param user 用户信息 - * @return 权限信息 - */ - List mapToGrantedAuthorities(UserDto user); - - /** - * 验证是否被用户关联 - * @param ids / - */ - void verification(Set ids); - - /** - * 根据菜单Id查询 - * @param menuIds / - * @return / - */ - List findInMenuId(List menuIds); -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/UserService.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/UserService.java deleted file mode 100644 index 814af92..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/UserService.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service; - -import me.zhengjie.modules.system.domain.User; -import me.zhengjie.modules.system.service.dto.UserDto; -import me.zhengjie.modules.system.service.dto.UserQueryCriteria; -import org.springframework.data.domain.Pageable; -import org.springframework.web.multipart.MultipartFile; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * @author Zheng Jie - * @date 2018-11-23 - */ -public interface UserService { - - /** - * 根据ID查询 - * @param id ID - * @return / - */ - UserDto findById(long id); - - /** - * 新增用户 - * @param resources / - */ - void create(User resources); - - /** - * 编辑用户 - * @param resources / - */ - void update(User resources) throws Exception; - - /** - * 删除用户 - * @param ids / - */ - void delete(Set ids); - - /** - * 根据用户名查询 - * @param userName / - * @return / - */ - UserDto findByName(String userName); - - /** - * 修改密码 - * @param username 用户名 - * @param encryptPassword 密码 - */ - void updatePass(String username, String encryptPassword); - - /** - * 修改头像 - * @param file 文件 - * @return / - */ - Map updateAvatar(MultipartFile file); - - /** - * 修改邮箱 - * @param username 用户名 - * @param email 邮箱 - */ - void updateEmail(String username, String email); - - /** - * 查询全部 - * @param criteria 条件 - * @param pageable 分页参数 - * @return / - */ - Object queryAll(UserQueryCriteria criteria, Pageable pageable); - - /** - * 查询全部不分页 - * @param criteria 条件 - * @return / - */ - List queryAll(UserQueryCriteria criteria); - - /** - * 导出数据 - * @param queryAll 待导出的数据 - * @param response / - * @throws IOException / - */ - void download(List queryAll, HttpServletResponse response) throws IOException; - - /** - * 用户自助修改资料 - * @param resources / - */ - void updateCenter(User resources); -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/VerifyService.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/VerifyService.java deleted file mode 100644 index 4ca39b9..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/VerifyService.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service; - -import me.zhengjie.domain.vo.EmailVo; - -/** - * @author Zheng Jie - * @date 2018-12-26 - */ -public interface VerifyService { - - /** - * 发送验证码 - * @param email / - * @param key / - * @return / - */ - EmailVo sendEmail(String email, String key); - - - /** - * 验证 - * @param code / - * @param key / - */ - void validated(String key, String code); -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DeptDto.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DeptDto.java deleted file mode 100644 index 4c3b12a..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DeptDto.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.dto; - -import com.fasterxml.jackson.annotation.JsonInclude; -import lombok.Getter; -import lombok.Setter; -import me.zhengjie.base.BaseDTO; -import java.io.Serializable; -import java.util.List; -import java.util.Objects; - -/** -* @author Zheng Jie -* @date 2019-03-25 -*/ -@Getter -@Setter -public class DeptDto extends BaseDTO implements Serializable { - - private Long id; - - private String name; - - private Boolean enabled; - - private Integer deptSort; - - @JsonInclude(JsonInclude.Include.NON_EMPTY) - private List children; - - private Long pid; - - private Integer subCount; - - public Boolean getHasChildren() { - return subCount > 0; - } - - public Boolean getLeaf() { - return subCount <= 0; - } - - public String getLabel() { - return name; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - DeptDto deptDto = (DeptDto) o; - return Objects.equals(id, deptDto.id) && - Objects.equals(name, deptDto.name); - } - - @Override - public int hashCode() { - return Objects.hash(id, name); - } -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DeptQueryCriteria.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DeptQueryCriteria.java deleted file mode 100644 index 4d8cdf2..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DeptQueryCriteria.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.dto; - -import lombok.Data; -import me.zhengjie.annotation.DataPermission; -import me.zhengjie.annotation.Query; -import java.sql.Timestamp; -import java.util.List; - -/** -* @author Zheng Jie -* @date 2019-03-25 -*/ -@Data -@DataPermission(fieldName = "id") -public class DeptQueryCriteria{ - - @Query(type = Query.Type.INNER_LIKE) - private String name; - - @Query - private Boolean enabled; - - @Query - private Long pid; - - @Query(type = Query.Type.IS_NULL, propName = "pid") - private Boolean pidIsNull; - - @Query(type = Query.Type.BETWEEN) - private List createTime; -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DeptSmallDto.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DeptSmallDto.java deleted file mode 100644 index 4dc64e5..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DeptSmallDto.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.dto; - -import lombok.Data; -import java.io.Serializable; - -/** -* @author Zheng Jie -* @date 2019-6-10 16:32:18 -*/ -@Data -public class DeptSmallDto implements Serializable { - - private Long id; - - private String name; -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DictDetailDto.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DictDetailDto.java deleted file mode 100644 index a4b931b..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DictDetailDto.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.dto; - -import lombok.Getter; -import lombok.Setter; -import me.zhengjie.base.BaseDTO; -import java.io.Serializable; - -/** -* @author Zheng Jie -* @date 2019-04-10 -*/ -@Getter -@Setter -public class DictDetailDto extends BaseDTO implements Serializable { - - private Long id; - - private DictSmallDto dict; - - private String label; - - private String value; - - private Integer dictSort; -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DictDetailQueryCriteria.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DictDetailQueryCriteria.java deleted file mode 100644 index 91a01b1..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DictDetailQueryCriteria.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.dto; - -import lombok.Data; -import me.zhengjie.annotation.Query; - -/** -* @author Zheng Jie -* @date 2019-04-10 -*/ -@Data -public class DictDetailQueryCriteria { - - @Query(type = Query.Type.INNER_LIKE) - private String label; - - @Query(propName = "name",joinName = "dict") - private String dictName; -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DictDto.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DictDto.java deleted file mode 100644 index 048b4a1..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DictDto.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.dto; - -import lombok.Getter; -import lombok.Setter; -import me.zhengjie.base.BaseDTO; -import java.io.Serializable; -import java.util.List; - -/** -* @author Zheng Jie -* @date 2019-04-10 -*/ -@Getter -@Setter -public class DictDto extends BaseDTO implements Serializable { - - private Long id; - - private List dictDetails; - - private String name; - - private String description; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DictQueryCriteria.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DictQueryCriteria.java deleted file mode 100644 index 7207c61..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DictQueryCriteria.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.dto; - -import lombok.Data; -import me.zhengjie.annotation.Query; - -/** - * @author Zheng Jie - * 公共查询类 - */ -@Data -public class DictQueryCriteria { - - @Query(blurry = "name,description") - private String blurry; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DictSmallDto.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DictSmallDto.java deleted file mode 100644 index 98fc6ee..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/DictSmallDto.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.dto; - -import lombok.Getter; -import lombok.Setter; -import java.io.Serializable; - -/** -* @author Zheng Jie -* @date 2019-04-10 -*/ -@Getter -@Setter -public class DictSmallDto implements Serializable { - - private Long id; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/GoogleAuthCodeDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/GoogleAuthCodeDTO.java deleted file mode 100644 index da99a81..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/GoogleAuthCodeDTO.java +++ /dev/null @@ -1,27 +0,0 @@ -package me.zhengjie.modules.system.service.dto; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotBlank; - -/** - * 验证身份验证码是否正确 DTO - * - * @author rch - * @since 2020-08-25 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class GoogleAuthCodeDTO { - - /** 输入的身份验证码 */ - @NotBlank(message = "身份验证码不能为空") - private String codes; - - /** 密钥 */ - @NotBlank(message = "密钥不能为空") - private String savedSecret; -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/GoogleAuthGenSecretDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/GoogleAuthGenSecretDTO.java deleted file mode 100644 index dd506f4..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/GoogleAuthGenSecretDTO.java +++ /dev/null @@ -1,23 +0,0 @@ -package me.zhengjie.modules.system.service.dto; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotBlank; - -/** - * 获取密钥 DTO - * - * @author rch - * @since 2020-08-25 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class GoogleAuthGenSecretDTO { - - /** 用户 */ - @NotBlank(message = "用户名不能为空") - private String userName; -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/GoogleAuthQrBarCodeUrlDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/GoogleAuthQrBarCodeUrlDTO.java deleted file mode 100644 index 049f341..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/GoogleAuthQrBarCodeUrlDTO.java +++ /dev/null @@ -1,23 +0,0 @@ -package me.zhengjie.modules.system.service.dto; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotBlank; - -/** - * 获取密钥 DTO - * - * @author rch - * @since 2020-08-25 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class GoogleAuthQrBarCodeUrlDTO { - - /** 用户 */ - @NotBlank(message = "用户名不能为空") - private String userName; -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/JobDto.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/JobDto.java deleted file mode 100644 index 8836d55..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/JobDto.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.dto; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import me.zhengjie.base.BaseDTO; - -import java.io.Serializable; - -/** -* @author Zheng Jie -* @date 2019-03-29 -*/ -@Getter -@Setter -@NoArgsConstructor -public class JobDto extends BaseDTO implements Serializable { - - private Long id; - - private Integer jobSort; - - private String name; - - private Boolean enabled; - - public JobDto(String name, Boolean enabled) { - this.name = name; - this.enabled = enabled; - } -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/JobQueryCriteria.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/JobQueryCriteria.java deleted file mode 100644 index ee851dc..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/JobQueryCriteria.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.dto; - -import lombok.Data; -import lombok.NoArgsConstructor; -import me.zhengjie.annotation.Query; -import java.sql.Timestamp; -import java.util.List; - -/** -* @author Zheng Jie -* @date 2019-6-4 14:49:34 -*/ -@Data -@NoArgsConstructor -public class JobQueryCriteria { - - @Query(type = Query.Type.INNER_LIKE) - private String name; - - @Query - private Boolean enabled; - - @Query(type = Query.Type.BETWEEN) - private List createTime; -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/JobSmallDto.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/JobSmallDto.java deleted file mode 100644 index 09cfa62..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/JobSmallDto.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.dto; - -import lombok.Data; -import lombok.NoArgsConstructor; -import java.io.Serializable; - -/** -* @author Zheng Jie -* @date 2019-6-10 16:32:18 -*/ -@Data -@NoArgsConstructor -public class JobSmallDto implements Serializable { - - private Long id; - - private String name; -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/MenuDto.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/MenuDto.java deleted file mode 100644 index d60dd29..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/MenuDto.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.dto; - -import lombok.Getter; -import lombok.Setter; -import me.zhengjie.base.BaseDTO; -import java.io.Serializable; -import java.util.List; -import java.util.Objects; - -/** - * @author Zheng Jie - * @date 2018-12-17 - */ -@Getter -@Setter -public class MenuDto extends BaseDTO implements Serializable { - - private Long id; - - private List children; - - private Integer type; - - private String permission; - - private String title; - - private Integer menuSort; - - private String path; - - private String component; - - private Long pid; - - private Integer subCount; - - private Boolean iFrame; - - private Boolean cache; - - private Boolean hidden; - - private String componentName; - - private String icon; - - public Boolean getHasChildren() { - return subCount > 0; - } - - public Boolean getLeaf() { - return subCount <= 0; - } - - public String getLabel() { - return title; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - MenuDto menuDto = (MenuDto) o; - return Objects.equals(id, menuDto.id); - } - - @Override - public int hashCode() { - return Objects.hash(id); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/MenuQueryCriteria.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/MenuQueryCriteria.java deleted file mode 100644 index bd43e8d..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/MenuQueryCriteria.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.dto; - -import lombok.Data; -import me.zhengjie.annotation.Query; -import java.sql.Timestamp; -import java.util.List; - -/** - * @author Zheng Jie - * 公共查询类 - */ -@Data -public class MenuQueryCriteria { - - @Query(blurry = "title,component,permission") - private String blurry; - - @Query(type = Query.Type.BETWEEN) - private List createTime; - - @Query(type = Query.Type.IS_NULL, propName = "pid") - private Boolean pidIsNull; - - @Query - private Long pid; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/RoleDto.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/RoleDto.java deleted file mode 100644 index fc74d84..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/RoleDto.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.dto; - -import lombok.Getter; -import lombok.Setter; -import me.zhengjie.base.BaseDTO; -import java.io.Serializable; -import java.util.Objects; -import java.util.Set; - -/** - * @author Zheng Jie - * @date 2018-11-23 - */ -@Getter -@Setter -public class RoleDto extends BaseDTO implements Serializable { - - private Long id; - - private Set menus; - - private Set depts; - - private String name; - - private String dataScope; - - private Integer level; - - private String description; - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - RoleDto roleDto = (RoleDto) o; - return Objects.equals(id, roleDto.id); - } - - @Override - public int hashCode() { - return Objects.hash(id); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/RoleQueryCriteria.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/RoleQueryCriteria.java deleted file mode 100644 index 5454fc4..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/RoleQueryCriteria.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.dto; - -import lombok.Data; -import me.zhengjie.annotation.Query; - -import java.sql.Timestamp; -import java.util.List; - -/** - * @author Zheng Jie - * 公共查询类 - */ -@Data -public class RoleQueryCriteria { - - @Query(blurry = "name,description") - private String blurry; - - @Query(type = Query.Type.BETWEEN) - private List createTime; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/RoleSmallDto.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/RoleSmallDto.java deleted file mode 100644 index 99215e6..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/RoleSmallDto.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.dto; - -import lombok.Data; -import java.io.Serializable; - -/** - * @author Zheng Jie - * @date 2018-11-23 - */ -@Data -public class RoleSmallDto implements Serializable { - - private Long id; - - private String name; - - private Integer level; - - private String dataScope; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/UpdateGoogleAuthDTO.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/UpdateGoogleAuthDTO.java deleted file mode 100644 index befe410..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/UpdateGoogleAuthDTO.java +++ /dev/null @@ -1,27 +0,0 @@ -package me.zhengjie.modules.system.service.dto; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.Max; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotNull; - -/** - * 修改Google认证器开关 DTO - * - * @author rch - * @since 2020-08-25 - */ -@Data -@AllArgsConstructor -@NoArgsConstructor -public class UpdateGoogleAuthDTO { - - /** 用户 */ - @NotNull - @Min(value=0) - @Max(value=1) - private Integer isOpen; -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/UserDto.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/UserDto.java deleted file mode 100644 index 923e2d4..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/UserDto.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.dto; - -import com.alibaba.fastjson.annotation.JSONField; -import lombok.Getter; -import lombok.Setter; -import me.zhengjie.base.BaseDTO; -import java.io.Serializable; -import java.util.Date; -import java.util.Set; - -/** - * @author Zheng Jie - * @date 2018-11-23 - */ -@Getter -@Setter -public class UserDto extends BaseDTO implements Serializable { - - private Long id; - - private Set roles; - - private Set jobs; - - private DeptSmallDto dept; - - private Long deptId; - - private String username; - - private String nickName; - - private String email; - - private String phone; - - private String gender; - - private String avatarName; - - private String avatarPath; - - @JSONField(serialize = false) - private String password; - - private Boolean enabled; - - @JSONField(serialize = false) - private Boolean isAdmin = false; - - private Date pwdResetTime; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/UserQueryCriteria.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/UserQueryCriteria.java deleted file mode 100644 index ad8e775..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/dto/UserQueryCriteria.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.dto; - -import lombok.Data; -import me.zhengjie.annotation.Query; -import java.io.Serializable; -import java.sql.Timestamp; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * @author Zheng Jie - * @date 2018-11-23 - */ -@Data -public class UserQueryCriteria implements Serializable { - - @Query - private Long id; - - @Query(propName = "id", type = Query.Type.IN, joinName = "dept") - private Set deptIds = new HashSet<>(); - - @Query(blurry = "email,username,nickName") - private String blurry; - - @Query - private Boolean enabled; - - private Long deptId; - - @Query(type = Query.Type.BETWEEN) - private List createTime; -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/DataServiceImpl.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/DataServiceImpl.java deleted file mode 100644 index 33a8148..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/DataServiceImpl.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.impl; - -import lombok.RequiredArgsConstructor; -import me.zhengjie.modules.system.domain.Dept; -import me.zhengjie.modules.system.service.DataService; -import me.zhengjie.modules.system.service.DeptService; -import me.zhengjie.modules.system.service.RoleService; -import me.zhengjie.modules.system.service.dto.RoleSmallDto; -import me.zhengjie.modules.system.service.dto.UserDto; -import me.zhengjie.utils.enums.DataScopeEnum; -import org.springframework.cache.annotation.CacheConfig; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.stereotype.Service; -import java.util.*; - -/** - * @author Zheng Jie - * @website https://el-admin.vip - * @description 数据权限服务实现 - * @date 2020-05-07 - **/ -@Service -@RequiredArgsConstructor -@CacheConfig(cacheNames = "data") -public class DataServiceImpl implements DataService { - - private final RoleService roleService; - private final DeptService deptService; - - /** - * 用户角色改变时需清理缓存 - * @param user / - * @return / - */ - @Override - @Cacheable(key = "'user:' + #p0.id") - public List getDeptIds(UserDto user) { - // 用于存储部门id - Set deptIds = new HashSet<>(); - // 查询用户角色 - List roleSet = roleService.findByUsersId(user.getId()); - // 获取对应的部门ID - for (RoleSmallDto role : roleSet) { - DataScopeEnum dataScopeEnum = DataScopeEnum.find(role.getDataScope()); - switch (Objects.requireNonNull(dataScopeEnum)) { - case THIS_LEVEL: - deptIds.add(user.getDept().getId()); - break; - case CUSTOMIZE: - deptIds.addAll(getCustomize(deptIds, role)); - break; - default: - return new ArrayList<>(deptIds); - } - } - return new ArrayList<>(deptIds); - } - - /** - * 获取自定义的数据权限 - * @param deptIds 部门ID - * @param role 角色 - * @return 数据权限ID - */ - public Set getCustomize(Set deptIds, RoleSmallDto role){ - Set depts = deptService.findByRoleId(role.getId()); - for (Dept dept : depts) { - deptIds.add(dept.getId()); - List deptChildren = deptService.findByPid(dept.getId()); - if (deptChildren != null && deptChildren.size() != 0) { - deptIds.addAll(deptService.getDeptChildren(deptChildren)); - } - } - return deptIds; - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/DeptServiceImpl.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/DeptServiceImpl.java deleted file mode 100644 index a02bd69..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/DeptServiceImpl.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.impl; - -import cn.hutool.core.collection.CollectionUtil; -import cn.hutool.core.util.ObjectUtil; -import lombok.RequiredArgsConstructor; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.modules.system.domain.Dept; -import me.zhengjie.modules.system.domain.User; -import me.zhengjie.modules.system.repository.RoleRepository; -import me.zhengjie.modules.system.repository.UserRepository; -import me.zhengjie.modules.system.service.dto.DeptDto; -import me.zhengjie.modules.system.service.dto.DeptQueryCriteria; -import me.zhengjie.utils.*; -import me.zhengjie.modules.system.repository.DeptRepository; -import me.zhengjie.modules.system.service.DeptService; -import me.zhengjie.modules.system.service.mapstruct.DeptMapper; -import me.zhengjie.utils.enums.DataScopeEnum; -import org.springframework.cache.annotation.CacheConfig; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.data.domain.Sort; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.*; -import java.util.stream.Collectors; - -/** -* @author Zheng Jie -* @date 2019-03-25 -*/ -@Service -@RequiredArgsConstructor -@CacheConfig(cacheNames = "dept") -public class DeptServiceImpl implements DeptService { - - private final DeptRepository deptRepository; - private final DeptMapper deptMapper; - private final UserRepository userRepository; - private final RedisUtils redisUtils; - private final RoleRepository roleRepository; - - @Override - public List queryAll(DeptQueryCriteria criteria, Boolean isQuery) throws Exception { - Sort sort = Sort.by(Sort.Direction.ASC, "deptSort"); - String dataScopeType = SecurityUtils.getDataScopeType(); - if (isQuery) { - if(dataScopeType.equals(DataScopeEnum.ALL.getValue())){ - criteria.setPidIsNull(true); - } - List fields = QueryHelp.getAllFields(criteria.getClass(), new ArrayList<>()); - List fieldNames = new ArrayList(){{ add("pidIsNull");add("enabled");}}; - for (Field field : fields) { - //设置对象的访问权限,保证对private的属性的访问 - field.setAccessible(true); - Object val = field.get(criteria); - if(fieldNames.contains(field.getName())){ - continue; - } - if (ObjectUtil.isNotNull(val)) { - criteria.setPidIsNull(null); - break; - } - } - } - List list = deptMapper.toDto(deptRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),sort)); - // 如果为空,就代表为自定义权限或者本级权限,就需要去重,不理解可以注释掉,看查询结果 - if(StringUtils.isBlank(dataScopeType)){ - return deduplication(list); - } - return list; - } - - @Override - @Cacheable(key = "'id:' + #p0") - public DeptDto findById(Long id) { - Dept dept = deptRepository.findById(id).orElseGet(Dept::new); - ValidationUtil.isNull(dept.getId(),"Dept","id",id); - return deptMapper.toDto(dept); - } - - @Override - public List findByPid(long pid) { - return deptRepository.findByPid(pid); - } - - @Override - public Set findByRoleId(Long id) { - return deptRepository.findByRoleId(id); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void create(Dept resources) { - deptRepository.save(resources); - // 计算子节点数目 - resources.setSubCount(0); - // 清理缓存 - updateSubCnt(resources.getPid()); - // 清理自定义角色权限的datascope缓存 - delCaches(resources.getPid()); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void update(Dept resources) { - // 旧的部门 - Long oldPid = findById(resources.getId()).getPid(); - Long newPid = resources.getPid(); - if(resources.getPid() != null && resources.getId().equals(resources.getPid())) { - throw new BadRequestException("上级不能为自己"); - } - Dept dept = deptRepository.findById(resources.getId()).orElseGet(Dept::new); - ValidationUtil.isNull( dept.getId(),"Dept","id",resources.getId()); - resources.setId(dept.getId()); - deptRepository.save(resources); - // 更新父节点中子节点数目 - updateSubCnt(oldPid); - updateSubCnt(newPid); - // 清理缓存 - delCaches(resources.getId()); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Set deptDtos) { - for (DeptDto deptDto : deptDtos) { - // 清理缓存 - delCaches(deptDto.getId()); - deptRepository.deleteById(deptDto.getId()); - updateSubCnt(deptDto.getPid()); - } - } - - @Override - public void download(List deptDtos, HttpServletResponse response) throws IOException { - List> list = new ArrayList<>(); - for (DeptDto deptDTO : deptDtos) { - Map map = new LinkedHashMap<>(); - map.put("部门名称", deptDTO.getName()); - map.put("部门状态", deptDTO.getEnabled() ? "启用" : "停用"); - map.put("创建日期", deptDTO.getCreateTime()); - list.add(map); - } - FileUtil.downloadExcel(list, response); - } - - @Override - public Set getDeleteDepts(List menuList, Set deptDtos) { - for (Dept dept : menuList) { - deptDtos.add(deptMapper.toDto(dept)); - List depts = deptRepository.findByPid(dept.getId()); - if(depts!=null && depts.size()!=0){ - getDeleteDepts(depts, deptDtos); - } - } - return deptDtos; - } - - @Override - public List getDeptChildren(List deptList) { - List list = new ArrayList<>(); - deptList.forEach(dept -> { - if (dept!=null && dept.getEnabled()) { - List depts = deptRepository.findByPid(dept.getId()); - if (depts.size() != 0) { - list.addAll(getDeptChildren(depts)); - } - list.add(dept.getId()); - } - } - ); - return list; - } - - @Override - public List getSuperior(DeptDto deptDto, List depts) { - if(deptDto.getPid() == null){ - depts.addAll(deptRepository.findByPidIsNull()); - return deptMapper.toDto(depts); - } - depts.addAll(deptRepository.findByPid(deptDto.getPid())); - return getSuperior(findById(deptDto.getPid()), depts); - } - - @Override - public Object buildTree(List deptDtos) { - Set trees = new LinkedHashSet<>(); - Set depts= new LinkedHashSet<>(); - List deptNames = deptDtos.stream().map(DeptDto::getName).collect(Collectors.toList()); - boolean isChild; - for (DeptDto deptDTO : deptDtos) { - isChild = false; - if (deptDTO.getPid() == null) { - trees.add(deptDTO); - } - for (DeptDto it : deptDtos) { - if (it.getPid() != null && deptDTO.getId().equals(it.getPid())) { - isChild = true; - if (deptDTO.getChildren() == null) { - deptDTO.setChildren(new ArrayList<>()); - } - deptDTO.getChildren().add(it); - } - } - if(isChild) { - depts.add(deptDTO); - } else if(deptDTO.getPid() != null && !deptNames.contains(findById(deptDTO.getPid()).getName())) { - depts.add(deptDTO); - } - } - - if (CollectionUtil.isEmpty(trees)) { - trees = depts; - } - Map map = new HashMap<>(2); - map.put("totalElements",deptDtos.size()); - map.put("content",CollectionUtil.isEmpty(trees)? deptDtos :trees); - return map; - } - - @Override - public void verification(Set deptDtos) { - Set deptIds = deptDtos.stream().map(DeptDto::getId).collect(Collectors.toSet()); - if(userRepository.countByDepts(deptIds) > 0){ - throw new BadRequestException("所选部门存在用户关联,请解除后再试!"); - } - if(roleRepository.countByDepts(deptIds) > 0){ - throw new BadRequestException("所选部门存在角色关联,请解除后再试!"); - } - } - - private void updateSubCnt(Long deptId){ - if(deptId != null){ - int count = deptRepository.countByPid(deptId); - deptRepository.updateSubCntById(count, deptId); - } - } - - private List deduplication(List list) { - List deptDtos = new ArrayList<>(); - for (DeptDto deptDto : list) { - boolean flag = true; - for (DeptDto dto : list) { - if (dto.getId().equals(deptDto.getPid())) { - flag = false; - break; - } - } - if (flag){ - deptDtos.add(deptDto); - } - } - return deptDtos; - } - - /** - * 清理缓存 - * @param id / - */ - public void delCaches(Long id){ - List users = userRepository.findByRoleDeptId(id); - // 删除数据权限 - redisUtils.delByKeys(CacheKey.DATA_USER, users.stream().map(User::getId).collect(Collectors.toSet())); - redisUtils.del(CacheKey.DEPT_ID + id); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/DictDetailServiceImpl.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/DictDetailServiceImpl.java deleted file mode 100644 index 3f5fc74..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/DictDetailServiceImpl.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.impl; - -import lombok.RequiredArgsConstructor; -import me.zhengjie.modules.system.domain.Dict; -import me.zhengjie.modules.system.domain.DictDetail; -import me.zhengjie.modules.system.repository.DictRepository; -import me.zhengjie.modules.system.service.dto.DictDetailQueryCriteria; -import me.zhengjie.utils.*; -import me.zhengjie.modules.system.repository.DictDetailRepository; -import me.zhengjie.modules.system.service.DictDetailService; -import me.zhengjie.modules.system.service.dto.DictDetailDto; -import me.zhengjie.modules.system.service.mapstruct.DictDetailMapper; -import org.springframework.cache.annotation.CacheConfig; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import java.util.List; -import java.util.Map; - -/** -* @author Zheng Jie -* @date 2019-04-10 -*/ -@Service -@RequiredArgsConstructor -@CacheConfig(cacheNames = "dict") -public class DictDetailServiceImpl implements DictDetailService { - - private final DictRepository dictRepository; - private final DictDetailRepository dictDetailRepository; - private final DictDetailMapper dictDetailMapper; - private final RedisUtils redisUtils; - - @Override - public Map queryAll(DictDetailQueryCriteria criteria, Pageable pageable) { - Page page = dictDetailRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable); - return PageUtil.toPage(page.map(dictDetailMapper::toDto)); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void create(DictDetail resources) { - dictDetailRepository.save(resources); - // 清理缓存 - delCaches(resources); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void update(DictDetail resources) { - DictDetail dictDetail = dictDetailRepository.findById(resources.getId()).orElseGet(DictDetail::new); - ValidationUtil.isNull( dictDetail.getId(),"DictDetail","id",resources.getId()); - resources.setId(dictDetail.getId()); - dictDetailRepository.save(resources); - // 清理缓存 - delCaches(resources); - } - - @Override - @Cacheable(key = "'name:' + #p0") - public List getDictByName(String name) { - return dictDetailMapper.toDto(dictDetailRepository.findByDictName(name)); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long id) { - DictDetail dictDetail = dictDetailRepository.findById(id).orElseGet(DictDetail::new); - // 清理缓存 - delCaches(dictDetail); - dictDetailRepository.deleteById(id); - } - - public void delCaches(DictDetail dictDetail){ - Dict dict = dictRepository.findById(dictDetail.getDict().getId()).orElseGet(Dict::new); - redisUtils.del(CacheKey.DICT_NAME + dict.getName()); - } -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/DictServiceImpl.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/DictServiceImpl.java deleted file mode 100644 index 3a2bcd9..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/DictServiceImpl.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.impl; - -import cn.hutool.core.collection.CollectionUtil; -import lombok.RequiredArgsConstructor; -import me.zhengjie.modules.system.domain.Dict; -import me.zhengjie.modules.system.service.dto.DictDetailDto; -import me.zhengjie.modules.system.service.dto.DictQueryCriteria; -import me.zhengjie.utils.*; -import me.zhengjie.modules.system.repository.DictRepository; -import me.zhengjie.modules.system.service.DictService; -import me.zhengjie.modules.system.service.dto.DictDto; -import me.zhengjie.modules.system.service.mapstruct.DictMapper; -import org.springframework.cache.annotation.CacheConfig; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.*; - -/** -* @author Zheng Jie -* @date 2019-04-10 -*/ -@Service -@RequiredArgsConstructor -@CacheConfig(cacheNames = "dict") -public class DictServiceImpl implements DictService { - - private final DictRepository dictRepository; - private final DictMapper dictMapper; - private final RedisUtils redisUtils; - - @Override - public Map queryAll(DictQueryCriteria dict, Pageable pageable){ - Page page = dictRepository.findAll((root, query, cb) -> QueryHelp.getPredicate(root, dict, cb), pageable); - return PageUtil.toPage(page.map(dictMapper::toDto)); - } - - @Override - public List queryAll(DictQueryCriteria dict) { - List list = dictRepository.findAll((root, query, cb) -> QueryHelp.getPredicate(root, dict, cb)); - return dictMapper.toDto(list); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void create(Dict resources) { - dictRepository.save(resources); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void update(Dict resources) { - // 清理缓存 - delCaches(resources); - Dict dict = dictRepository.findById(resources.getId()).orElseGet(Dict::new); - ValidationUtil.isNull( dict.getId(),"Dict","id",resources.getId()); - dict.setName(resources.getName()); - dict.setDescription(resources.getDescription()); - dictRepository.save(dict); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Set ids) { - // 清理缓存 - List dicts = dictRepository.findByIdIn(ids); - for (Dict dict : dicts) { - delCaches(dict); - } - dictRepository.deleteByIdIn(ids); - } - - @Override - public void download(List dictDtos, HttpServletResponse response) throws IOException { - List> list = new ArrayList<>(); - for (DictDto dictDTO : dictDtos) { - if(CollectionUtil.isNotEmpty(dictDTO.getDictDetails())){ - for (DictDetailDto dictDetail : dictDTO.getDictDetails()) { - Map map = new LinkedHashMap<>(); - map.put("字典名称", dictDTO.getName()); - map.put("字典描述", dictDTO.getDescription()); - map.put("字典标签", dictDetail.getLabel()); - map.put("字典值", dictDetail.getValue()); - map.put("创建日期", dictDetail.getCreateTime()); - list.add(map); - } - } else { - Map map = new LinkedHashMap<>(); - map.put("字典名称", dictDTO.getName()); - map.put("字典描述", dictDTO.getDescription()); - map.put("字典标签", null); - map.put("字典值", null); - map.put("创建日期", dictDTO.getCreateTime()); - list.add(map); - } - } - FileUtil.downloadExcel(list, response); - } - - public void delCaches(Dict dict){ - redisUtils.del(CacheKey.DICT_NAME + dict.getName()); - } -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/JobServiceImpl.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/JobServiceImpl.java deleted file mode 100644 index 5c76dfc..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/JobServiceImpl.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.impl; - -import lombok.RequiredArgsConstructor; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.exception.EntityExistException; -import me.zhengjie.modules.system.domain.Job; -import me.zhengjie.modules.system.repository.UserRepository; -import me.zhengjie.modules.system.service.dto.JobQueryCriteria; -import me.zhengjie.utils.*; -import me.zhengjie.modules.system.repository.JobRepository; -import me.zhengjie.modules.system.service.JobService; -import me.zhengjie.modules.system.service.dto.JobDto; -import me.zhengjie.modules.system.service.mapstruct.JobMapper; -import org.springframework.cache.annotation.CacheConfig; -import org.springframework.cache.annotation.CacheEvict; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.*; - -/** -* @author Zheng Jie -* @date 2019-03-29 -*/ -@Service -@RequiredArgsConstructor -@CacheConfig(cacheNames = "job") -public class JobServiceImpl implements JobService { - - private final JobRepository jobRepository; - private final JobMapper jobMapper; - private final RedisUtils redisUtils; - private final UserRepository userRepository; - - @Override - public Map queryAll(JobQueryCriteria criteria, Pageable pageable) { - Page page = jobRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable); - return PageUtil.toPage(page.map(jobMapper::toDto).getContent(),page.getTotalElements()); - } - - @Override - public List queryAll(JobQueryCriteria criteria) { - List list = jobRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)); - return jobMapper.toDto(list); - } - - @Override - @Cacheable(key = "'id:' + #p0") - public JobDto findById(Long id) { - Job job = jobRepository.findById(id).orElseGet(Job::new); - ValidationUtil.isNull(job.getId(),"Job","id",id); - return jobMapper.toDto(job); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void create(Job resources) { - Job job = jobRepository.findByName(resources.getName()); - if(job != null){ - throw new EntityExistException(Job.class,"name",resources.getName()); - } - jobRepository.save(resources); - } - - @Override - @CacheEvict(key = "'id:' + #p0.id") - @Transactional(rollbackFor = Exception.class) - public void update(Job resources) { - Job job = jobRepository.findById(resources.getId()).orElseGet(Job::new); - Job old = jobRepository.findByName(resources.getName()); - if(old != null && !old.getId().equals(resources.getId())){ - throw new EntityExistException(Job.class,"name",resources.getName()); - } - ValidationUtil.isNull( job.getId(),"Job","id",resources.getId()); - resources.setId(job.getId()); - jobRepository.save(resources); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Set ids) { - jobRepository.deleteAllByIdIn(ids); - jobRepository.deleteAll(); - // 删除缓存 - redisUtils.delByKeys(CacheKey.JOB_ID, ids); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete() { - jobRepository.deleteAll(); - } - - @Override - public void download(List jobDtos, HttpServletResponse response) throws IOException { - List> list = new ArrayList<>(); - for (JobDto jobDTO : jobDtos) { - Map map = new LinkedHashMap<>(); - map.put("岗位名称", jobDTO.getName()); - map.put("岗位状态", jobDTO.getEnabled() ? "启用" : "停用"); - map.put("创建日期", jobDTO.getCreateTime()); - list.add(map); - } - FileUtil.downloadExcel(list, response); - } - - @Override - public void verification(Set ids) { - if(userRepository.countByJobs(ids) > 0){ - throw new BadRequestException("所选的岗位中存在用户关联,请解除关联再试!"); - } - } -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/MenuServiceImpl.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/MenuServiceImpl.java deleted file mode 100644 index 0e54fc9..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/MenuServiceImpl.java +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.impl; - -import cn.hutool.core.collection.CollectionUtil; -import cn.hutool.core.util.ObjectUtil; -import lombok.RequiredArgsConstructor; -import me.zhengjie.modules.system.domain.Menu; -import me.zhengjie.modules.system.domain.Role; -import me.zhengjie.modules.system.domain.User; -import me.zhengjie.modules.system.domain.vo.MenuMetaVo; -import me.zhengjie.modules.system.domain.vo.MenuVo; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.exception.EntityExistException; -import me.zhengjie.modules.system.repository.MenuRepository; -import me.zhengjie.modules.system.repository.UserRepository; -import me.zhengjie.modules.system.service.MenuService; -import me.zhengjie.modules.system.service.RoleService; -import me.zhengjie.modules.system.service.dto.MenuDto; -import me.zhengjie.modules.system.service.dto.MenuQueryCriteria; -import me.zhengjie.modules.system.service.dto.RoleSmallDto; -import me.zhengjie.modules.system.service.mapstruct.MenuMapper; -import me.zhengjie.utils.*; -import org.springframework.cache.annotation.CacheConfig; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.data.domain.Sort; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.*; -import java.util.stream.Collectors; - -/** - * @author Zheng Jie - */ -@Service -@RequiredArgsConstructor -@CacheConfig(cacheNames = "menu") -public class MenuServiceImpl implements MenuService { - - private final MenuRepository menuRepository; - private final UserRepository userRepository; - private final MenuMapper menuMapper; - private final RoleService roleService; - private final RedisUtils redisUtils; - - @Override - public List queryAll(MenuQueryCriteria criteria, Boolean isQuery) throws Exception { - Sort sort = Sort.by(Sort.Direction.ASC, "menuSort"); - if(isQuery){ - criteria.setPidIsNull(true); - List fields = QueryHelp.getAllFields(criteria.getClass(), new ArrayList<>()); - for (Field field : fields) { - //设置对象的访问权限,保证对private的属性的访问 - field.setAccessible(true); - Object val = field.get(criteria); - if("pidIsNull".equals(field.getName())){ - continue; - } - if (ObjectUtil.isNotNull(val)) { - criteria.setPidIsNull(null); - break; - } - } - } - return menuMapper.toDto(menuRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),sort)); - } - - @Override - @Cacheable(key = "'id:' + #p0") - public MenuDto findById(long id) { - Menu menu = menuRepository.findById(id).orElseGet(Menu::new); - ValidationUtil.isNull(menu.getId(),"Menu","id",id); - return menuMapper.toDto(menu); - } - - /** - * 用户角色改变时需清理缓存 - * @param currentUserId / - * @return / - */ - @Override - @Cacheable(key = "'user:' + #p0") - public List findByUser(Long currentUserId) { - List roles = roleService.findByUsersId(currentUserId); - Set roleIds = roles.stream().map(RoleSmallDto::getId).collect(Collectors.toSet()); - LinkedHashSet menus = menuRepository.findByRoleIdsAndTypeNot(roleIds, 2); - return menus.stream().map(menuMapper::toDto).collect(Collectors.toList()); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void create(Menu resources) { - if(menuRepository.findByTitle(resources.getTitle()) != null){ - throw new EntityExistException(Menu.class,"title",resources.getTitle()); - } - if(StringUtils.isNotBlank(resources.getComponentName())){ - if(menuRepository.findByComponentName(resources.getComponentName()) != null){ - throw new EntityExistException(Menu.class,"componentName",resources.getComponentName()); - } - } - if(resources.getPid().equals(0L)){ - resources.setPid(null); - } - if(resources.getIFrame()){ - String http = "http://", https = "https://"; - if (!(resources.getPath().toLowerCase().startsWith(http)||resources.getPath().toLowerCase().startsWith(https))) { - throw new BadRequestException("外链必须以http://或者https://开头"); - } - } - menuRepository.save(resources); - // 计算子节点数目 - resources.setSubCount(0); - // 更新父节点菜单数目 - updateSubCnt(resources.getPid()); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void update(Menu resources) { - if(resources.getId().equals(resources.getPid())) { - throw new BadRequestException("上级不能为自己"); - } - Menu menu = menuRepository.findById(resources.getId()).orElseGet(Menu::new); - ValidationUtil.isNull(menu.getId(),"Permission","id",resources.getId()); - - if(resources.getIFrame()){ - String http = "http://", https = "https://"; - if (!(resources.getPath().toLowerCase().startsWith(http)||resources.getPath().toLowerCase().startsWith(https))) { - throw new BadRequestException("外链必须以http://或者https://开头"); - } - } - Menu menu1 = menuRepository.findByTitle(resources.getTitle()); - - if(menu1 != null && !menu1.getId().equals(menu.getId())){ - throw new EntityExistException(Menu.class,"title",resources.getTitle()); - } - - if(resources.getPid().equals(0L)){ - resources.setPid(null); - } - - // 记录的父节点ID - Long oldPid = menu.getPid(); - Long newPid = resources.getPid(); - - if(StringUtils.isNotBlank(resources.getComponentName())){ - menu1 = menuRepository.findByComponentName(resources.getComponentName()); - if(menu1 != null && !menu1.getId().equals(menu.getId())){ - throw new EntityExistException(Menu.class,"componentName",resources.getComponentName()); - } - } - menu.setTitle(resources.getTitle()); - menu.setComponent(resources.getComponent()); - menu.setPath(resources.getPath()); - menu.setIcon(resources.getIcon()); - menu.setIFrame(resources.getIFrame()); - menu.setPid(resources.getPid()); - menu.setMenuSort(resources.getMenuSort()); - menu.setCache(resources.getCache()); - menu.setHidden(resources.getHidden()); - menu.setComponentName(resources.getComponentName()); - menu.setPermission(resources.getPermission()); - menu.setType(resources.getType()); - menuRepository.save(menu); - // 计算父级菜单节点数目 - updateSubCnt(oldPid); - updateSubCnt(newPid); - // 清理缓存 - delCaches(resources.getId()); - } - - @Override - public Set getChildMenus(List menuList, Set menuSet) { - for (Menu menu : menuList) { - menuSet.add(menu); - List menus = menuRepository.findByPid(menu.getId()); - if(menus!=null && menus.size()!=0){ - getChildMenus(menus, menuSet); - } - } - return menuSet; - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Set menuSet) { - for (Menu menu : menuSet) { - // 清理缓存 - delCaches(menu.getId()); - roleService.untiedMenu(menu.getId()); - menuRepository.deleteById(menu.getId()); - updateSubCnt(menu.getPid()); - } - } - - @Override - public List getMenus(Long pid) { - List menus; - if(pid != null && !pid.equals(0L)){ - menus = menuRepository.findByPid(pid); - } else { - menus = menuRepository.findByPidIsNull(); - } - return menuMapper.toDto(menus); - } - - @Override - public List getSuperior(MenuDto menuDto, List menus) { - if(menuDto.getPid() == null){ - menus.addAll(menuRepository.findByPidIsNull()); - return menuMapper.toDto(menus); - } - menus.addAll(menuRepository.findByPid(menuDto.getPid())); - return getSuperior(findById(menuDto.getPid()), menus); - } - - @Override - public List buildTree(List menuDtos) { - List trees = new ArrayList<>(); - Set ids = new HashSet<>(); - for (MenuDto menuDTO : menuDtos) { - if (menuDTO.getPid() == null) { - trees.add(menuDTO); - } - for (MenuDto it : menuDtos) { - if (menuDTO.getId().equals(it.getPid())) { - if (menuDTO.getChildren() == null) { - menuDTO.setChildren(new ArrayList<>()); - } - menuDTO.getChildren().add(it); - ids.add(it.getId()); - } - } - } - if(trees.size() == 0){ - trees = menuDtos.stream().filter(s -> !ids.contains(s.getId())).collect(Collectors.toList()); - } - return trees; - } - - @Override - public List buildMenus(List menuDtos) { - List list = new LinkedList<>(); - menuDtos.forEach(menuDTO -> { - if (menuDTO!=null){ - List menuDtoList = menuDTO.getChildren(); - MenuVo menuVo = new MenuVo(); - menuVo.setName(ObjectUtil.isNotEmpty(menuDTO.getComponentName()) ? menuDTO.getComponentName() : menuDTO.getTitle()); - // 一级目录需要加斜杠,不然会报警告 - menuVo.setPath(menuDTO.getPid() == null ? "/" + menuDTO.getPath() :menuDTO.getPath()); - menuVo.setHidden(menuDTO.getHidden()); - // 如果不是外链 - if(!menuDTO.getIFrame()){ - if(menuDTO.getPid() == null){ - menuVo.setComponent(StringUtils.isEmpty(menuDTO.getComponent())?"Layout":menuDTO.getComponent()); - // 如果不是一级菜单,并且菜单类型为目录,则代表是多级菜单 - }else if(menuDTO.getType() == 0){ - menuVo.setComponent(StringUtils.isEmpty(menuDTO.getComponent())?"ParentView":menuDTO.getComponent()); - }else if(StringUtils.isNoneBlank(menuDTO.getComponent())){ - menuVo.setComponent(menuDTO.getComponent()); - } - } - menuVo.setMeta(new MenuMetaVo(menuDTO.getTitle(),menuDTO.getIcon(),!menuDTO.getCache())); - if(CollectionUtil.isNotEmpty(menuDtoList)){ - menuVo.setAlwaysShow(true); - menuVo.setRedirect("noredirect"); - menuVo.setChildren(buildMenus(menuDtoList)); - // 处理是一级菜单并且没有子菜单的情况 - } else if(menuDTO.getPid() == null){ - MenuVo menuVo1 = new MenuVo(); - menuVo1.setMeta(menuVo.getMeta()); - // 非外链 - if(!menuDTO.getIFrame()){ - menuVo1.setPath("index"); - menuVo1.setName(menuVo.getName()); - menuVo1.setComponent(menuVo.getComponent()); - } else { - menuVo1.setPath(menuDTO.getPath()); - } - menuVo.setName(null); - menuVo.setMeta(null); - menuVo.setComponent("Layout"); - List list1 = new ArrayList<>(); - list1.add(menuVo1); - menuVo.setChildren(list1); - } - list.add(menuVo); - } - } - ); - return list; - } - - @Override - public Menu findOne(Long id) { - Menu menu = menuRepository.findById(id).orElseGet(Menu::new); - ValidationUtil.isNull(menu.getId(),"Menu","id",id); - return menu; - } - - @Override - public void download(List menuDtos, HttpServletResponse response) throws IOException { - List> list = new ArrayList<>(); - for (MenuDto menuDTO : menuDtos) { - Map map = new LinkedHashMap<>(); - map.put("菜单标题", menuDTO.getTitle()); - map.put("菜单类型", menuDTO.getType() == null ? "目录" : menuDTO.getType() == 1 ? "菜单" : "按钮"); - map.put("权限标识", menuDTO.getPermission()); - map.put("外链菜单", menuDTO.getIFrame() ? "是" : "否"); - map.put("菜单可见", menuDTO.getHidden() ? "否" : "是"); - map.put("是否缓存", menuDTO.getCache() ? "是" : "否"); - map.put("创建日期", menuDTO.getCreateTime()); - list.add(map); - } - FileUtil.downloadExcel(list, response); - } - - private void updateSubCnt(Long menuId){ - if(menuId != null){ - int count = menuRepository.countByPid(menuId); - menuRepository.updateSubCntById(count, menuId); - } - } - - /** - * 清理缓存 - * @param id 菜单ID - */ - public void delCaches(Long id){ - List users = userRepository.findByMenuId(id); - redisUtils.del(CacheKey.MENU_ID + id); - redisUtils.delByKeys(CacheKey.MENU_USER, users.stream().map(User::getId).collect(Collectors.toSet())); - // 清除 Role 缓存 - List roles = roleService.findInMenuId(new ArrayList(){{ - add(id); - }}); - redisUtils.delByKeys(CacheKey.ROLE_ID, roles.stream().map(Role::getId).collect(Collectors.toSet())); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/MonitorServiceImpl.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/MonitorServiceImpl.java deleted file mode 100644 index 7ff2e91..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/MonitorServiceImpl.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.impl; - -import cn.hutool.core.date.BetweenFormater; -import cn.hutool.core.date.DateUtil; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.modules.system.service.MonitorService; -import me.zhengjie.utils.ElAdminConstant; -import me.zhengjie.utils.FileUtil; -import me.zhengjie.utils.StringUtils; -import org.springframework.stereotype.Service; -import oshi.SystemInfo; -import oshi.hardware.*; -import oshi.software.os.FileSystem; -import oshi.software.os.OSFileStore; -import oshi.software.os.OperatingSystem; -import oshi.util.FormatUtil; -import oshi.util.Util; -import java.lang.management.ManagementFactory; -import java.text.DecimalFormat; -import java.util.*; - -/** -* @author Zheng Jie -* @date 2020-05-02 -*/ -@Service -public class MonitorServiceImpl implements MonitorService { - - private final DecimalFormat df = new DecimalFormat("0.00"); - - @Override - public Map getServers(){ - Map resultMap = new LinkedHashMap<>(8); - try { - SystemInfo si = new SystemInfo(); - OperatingSystem os = si.getOperatingSystem(); - HardwareAbstractionLayer hal = si.getHardware(); - // 系统信息 - resultMap.put("sys", getSystemInfo(os)); - // cpu 信息 - resultMap.put("cpu", getCpuInfo(hal.getProcessor())); - // 内存信息 - resultMap.put("memory", getMemoryInfo(hal.getMemory())); - // 交换区信息 - resultMap.put("swap", getSwapInfo(hal.getMemory())); - // 磁盘 - resultMap.put("disk", getDiskInfo(os)); - resultMap.put("time", DateUtil.format(new Date(), "HH:mm:ss")); - } catch (Exception e) { - e.printStackTrace(); - } - return resultMap; - } - - /** - * 获取磁盘信息 - * @return / - */ - private Map getDiskInfo(OperatingSystem os) { - Map diskInfo = new LinkedHashMap<>(); - FileSystem fileSystem = os.getFileSystem(); - List fsArray = fileSystem.getFileStores(); - String osName = System.getProperty("os.name"); - long available = 0, total = 0; - for (OSFileStore fs : fsArray){ - // windows 需要将所有磁盘分区累加,linux 和 mac 直接累加会出现磁盘重复的问题,待修复 - if(osName.toLowerCase().startsWith(ElAdminConstant.WIN)) { - available += fs.getUsableSpace(); - total += fs.getTotalSpace(); - } else { - available = fs.getUsableSpace(); - total = fs.getTotalSpace(); - break; - } - } - long used = total - available; - diskInfo.put("total", total > 0 ? FileUtil.getSize(total) : "?"); - diskInfo.put("available", FileUtil.getSize(available)); - diskInfo.put("used", FileUtil.getSize(used)); - if(total != 0){ - diskInfo.put("usageRate", df.format(used/(double)total * 100)); - } else { - diskInfo.put("usageRate", 0); - } - return diskInfo; - } - - /** - * 获取交换区信息 - * @param memory / - * @return / - */ - private Map getSwapInfo(GlobalMemory memory) { - Map swapInfo = new LinkedHashMap<>(); - VirtualMemory virtualMemory = memory.getVirtualMemory(); - long total = virtualMemory.getSwapTotal(); - long used = virtualMemory.getSwapUsed(); - swapInfo.put("total", FormatUtil.formatBytes(total)); - swapInfo.put("used", FormatUtil.formatBytes(used)); - swapInfo.put("available", FormatUtil.formatBytes(total - used)); - if(used == 0){ - swapInfo.put("usageRate", 0); - } else { - swapInfo.put("usageRate", df.format(used/(double)total * 100)); - } - return swapInfo; - } - - /** - * 获取内存信息 - * @param memory / - * @return / - */ - private Map getMemoryInfo(GlobalMemory memory) { - Map memoryInfo = new LinkedHashMap<>(); - memoryInfo.put("total", FormatUtil.formatBytes(memory.getTotal())); - memoryInfo.put("available", FormatUtil.formatBytes(memory.getAvailable())); - memoryInfo.put("used", FormatUtil.formatBytes(memory.getTotal() - memory.getAvailable())); - memoryInfo.put("usageRate", df.format((memory.getTotal() - memory.getAvailable())/(double)memory.getTotal() * 100)); - return memoryInfo; - } - - /** - * 获取Cpu相关信息 - * @param processor / - * @return / - */ - private Map getCpuInfo(CentralProcessor processor) { - Map cpuInfo = new LinkedHashMap<>(); - cpuInfo.put("name", processor.getProcessorIdentifier().getName()); - cpuInfo.put("package", processor.getPhysicalPackageCount() + "个物理CPU"); - cpuInfo.put("core", processor.getPhysicalProcessorCount() + "个物理核心"); - cpuInfo.put("coreNumber", processor.getPhysicalProcessorCount()); - cpuInfo.put("logic", processor.getLogicalProcessorCount() + "个逻辑CPU"); - // CPU信息 - long[] prevTicks = processor.getSystemCpuLoadTicks(); - // 等待1秒... - Util.sleep(1000); - long[] ticks = processor.getSystemCpuLoadTicks(); - long user = ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()]; - long nice = ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()]; - long sys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()]; - long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()]; - long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()]; - long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()]; - long softirq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()]; - long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()]; - long totalCpu = user + nice + sys + idle + iowait + irq + softirq + steal; - cpuInfo.put("used", df.format(100d * user / totalCpu + 100d * sys / totalCpu)); - cpuInfo.put("idle", df.format(100d * idle / totalCpu)); - return cpuInfo; - } - - /** - * 获取系统相关信息,系统、运行天数、系统IP - * @param os / - * @return / - */ - private Map getSystemInfo(OperatingSystem os){ - Map systemInfo = new LinkedHashMap<>(); - // jvm 运行时间 - long time = ManagementFactory.getRuntimeMXBean().getStartTime(); - Date date = new Date(time); - // 计算项目运行时间 - String formatBetween = DateUtil.formatBetween(date, new Date(),BetweenFormater.Level.HOUR); - // 系统信息 - systemInfo.put("os", os.toString()); - systemInfo.put("day", formatBetween); - systemInfo.put("ip", StringUtils.getLocalIp()); - return systemInfo; - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/RoleServiceImpl.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/RoleServiceImpl.java deleted file mode 100644 index e8b4143..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/RoleServiceImpl.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.impl; - -import cn.hutool.core.collection.CollectionUtil; -import lombok.RequiredArgsConstructor; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.modules.security.service.UserCacheClean; -import me.zhengjie.modules.system.domain.Menu; -import me.zhengjie.modules.system.domain.Role; -import me.zhengjie.exception.EntityExistException; -import me.zhengjie.modules.system.domain.User; -import me.zhengjie.modules.system.repository.RoleRepository; -import me.zhengjie.modules.system.repository.UserRepository; -import me.zhengjie.modules.system.service.RoleService; -import me.zhengjie.modules.system.service.dto.RoleDto; -import me.zhengjie.modules.system.service.dto.RoleQueryCriteria; -import me.zhengjie.modules.system.service.dto.RoleSmallDto; -import me.zhengjie.modules.system.service.dto.UserDto; -import me.zhengjie.modules.system.service.mapstruct.RoleMapper; -import me.zhengjie.modules.system.service.mapstruct.RoleSmallMapper; -import me.zhengjie.utils.*; -import org.springframework.cache.annotation.CacheConfig; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.*; -import java.util.stream.Collectors; - -/** - * @author Zheng Jie - * @date 2018-12-03 - */ -@Service -@RequiredArgsConstructor -@CacheConfig(cacheNames = "role") -public class RoleServiceImpl implements RoleService { - - private final RoleRepository roleRepository; - private final RoleMapper roleMapper; - private final RoleSmallMapper roleSmallMapper; - private final RedisUtils redisUtils; - private final UserRepository userRepository; - private final UserCacheClean userCacheClean; - - @Override - public List queryAll() { - Sort sort = Sort.by(Sort.Direction.ASC, "level"); - return roleMapper.toDto(roleRepository.findAll(sort)); - } - - @Override - public List queryAll(RoleQueryCriteria criteria) { - return roleMapper.toDto(roleRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder))); - } - - @Override - public Object queryAll(RoleQueryCriteria criteria, Pageable pageable) { - Page page = roleRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable); - return PageUtil.toPage(page.map(roleMapper::toDto)); - } - - @Override - @Cacheable(key = "'id:' + #p0") - @Transactional(rollbackFor = Exception.class) - public RoleDto findById(long id) { - Role role = roleRepository.findById(id).orElseGet(Role::new); - ValidationUtil.isNull(role.getId(), "Role", "id", id); - return roleMapper.toDto(role); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void create(Role resources) { - if (roleRepository.findByName(resources.getName()) != null) { - throw new EntityExistException(Role.class, "username", resources.getName()); - } - roleRepository.save(resources); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void update(Role resources) { - Role role = roleRepository.findById(resources.getId()).orElseGet(Role::new); - ValidationUtil.isNull(role.getId(), "Role", "id", resources.getId()); - - Role role1 = roleRepository.findByName(resources.getName()); - - if (role1 != null && !role1.getId().equals(role.getId())) { - throw new EntityExistException(Role.class, "username", resources.getName()); - } - role.setName(resources.getName()); - role.setDescription(resources.getDescription()); - role.setDataScope(resources.getDataScope()); - role.setDepts(resources.getDepts()); - role.setLevel(resources.getLevel()); - roleRepository.save(role); - // 更新相关缓存 - delCaches(role.getId(), null); - } - - @Override - public void updateMenu(Role resources, RoleDto roleDTO) { - Role role = roleMapper.toEntity(roleDTO); - List users = userRepository.findByRoleId(role.getId()); - // 更新菜单 - role.setMenus(resources.getMenus()); - delCaches(resources.getId(), users); - roleRepository.save(role); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void untiedMenu(Long menuId) { - // 更新菜单 - roleRepository.untiedMenu(menuId); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Set ids) { - for (Long id : ids) { - // 更新相关缓存 - delCaches(id, null); - } - roleRepository.deleteAllByIdIn(ids); - } - - @Override - public List findByUsersId(Long id) { - return roleSmallMapper.toDto(new ArrayList<>(roleRepository.findByUserId(id))); - } - - @Override - public Integer findByRoles(Set roles) { - if (roles.size() == 0) { - return Integer.MAX_VALUE; - } - Set roleDtos = new HashSet<>(); - for (Role role : roles) { - roleDtos.add(findById(role.getId())); - } - return Collections.min(roleDtos.stream().map(RoleDto::getLevel).collect(Collectors.toList())); - } - - @Override - @Cacheable(key = "'auth:' + #p0.id") - public List mapToGrantedAuthorities(UserDto user) { - Set permissions = new HashSet<>(); - // 如果是管理员直接返回 - if (user.getIsAdmin()) { - permissions.add("admin"); - return permissions.stream().map(SimpleGrantedAuthority::new) - .collect(Collectors.toList()); - } - Set roles = roleRepository.findByUserId(user.getId()); - permissions = roles.stream().flatMap(role -> role.getMenus().stream()) - .filter(menu -> StringUtils.isNotBlank(menu.getPermission())) - .map(Menu::getPermission).collect(Collectors.toSet()); - return permissions.stream().map(SimpleGrantedAuthority::new) - .collect(Collectors.toList()); - } - - @Override - public void download(List roles, HttpServletResponse response) throws IOException { - List> list = new ArrayList<>(); - for (RoleDto role : roles) { - Map map = new LinkedHashMap<>(); - map.put("角色名称", role.getName()); - map.put("角色级别", role.getLevel()); - map.put("描述", role.getDescription()); - map.put("创建日期", role.getCreateTime()); - list.add(map); - } - FileUtil.downloadExcel(list, response); - } - - @Override - public void verification(Set ids) { - if (userRepository.countByRoles(ids) > 0) { - throw new BadRequestException("所选角色存在用户关联,请解除关联再试!"); - } - } - - @Override - public List findInMenuId(List menuIds) { - return roleRepository.findInMenuId(menuIds); - } - - /** - * 清理缓存 - * @param id / - */ - public void delCaches(Long id, List users) { - users = CollectionUtil.isEmpty(users) ? userRepository.findByRoleId(id) : users; - if (CollectionUtil.isNotEmpty(users)) { - users.forEach(item -> userCacheClean.cleanUserCache(item.getUsername())); - Set userIds = users.stream().map(User::getId).collect(Collectors.toSet()); - redisUtils.delByKeys(CacheKey.DATA_USER, userIds); - redisUtils.delByKeys(CacheKey.MENU_USER, userIds); - redisUtils.delByKeys(CacheKey.ROLE_AUTH, userIds); - } - redisUtils.del(CacheKey.ROLE_ID + id); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/UserServiceImpl.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/UserServiceImpl.java deleted file mode 100644 index 3a56692..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/UserServiceImpl.java +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.impl; - -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.json.JSONUtil; -import lombok.RequiredArgsConstructor; -import me.zhengjie.config.FileProperties; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.modules.security.service.OnlineUserService; -import me.zhengjie.modules.security.service.UserCacheClean; -import me.zhengjie.modules.system.domain.User; -import me.zhengjie.exception.EntityExistException; -import me.zhengjie.exception.EntityNotFoundException; -import me.zhengjie.modules.system.repository.UserRepository; -import me.zhengjie.modules.system.service.UserService; -import me.zhengjie.modules.system.service.dto.JobSmallDto; -import me.zhengjie.modules.system.service.dto.RoleSmallDto; -import me.zhengjie.modules.system.service.dto.UserDto; -import me.zhengjie.modules.system.service.dto.UserQueryCriteria; -import me.zhengjie.modules.system.service.mapstruct.UserMapper; -import me.zhengjie.utils.*; -import org.springframework.cache.annotation.CacheConfig; -import org.springframework.cache.annotation.Cacheable; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.multipart.MultipartFile; -import javax.servlet.http.HttpServletResponse; -import javax.validation.constraints.NotBlank; -import java.io.File; -import java.io.IOException; -import java.util.*; -import java.util.stream.Collectors; - -/** - * @author Zheng Jie - * @date 2018-11-23 - */ -@Service -@RequiredArgsConstructor -@CacheConfig(cacheNames = "user") -public class UserServiceImpl implements UserService { - - private final UserRepository userRepository; - private final UserMapper userMapper; - private final FileProperties properties; - private final RedisUtils redisUtils; - private final UserCacheClean userCacheClean; - private final OnlineUserService onlineUserService; - - @Override - public Object queryAll(UserQueryCriteria criteria, Pageable pageable) { - Page page = userRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable); - // 添加用户账户冻结状态 - Map map = PageUtil.toPage(page.map(userMapper::toDto)); - - List userDtoList = (List) map.get("content"); - if (ObjectUtil.isNotEmpty(userDtoList)) { - List list = new ArrayList(); - for (UserDto userDto : userDtoList) { - String key = String.format(RedisUtils.BLOCKED_ACCOUNT, userDto.getUsername()); - long expire = redisUtils.getExpire(key); - Integer blockedStatus = 0; - String blockedTime = ""; - if (expire > 0) { - blockedStatus = 1; - blockedTime = DateUtil.getHour(expire); - } - Map toMap = JSONUtil.parseObj(userDto); - toMap.put("blockedStatus", blockedStatus); - toMap.put("blockedTime", blockedTime); - list.add(toMap); - } - map.put("content", list); - } - - return map; - } - - @Override - public List queryAll(UserQueryCriteria criteria) { - List users = userRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder)); - return userMapper.toDto(users); - } - - @Override - @Cacheable(key = "'id:' + #p0") - @Transactional(rollbackFor = Exception.class) - public UserDto findById(long id) { - User user = userRepository.findById(id).orElseGet(User::new); - ValidationUtil.isNull(user.getId(), "User", "id", id); - return userMapper.toDto(user); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void create(User resources) { - if (userRepository.findByUsername(resources.getUsername()) != null) { - throw new EntityExistException(User.class, "username", resources.getUsername()); - } - if (userRepository.findByEmail(resources.getEmail()) != null) { - throw new EntityExistException(User.class, "email", resources.getEmail()); - } - if (userRepository.findByPhone(resources.getPhone()) != null) { - throw new EntityExistException(User.class, "phone", resources.getPhone()); - } - userRepository.save(resources); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void update(User resources) throws Exception { - User user = userRepository.findById(resources.getId()).orElseGet(User::new); - ValidationUtil.isNull(user.getId(), "User", "id", resources.getId()); - User user1 = userRepository.findByUsername(resources.getUsername()); - User user2 = userRepository.findByEmail(resources.getEmail()); - User user3 = userRepository.findByPhone(resources.getPhone()); - if (user1 != null && !user.getId().equals(user1.getId())) { - throw new EntityExistException(User.class, "username", resources.getUsername()); - } - if (user2 != null && !user.getId().equals(user2.getId())) { - throw new EntityExistException(User.class, "email", resources.getEmail()); - } - if (user3 != null && !user.getId().equals(user3.getId())) { - throw new EntityExistException(User.class, "phone", resources.getPhone()); - } - // 如果用户的角色改变 - if (!resources.getRoles().equals(user.getRoles())) { - redisUtils.del(CacheKey.DATA_USER + resources.getId()); - redisUtils.del(CacheKey.MENU_USER + resources.getId()); - redisUtils.del(CacheKey.ROLE_AUTH + resources.getId()); - } - // 如果用户被禁用,则清除用户登录信息 - if(!resources.getEnabled()){ - onlineUserService.kickOutForUsername(resources.getUsername()); - } - user.setUsername(resources.getUsername()); - user.setEmail(resources.getEmail()); - user.setEnabled(resources.getEnabled()); - user.setRoles(resources.getRoles()); - user.setDept(resources.getDept()); - user.setJobs(resources.getJobs()); - user.setPhone(resources.getPhone()); - user.setNickName(resources.getNickName()); - user.setGender(resources.getGender()); - userRepository.save(user); - // 清除缓存 - delCaches(user.getId(), user.getUsername()); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void updateCenter(User resources) { - User user = userRepository.findById(resources.getId()).orElseGet(User::new); - User user1 = userRepository.findByPhone(resources.getPhone()); - if (user1 != null && !user.getId().equals(user1.getId())) { - throw new EntityExistException(User.class, "phone", resources.getPhone()); - } - user.setNickName(resources.getNickName()); - user.setPhone(resources.getPhone()); - user.setGender(resources.getGender()); - userRepository.save(user); - // 清理缓存 - delCaches(user.getId(), user.getUsername()); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Set ids) { - for (Long id : ids) { - // 清理缓存 - UserDto user = findById(id); - delCaches(user.getId(), user.getUsername()); - } - userRepository.deleteAllByIdIn(ids); - } - - @Override - public UserDto findByName(String userName) { - User user = userRepository.findByUsername(userName); - if (user == null) { - throw new EntityNotFoundException(User.class, "name", userName); - } else { - return userMapper.toDto(user); - } - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void updatePass(String username, String pass) { - userRepository.updatePass(username, pass, new Date()); - flushCache(username); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public Map updateAvatar(MultipartFile multipartFile) { - // 文件大小验证 - FileUtil.checkSize(properties.getAvatarMaxSize(), multipartFile.getSize()); - // 验证文件上传的格式 - String image = "gif jpg png jpeg"; - String fileType = FileUtil.getExtensionName(multipartFile.getOriginalFilename()); - if(fileType != null && !image.contains(fileType)){ - throw new BadRequestException("文件格式错误!, 仅支持 " + image +" 格式"); - } - User user = userRepository.findByUsername(SecurityUtils.getCurrentUsername()); - String oldPath = user.getAvatarPath(); - File file = FileUtil.upload(multipartFile, properties.getPath().getAvatar()); - user.setAvatarPath(Objects.requireNonNull(file).getPath()); - user.setAvatarName(file.getName()); - userRepository.save(user); - if (StringUtils.isNotBlank(oldPath)) { - FileUtil.del(oldPath); - } - @NotBlank String username = user.getUsername(); - flushCache(username); - return new HashMap(1) {{ - put("avatar", file.getName()); - }}; - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void updateEmail(String username, String email) { - userRepository.updateEmail(username, email); - flushCache(username); - } - - @Override - public void download(List queryAll, HttpServletResponse response) throws IOException { - List> list = new ArrayList<>(); - for (UserDto userDTO : queryAll) { - List roles = userDTO.getRoles().stream().map(RoleSmallDto::getName).collect(Collectors.toList()); - Map map = new LinkedHashMap<>(); - map.put("用户名", userDTO.getUsername()); - map.put("角色", roles); - map.put("部门", userDTO.getDept().getName()); - map.put("岗位", userDTO.getJobs().stream().map(JobSmallDto::getName).collect(Collectors.toList())); - map.put("邮箱", userDTO.getEmail()); - map.put("状态", userDTO.getEnabled() ? "启用" : "禁用"); - map.put("手机号码", userDTO.getPhone()); - map.put("修改密码的时间", userDTO.getPwdResetTime()); - map.put("创建日期", userDTO.getCreateTime()); - list.add(map); - } - FileUtil.downloadExcel(list, response); - } - - /** - * 清理缓存 - * - * @param id / - */ - public void delCaches(Long id, String username) { - redisUtils.del(CacheKey.USER_ID + id); - flushCache(username); - } - - /** - * 清理 登陆时 用户缓存信息 - * - * @param username / - */ - private void flushCache(String username) { - userCacheClean.cleanUserCache(username); - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/VerifyServiceImpl.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/VerifyServiceImpl.java deleted file mode 100644 index ec3230c..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/impl/VerifyServiceImpl.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.impl; - -import cn.hutool.core.lang.Dict; -import cn.hutool.core.util.RandomUtil; -import cn.hutool.extra.template.Template; -import cn.hutool.extra.template.TemplateConfig; -import cn.hutool.extra.template.TemplateEngine; -import cn.hutool.extra.template.TemplateUtil; -import lombok.RequiredArgsConstructor; -import me.zhengjie.domain.vo.EmailVo; -import me.zhengjie.exception.BadRequestException; -import me.zhengjie.modules.system.service.VerifyService; -import me.zhengjie.utils.RedisUtils; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import java.util.Collections; - -/** - * @author Zheng Jie - * @date 2018-12-26 - */ -@Service -@RequiredArgsConstructor -public class VerifyServiceImpl implements VerifyService { - - @Value("${code.expiration}") - private Long expiration; - private final RedisUtils redisUtils; - - @Override - @Transactional(rollbackFor = Exception.class) - public EmailVo sendEmail(String email, String key) { - EmailVo emailVo; - String content; - String redisKey = key + email; - // 如果不存在有效的验证码,就创建一个新的 - TemplateEngine engine = TemplateUtil.createEngine(new TemplateConfig("template", TemplateConfig.ResourceMode.CLASSPATH)); - Template template = engine.getTemplate("email/email.ftl"); - Object oldCode = redisUtils.get(redisKey); - if(oldCode == null){ - String code = RandomUtil.randomNumbers (6); - // 存入缓存 - if(!redisUtils.set(redisKey, code, expiration)){ - throw new BadRequestException("服务异常,请联系网站负责人"); - } - content = template.render(Dict.create().set("code",code)); - emailVo = new EmailVo(Collections.singletonList(email),"EL-ADMIN后台管理系统",content); - // 存在就再次发送原来的验证码 - } else { - content = template.render(Dict.create().set("code",oldCode)); - emailVo = new EmailVo(Collections.singletonList(email),"EL-ADMIN后台管理系统",content); - } - return emailVo; - } - - @Override - public void validated(String key, String code) { - Object value = redisUtils.get(key); - if(value == null || !value.toString().equals(code)){ - throw new BadRequestException("无效验证码"); - } else { - redisUtils.del(key); - } - } -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/DeptMapper.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/DeptMapper.java deleted file mode 100644 index b0fb904..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/DeptMapper.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.mapstruct; - -import me.zhengjie.base.BaseMapper; -import me.zhengjie.modules.system.domain.Dept; -import me.zhengjie.modules.system.service.dto.DeptDto; -import org.mapstruct.Mapper; -import org.mapstruct.ReportingPolicy; - -/** -* @author Zheng Jie -* @date 2019-03-25 -*/ -@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface DeptMapper extends BaseMapper { -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/DeptSmallMapper.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/DeptSmallMapper.java deleted file mode 100644 index 7507600..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/DeptSmallMapper.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.mapstruct; - -import me.zhengjie.base.BaseMapper; -import me.zhengjie.modules.system.domain.Dept; -import me.zhengjie.modules.system.service.dto.DeptSmallDto; -import org.mapstruct.Mapper; -import org.mapstruct.ReportingPolicy; - -/** -* @author Zheng Jie -* @date 2019-03-25 -*/ -@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface DeptSmallMapper extends BaseMapper { - -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/DictDetailMapper.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/DictDetailMapper.java deleted file mode 100644 index 3f9fe84..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/DictDetailMapper.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.mapstruct; - -import me.zhengjie.base.BaseMapper; -import me.zhengjie.modules.system.domain.DictDetail; -import me.zhengjie.modules.system.service.dto.DictDetailDto; -import org.mapstruct.Mapper; -import org.mapstruct.ReportingPolicy; - -/** -* @author Zheng Jie -* @date 2019-04-10 -*/ -@Mapper(componentModel = "spring", uses = {DictSmallMapper.class}, unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface DictDetailMapper extends BaseMapper { - -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/DictMapper.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/DictMapper.java deleted file mode 100644 index 1047b3b..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/DictMapper.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.mapstruct; - -import me.zhengjie.base.BaseMapper; -import me.zhengjie.modules.system.domain.Dict; -import me.zhengjie.modules.system.service.dto.DictDto; -import org.mapstruct.Mapper; -import org.mapstruct.ReportingPolicy; - -/** -* @author Zheng Jie -* @date 2019-04-10 -*/ -@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface DictMapper extends BaseMapper { - -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/DictSmallMapper.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/DictSmallMapper.java deleted file mode 100644 index 80ccc4e..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/DictSmallMapper.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.mapstruct; - -import me.zhengjie.base.BaseMapper; -import me.zhengjie.modules.system.domain.Dict; -import me.zhengjie.modules.system.service.dto.DictSmallDto; -import org.mapstruct.Mapper; -import org.mapstruct.ReportingPolicy; - -/** -* @author Zheng Jie -* @date 2019-04-10 -*/ -@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface DictSmallMapper extends BaseMapper { - -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/JobMapper.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/JobMapper.java deleted file mode 100644 index 3771930..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/JobMapper.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.mapstruct; - -import me.zhengjie.base.BaseMapper; -import me.zhengjie.modules.system.domain.Job; -import me.zhengjie.modules.system.service.dto.JobDto; -import org.mapstruct.Mapper; -import org.mapstruct.ReportingPolicy; - -/** -* @author Zheng Jie -* @date 2019-03-29 -*/ -@Mapper(componentModel = "spring",uses = {DeptMapper.class},unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface JobMapper extends BaseMapper { -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/JobSmallMapper.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/JobSmallMapper.java deleted file mode 100644 index 36a59cf..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/JobSmallMapper.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.mapstruct; - -import me.zhengjie.base.BaseMapper; -import me.zhengjie.modules.system.domain.Job; -import me.zhengjie.modules.system.service.dto.JobSmallDto; -import org.mapstruct.Mapper; -import org.mapstruct.ReportingPolicy; - -/** -* @author Zheng Jie -* @date 2019-03-29 -*/ -@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface JobSmallMapper extends BaseMapper { - -} \ No newline at end of file diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/MenuMapper.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/MenuMapper.java deleted file mode 100644 index 6d8bffa..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/MenuMapper.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.mapstruct; - -import me.zhengjie.base.BaseMapper; -import me.zhengjie.modules.system.domain.Menu; -import me.zhengjie.modules.system.service.dto.MenuDto; -import org.mapstruct.Mapper; -import org.mapstruct.ReportingPolicy; - -/** - * @author Zheng Jie - * @date 2018-12-17 - */ -@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface MenuMapper extends BaseMapper { -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/RoleMapper.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/RoleMapper.java deleted file mode 100644 index 5dc551d..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/RoleMapper.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.mapstruct; - -import me.zhengjie.base.BaseMapper; -import me.zhengjie.modules.system.domain.Role; -import me.zhengjie.modules.system.service.dto.RoleDto; -import org.mapstruct.Mapper; -import org.mapstruct.ReportingPolicy; - -/** - * @author Zheng Jie - * @date 2018-11-23 - */ -@Mapper(componentModel = "spring", uses = {MenuMapper.class, DeptMapper.class}, unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface RoleMapper extends BaseMapper { - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/RoleSmallMapper.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/RoleSmallMapper.java deleted file mode 100644 index db034b5..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/RoleSmallMapper.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.mapstruct; - -import me.zhengjie.base.BaseMapper; -import me.zhengjie.modules.system.domain.Role; -import me.zhengjie.modules.system.service.dto.RoleSmallDto; -import org.mapstruct.Mapper; -import org.mapstruct.ReportingPolicy; - -/** - * @author Zheng Jie - * @date 2019-5-23 - */ -@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface RoleSmallMapper extends BaseMapper { - -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/UserMapper.java b/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/UserMapper.java deleted file mode 100644 index 510c21b..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/system/service/mapstruct/UserMapper.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2019-2020 Zheng Jie - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package me.zhengjie.modules.system.service.mapstruct; - -import me.zhengjie.base.BaseMapper; -import me.zhengjie.modules.system.domain.User; -import me.zhengjie.modules.system.service.dto.UserDto; -import org.mapstruct.Mapper; -import org.mapstruct.ReportingPolicy; - -/** - * @author Zheng Jie - * @date 2018-11-23 - */ -@Mapper(componentModel = "spring",uses = {RoleMapper.class, DeptMapper.class, JobMapper.class},unmappedTargetPolicy = ReportingPolicy.IGNORE) -public interface UserMapper extends BaseMapper { -} diff --git a/wjcy-system/src/main/java/me/zhengjie/modules/utils/GoogleAuthenticatorUtil.java b/wjcy-system/src/main/java/me/zhengjie/modules/utils/GoogleAuthenticatorUtil.java deleted file mode 100644 index 0861ddf..0000000 --- a/wjcy-system/src/main/java/me/zhengjie/modules/utils/GoogleAuthenticatorUtil.java +++ /dev/null @@ -1,179 +0,0 @@ -package me.zhengjie.modules.utils; - -import cn.hutool.core.util.ObjectUtil; -import me.zhengjie.config.GoogleAuthProperties; -import me.zhengjie.utils.RedisUtils; -import org.apache.commons.codec.binary.Base32; -import org.apache.commons.codec.binary.Base64; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; - -/** - *

- * Google Authenticator 工具类 - *

- * - * @author: rch - * @since: 2020-08-25 - */ -@Component -public class GoogleAuthenticatorUtil { - - private static RedisUtils redisUtils; - @Resource(name = "redisUtils") - public void setRedisUtils(RedisUtils redisUtils) { - GoogleAuthenticatorUtil.redisUtils = redisUtils; - } - - /** default 3 - max 17 (from google docs)最多可偏移的时间 */ - int window_size = 0; - - public void setWindowSize(int s) { - if (s >= 1 && s <= 17) { - window_size = s; - } - } - - /** - * 验证身份验证码是否正确 - * - * @param codes - * 输入的身份验证码 - * @param savedSecret - * 密钥 - * @return - */ - public static Boolean authcode(String codes, String savedSecret) { - long code = 0; - try { - code = Long.parseLong(codes); - } catch (Exception e) { - e.printStackTrace(); - } - long t = System.currentTimeMillis(); - GoogleAuthenticatorUtil ga = new GoogleAuthenticatorUtil(); - // should give 5 * 30 seconds of grace... - ga.setWindowSize(GoogleAuthProperties.WINDOW_SIZE); - boolean r = ga.check_code(savedSecret, code, t); - return r; - } - - /** - * 获取密钥 - * - * @param user - * 用户 - * @param host - * 域 - * @return 密钥 - */ - public static String genSecret(String user, String host) { - - String secretKey = GoogleAuthProperties.REDIS_GOOGLE_AUTH_KEY + "_" + GoogleAuthProperties.SEED + "_" + user; - Object secretValue = redisUtils.get(secretKey); - if (ObjectUtil.isEmpty(secretValue)) { - String secret = generateSecretKey(); - getQRBarcodeURL(user, host, secret); - secretValue = secret; - redisUtils.set(secretKey, secret); - } - - return secretValue.toString(); - } - - private static String generateSecretKey() { - SecureRandom sr = null; - try { - sr = SecureRandom.getInstance(GoogleAuthProperties.RANDOM_NUMBER_ALGORITHM); - sr.setSeed(Base64.decodeBase64(GoogleAuthProperties.SEED)); - byte[] buffer = sr.generateSeed(GoogleAuthProperties.SECRET_SIZE); - Base32 codec = new Base32(); - byte[] bEncodedKey = codec.encode(buffer); - String encodedKey = new String(bEncodedKey); - return encodedKey; - } catch (NoSuchAlgorithmException e) { - // should never occur... configuration error - } - return null; - } - - /** - * 获取二维码图片URL - * - * @param user - * 用户 - * @param host - * 域 - * @param secret - * 密钥 - * @return 二维码URL - */ - public static String getQRBarcodeURL(String user, String host, String secret) { - return String.format(GoogleAuthProperties.QR_CREATE_PREFIX_URL, user, host, secret); - } - - private boolean check_code(String secret, long code, long timeMsec) { - Base32 codec = new Base32(); - byte[] decodedKey = codec.decode(secret); - long t = (timeMsec / 1000L) / 30L; - for (int i = -window_size; i <= window_size; ++i) { - long hash; - try { - hash = verify_code(decodedKey, t + i); - } catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException(e.getMessage()); - } - if (hash == code) { - return true; - } - } - return false; - } - - private static int verify_code(byte[] key, long t) - throws NoSuchAlgorithmException, InvalidKeyException { - byte[] data = new byte[8]; - long value = t; - for (int i = 8; i-- > 0; value >>>= 8) { - data[i] = (byte) value; - } - SecretKeySpec signKey = new SecretKeySpec(key, "HmacSHA1"); - Mac mac = Mac.getInstance("HmacSHA1"); - mac.init(signKey); - byte[] hash = mac.doFinal(data); - int offset = hash[20 - 1] & 0xF; - long truncatedHash = 0; - for (int i = 0; i < 4; ++i) { - truncatedHash <<= 8; - truncatedHash |= (hash[offset + i] & 0xFF); - } - truncatedHash &= 0x7FFFFFFF; - truncatedHash %= 1000000; - return (int) truncatedHash; - } - - public static void main(String[] args) { - /* - * 注意:先运行前两步,获取密钥和二维码url。 然后只运行第三步,填写需要验证的验证码,和第一步生成的密钥 - */ - String user = "testUser"; - String host = "testHost"; - // 第一步:获取密钥 - String secret = genSecret(user, host); - System.out.println("secret:" + secret); - // 第二步:根据密钥获取二维码图片url(可忽略) - String url = getQRBarcodeURL(user, host, secret); - System.out.println("url:" + url); - // 第三步:验证(第一个参数是需要验证的验证码,第二个参数是第一步生成的secret运行) - boolean result = authcode("271239", "OHXU6PLMZMDJIDY6"); - System.out.println("result:" + result); - } -} - diff --git a/wjcy-system/src/main/resources/banner.txt b/wjcy-system/src/main/resources/banner.txt deleted file mode 100644 index d0f401a..0000000 --- a/wjcy-system/src/main/resources/banner.txt +++ /dev/null @@ -1,8 +0,0 @@ - _ _ _ - | | | | (_) - ___| |______ __ _ __| |_ __ ___ _ _ __ - / _ | |______/ _` |/ _` | '_ ` _ \| | '_ \ - | __| | | (_| | (_| | | | | | | | | | | - \___|_| \__,_|\__,_|_| |_| |_|_|_| |_| - - :: Spring Boot :: (v2.1.0.RELEASE) \ No newline at end of file diff --git a/wjcy-system/src/main/resources/config/application-dev.yml b/wjcy-system/src/main/resources/config/application-dev.yml deleted file mode 100644 index 81d0a99..0000000 --- a/wjcy-system/src/main/resources/config/application-dev.yml +++ /dev/null @@ -1,285 +0,0 @@ -#配置数据源 -spring: - datasource: - druid: - db-type: com.alibaba.druid.pool.DruidDataSource - driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy - url: jdbc:log4jdbc:mysql://192.168.10.136:3306/wjcy?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false -# url: jdbc:log4jdbc:mysql://192.168.10.85:3306/wjcy?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false - username: root - password: wjcy@123456 -# url: jdbc:log4jdbc:mysql://120.77.145.59:3306/wjcy_2?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false -# username: root -# password: 416909 - # 初始连接数 - initial-size: 5 - # 最小连接数 - min-idle: 15 - # 最大连接数 - max-active: 30 - # 超时时间(以秒数为单位) - remove-abandoned-timeout: 180 - # 获取连接超时时间 - max-wait: 3000 - # 连接有效性检测时间 - time-between-eviction-runs-millis: 60000 - # 连接在池中最小生存的时间 - min-evictable-idle-time-millis: 300000 - # 连接在池中最大生存的时间 - max-evictable-idle-time-millis: 900000 - # 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除 - test-while-idle: true - # 指明是否在从池中取出连接前进行检验,如果检验失败, 则从池中去除连接并尝试取出另一个 - test-on-borrow: true - # 是否在归还到池中前进行检验 - test-on-return: false - # 检测连接是否有效 - validation-query: select 1 - # 配置监控统计 - webStatFilter: - enabled: true - stat-view-servlet: - enabled: true - url-pattern: /druid/* - reset-enable: false - filter: - stat: - enabled: true - # 记录慢SQL - log-slow-sql: true - slow-sql-millis: 1000 - merge-sql: true - wall: - config: - multi-statement-allow: true - slf4j: - enabled: true - statement-create-after-log-enabled: false - statement-close-after-log-enabled: false - result-set-open-after-log-enabled: false - result-set-close-after-log-enabled: false - result-set-next-after-log-enabled: false - - redis: - #数据库索引 - database: 13 - host: 192.168.10.136 - port: 6379 - password: wjcy@123456 -# host: 120.77.145.59 -# port: 6379 -# password: 416909 - #连接超时时间 - timeout: 5000 - #过期时间 1个月(60*60*24*30) - expired: 2592000 - - mvc: - view: - prefix: classpath:/templates/ - suffix: .html - thymeleaf: - cache: false - -knife4j: - enable: true - basic: - enable: true - username: wjcy - password: 123456 - - -logging: - config: classpath:log4j2.xml - level: - me.zhengjie: debug - -#Mybatis plus 配置 -mybatis-plus: - # 映射文件所在路径 - mapper-locations: classpath*:me/zhengjie/dao/mapper/*.xml - # pojo类所在包路径 - #typeAliasesPackage: - # 开启驼峰命名规则自动转换 - configuration: - map-underscore-to-camel-case: true - log-impl: org.apache.ibatis.logging.log4j2.Log4j2Impl - global-config: - db-config: - # 配置表明前缀,例如表设计时表名为tb_manager,对应entity为Manager - #table-prefix: tb_ - #逻辑已删除值 - logic-delete-value: 1 - #逻辑未删除值 - logic-not-delete-value: 0 - # 是否开启like查询,即对 stirng 字段是否使用 like,默认不开启 - column-like: true - -# 登录相关配置 -login: - # 登录缓存 - cache-enable: true - # 是否限制单用户登录 - single-login: false - # 验证码 - login-code: - # 验证码类型配置 查看 LoginProperties 类 - code-type: arithmetic - # 登录图形验证码有效时间/分钟 - expiration: 2 - # 验证码高度 - width: 111 - # 验证码宽度 - height: 36 - # 内容长度 - length: 2 - # 字体名称,为空则使用默认字体 - font-name: - # 字体大小 - font-size: 25 - -#jwt -jwt: - header: Authorization - # 令牌前缀 - token-start-with: Bearer - # 必须使用最少88位的Base64对该令牌进行编码 - base64-secret: ZmQ0ZGI5NjQ0MDQwY2I4MjMxY2Y3ZmI3MjdhN2ZmMjNhODViOTg1ZGE0NTBjMGM4NDA5NzYxMjdjOWMwYWRmZTBlZjlhNGY3ZTg4Y2U3YTE1ODVkZDU5Y2Y3OGYwZWE1NzUzNWQ2YjFjZDc0NGMxZWU2MmQ3MjY1NzJmNTE0MzI= - # 令牌过期时间 此处单位/毫秒 ,默认4小时,可在此网站生成 https://www.convertworld.com/zh-hans/time/milliseconds.html - token-validity-in-seconds: 14400000 - # 在线用户key - online-key: online-token- - # 验证码 - code-key: code-key- - # token 续期检查时间范围(默认30分钟,单位毫秒),在token即将过期的一段时间内用户操作了,则给用户的token续期 - detect: 1800000 - # 续期时间范围,默认1小时,单位毫秒 - renew: 3600000 - -#是否允许生成代码,生产环境设置为false -generator: - enabled: true - -#是否开启 swagger-ui -swagger: - enabled: true - -# IP 本地解析 -ip: - local-parsing: true - -# 文件存储路径 -file: - mac: - path: ~/file/ - avatar: ~/avatar/ - linux: - path: /home/luckyDraw/file/ - avatar: /home/luckyDraw/avatar/ - windows: - path: E:\wjcyFileSpace\file\ - avatar: E:\wjcyFileSpace\avatar\ - # 文件大小 /M - maxSize: 100 - avatarMaxSize: 5 - - -system: - imgPath: E:\wjcyFileSpace\file - # 静态资源访问路径(返回前端时添加) -# fileVisitAddr: http://www.images.com - fileVisitAddr: http://localhost:8008/file - #文件上传接口后缀,用来放行xss过滤 - uploadSuffix: file/uploadFile - # 单文件上传大小限制,单位 :MB - maxFileSize: 10 - # 视频单文件上传限制,单位 :MB - maxVideoFileSize: 25 - # ip库文件的绝对路径 window 就是指到resource下的ip2region下 - ip2regionDbPath: E:\CodeWorkSpace\wjcy\wjcy-system\src\main\resources\ip2region\ip2region.db - # 多语言文件路径 - languagePath: /home/waguda/wjcy/language - -config: - # 放掉的api 校验token huijia@biying123 - https://md5jiami.51240.com/ - apiToken: "e6f5e41ca6b103070ff89c812a36eaec" - #文件上传前缀(首位+'/' 末尾不加'/'),用来放行静态资源访问权限(图片,音频等) - uploadPrefix: /capital - # 图片上传保存路径(注意格式,首尾带‘/’) key:图片上传类型 value: - uploadImgPath: - # 用户头像修改 - 1: /wjcy/img/ - 2: /wjcy/rotation/ - 3: /wjcy/article/ - 4: /wjcy/currency/ - # 提现审核提示音 - 5: /wjcy/tones/ - # 聊天室默认头像 - 6: /wjcy/chat/head/ - # 聊天室会员上传的图片 - 7: /wjcy/chat/img/ - # 聊天室会员上传视频 - 8: /wjcy/chat/video/ - 9: /wjcy/promotion/ - # excel - 10: /wjcy/excel/ - 11: /wjcy/export/ - 12: /wjcy/wellReceived/ - 13: /wjcy/dhWellReceived/ - # 支持文件上传的文件格式 - sustainImgFormat: - - img - - jpg - - png - - mp3 - - pem - - jpeg - - gif - - JPG - - JPEG - - PNG - - AVI - - mov - - rmvb - - rm - - FLV - - mp4 - - 3GP - - zip - - xlsx - -# Goole Auth -auth: - secret_size: 10 - seed: g8GjEvTbW5oVSV7avLBdwIHqGlUYNzKFI7izOF8GwLDVKs2m0QN7vxRs2im5MDaNCWGmcD2rvcZx - random_number_algorithm: SHA1PRNG - window_size: 0 - redis_google_auth_key: googelAuthKey - qr_create_prefix_url: https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=otpauth://totp/%s@%s?secret=%s - - -#敦煌api 请求参数 -dh: - access_token: 0QkUo9opYCcmB0UMzqK2XKFFNDDvlpmpRYyDkcVJ - buy_order_url: http://api.dhgate.com/dop/router - buy_order_method: dh.buyer.order.place - buy_order_v: 2.0 - pay_order_url: http://api.dhgate.com/dop/router - pay_order_method: dh.buyer.order.pay - pay_order_v: 1.0 - -# 平台配置 -plats: - dh: - buyOrderUrl: http://api.dhgate.com/dop/router - buyOrderMethod: dh.buyer.order.place - buyOrderv: 2.0 - payOrder_url: http://api.dhgate.com/dop/router - payOrderMethod: dh.buyer.order.pay - payOrderv: 1.0 - -# 影刀 -yd: - accessKeyId: navkbKspVWfjPgm6@platform - accessKeySecret: SuUc0zMfhrQX594eJnwFPm1sqk8CYtNv - callback: http://test.vogocm.com:8008/api/yd/callback diff --git a/wjcy-system/src/main/resources/config/application-local.yml b/wjcy-system/src/main/resources/config/application-local.yml deleted file mode 100644 index 262baba..0000000 --- a/wjcy-system/src/main/resources/config/application-local.yml +++ /dev/null @@ -1,411 +0,0 @@ -#配置数据源 -spring: - datasource: - druid: - db-type: com.alibaba.druid.pool.DruidDataSource - driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy - url: jdbc:log4jdbc:mysql://192.168.110.108:3306/jlt_capiltal_xxs5?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false - username: root - password: root - # 初始连接数 - initial-size: 5 - # 最小连接数 - min-idle: 15 - # 最大连接数 - max-active: 30 - # 超时时间(以秒数为单位) - remove-abandoned-timeout: 180 - # 获取连接超时时间 - max-wait: 3000 - # 连接有效性检测时间 - time-between-eviction-runs-millis: 60000 - # 连接在池中最小生存的时间 - min-evictable-idle-time-millis: 300000 - # 连接在池中最大生存的时间 - max-evictable-idle-time-millis: 900000 - # 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除 - test-while-idle: true - # 指明是否在从池中取出连接前进行检验,如果检验失败, 则从池中去除连接并尝试取出另一个 - test-on-borrow: true - # 是否在归还到池中前进行检验 - test-on-return: false - # 检测连接是否有效 - validation-query: select 1 - # 配置监控统计 - webStatFilter: - enabled: true - stat-view-servlet: - enabled: true - url-pattern: /druid/* - reset-enable: false - filter: - stat: - enabled: true - # 记录慢SQL - log-slow-sql: true - slow-sql-millis: 1000 - merge-sql: true - wall: - config: - multi-statement-allow: true - slf4j: - enabled: true - statement-create-after-log-enabled: false - statement-close-after-log-enabled: false - result-set-open-after-log-enabled: false - result-set-close-after-log-enabled: false - result-set-next-after-log-enabled: false - - redis: - #数据库索引 - database: 12 - host: 192.168.110.108 - port: 6379 - password: tiyu!tiyu! - #连接超时时间 - timeout: 5000 - #过期时间 1个月(60*60*24*30) - expired: 2592000 - - mvc: - view: - prefix: classpath:/templates/ - suffix: .html - thymeleaf: - cache: false - - -logging: - config: classpath:log4j2.xml - level: - me.zhengjie: debug - -#Mybatis plus 配置 -mybatis-plus: - # 映射文件所在路径 - mapper-locations: classpath*:me/zhengjie/dao/mapper/*.xml - # pojo类所在包路径 - #typeAliasesPackage: - # 开启驼峰命名规则自动转换 - configuration: - map-underscore-to-camel-case: true - log-impl: org.apache.ibatis.logging.log4j2.Log4j2Impl - global-config: - db-config: - # 配置表明前缀,例如表设计时表名为tb_manager,对应entity为Manager - #table-prefix: tb_ - #逻辑已删除值 - logic-delete-value: 1 - #逻辑未删除值 - logic-not-delete-value: 0 - # 是否开启like查询,即对 stirng 字段是否使用 like,默认不开启 - column-like: true - -# 登录相关配置 -login: - # 登录缓存 - cache-enable: true - # 是否限制单用户登录 - single-login: false - # 验证码 - login-code: - # 验证码类型配置 查看 LoginProperties 类 - code-type: arithmetic - # 登录图形验证码有效时间/分钟 - expiration: 2 - # 验证码高度 - width: 111 - # 验证码宽度 - height: 36 - # 内容长度 - length: 2 - # 字体名称,为空则使用默认字体 - font-name: - # 字体大小 - font-size: 25 - -#jwt -jwt: - header: Authorization - # 令牌前缀 - token-start-with: Bearer - # 必须使用最少88位的Base64对该令牌进行编码 - base64-secret: ZmQ0ZGI5NjQ0MDQwY2I4MjMxY2Y3ZmI3MjdhN2ZmMjNhODViOTg1ZGE0NTBjMGM4NDA5NzYxMjdjOWMwYWRmZTBlZjlhNGY3ZTg4Y2U3YTE1ODVkZDU5Y2Y3OGYwZWE1NzUzNWQ2YjFjZDc0NGMxZWU2MmQ3MjY1NzJmNTE0MzI= - # 令牌过期时间 此处单位/毫秒 ,默认4小时,可在此网站生成 https://www.convertworld.com/zh-hans/time/milliseconds.html - token-validity-in-seconds: 14400000 - # 在线用户key - online-key: online-token- - # 验证码 - code-key: code-key- - # token 续期检查时间范围(默认30分钟,单位毫秒),在token即将过期的一段时间内用户操作了,则给用户的token续期 - detect: 1800000 - # 续期时间范围,默认1小时,单位毫秒 - renew: 3600000 - -#是否允许生成代码,生产环境设置为false -generator: - enabled: true - -#是否开启 swagger-ui -swagger: - enabled: true - -# IP 本地解析 -ip: - local-parsing: true - -# 文件存储路径 -file: - mac: - path: ~/file/ - avatar: ~/avatar/ - linux: - path: /home/luckyDraw/file/ - avatar: /home/luckyDraw/avatar/ - windows: - path: C:\luckyDraw\file\ - avatar: C:\luckyDraw\avatar\ - # 文件大小 /M - maxSize: 100 - avatarMaxSize: 5 - - -system: - imgPath: /home/waguda/capiltal/file/ - # 静态资源访问路径(返回前端时添加) - fileVisitAddr: http://img.com - #文件上传接口后缀,用来放行xss过滤 - uploadSuffix: file/uploadFile - # 单文件上传大小限制,单位 :MB - maxFileSize: 10 - # 视频单文件上传限制,单位 :MB - maxVideoFileSize: 25 - # ip库文件的绝对路径 window 就是指到resource下的ip2region下 - ip2regionDbPath: /home/work/services/capiltal/capiltal-system/ip2region/ip2region.db - # 多语言文件路径 - languagePath: /home/waguda/capiltal/language - wsUrl: ws://192.168.110.99:8110 - # 百度翻译 APPID - baiduAppId: 20211116001000718 - # 百度翻译privateKey - baiduPrivateKey: jSDxw0_QkRnbRdRT0rKY - -config: - # 放掉的api 校验token huijia@biying123 - https://md5jiami.51240.com/ - apiToken: "e6f5e41ca6b103070ff89c812a36eaec" - #文件上传前缀(首位+'/' 末尾不加'/'),用来放行静态资源访问权限(图片,音频等) - uploadPrefix: /capital - # 图片上传保存路径(注意格式,首尾带‘/’) key:图片上传类型 value: - uploadImgPath: - # 用户头像修改 - 1: /capital/img/ - 2: /capital/rotation/ - 3: /capital/article/ - 4: /capital/currency/ - - # 支持文件上传的文件格式 - sustainImgFormat: - - img - - jpg - - png - - mp3 - - pem - - jpeg - - gif - - JPG - - JPEG - - PNG - - AVI - - mov - - rmvb - - rm - - FLV - - mp4 - - 3GP - - zip - -web3j: - # web3j 区块链信息 - linkAddress: - #火币 - - name: HECO - # 服务实现类全限定类名 - serverName: "me.zhengjie.web3j.service.impl.ETHBlockchainServiceImpl" - # rpc 连接地址 - url: https://http-testnet.hecochain.com - # 官网域名+查询交易明细 - domain: https://testnet.hecoinfo.com/tx - # 链路Id,必须以 0x开头 - chainId: "0x100" - #合约币种 - contracts: - USDT: - address: "0x425a2d7c3df8a7872f05405dc6e34b6d9cd714be" - accuracy: 18 - MDX: - address: "0x30e552B5Ce0495A55b9138343dD88d6457a6C66b" - accuracy: 18 - DMT: - address: "0x4da2F416aa79fB0BeCA3D6cf6EB6Fe86b4a747CF" - accuracy: 18 - - # ok链 - - name: OKEX - # 服务实现类全限定类名 - serverName: "me.zhengjie.web3j.service.impl.ETHBlockchainServiceImpl" - # rpc 连接地址 - url: https://exchaintestrpc.okex.org - # 官网域名+查询交易明细 - domain: https://www.oklink.com/zh-cn/oec-test/tx - # 链路Id,必须以 0x开头 - chainId: "0x41" - #合约币种 - contracts: - USDT: - address: "0x1328bB18fe06647878d04fcB94BA5474c85C7616" - accuracy: 18 - MDX: - address: "" - accuracy: 0 - DMT: - address: "" - accuracy: 0 - - # 币安链 - - name: BNB - # 服务实现类全限定类名 - serverName: "me.zhengjie.web3j.service.impl.ETHBlockchainServiceImpl" - # rpc 连接地址 https://data-seed-prebsc-1-s1.binance.org:8545/ https://data-seed-prebsc-2-s3.binance.org:8545 - url: https://data-seed-prebsc-1-s1.binance.org:8545/ - # 官网域名+查询交易明细 - domain: https://testnet.bscscan.com/tx - # 链路Id,必须以 0x开头 - chainId: "0x61" - #合约币种 - contracts: - USDT: - # address: "0x3D39e763d2942816c96E783bb53C7c5DB44AFFF3" - address: "0xA12327AaE5C6CCcf816bAC49136f050FeFe89CB6" - accuracy: 18 - MDX: - address: "0x79CA70F863c4273Bb276F37381e1aD2096b77CeE" - accuracy: 18 - ETH: - address: "0x19E6689Bb9CF7Ef04AFf57B77562E4C943c415cD" - accuracy: 18 - CAKE: - address: "0xeBb3CD5EF4a5875AEfcf02CeAaa77Ac8A164523f" - accuracy: 18 - - # 波场 - - name: TRON - # 服务实现类全限定类名 - serverName: "me.zhengjie.web3j.service.impl.TronBlockchainServiceImpl" - # rpc 连接地址, 可选: mainnet、shasta、nile,或其他节点(例:47.252.19.181) - network: shasta - # http接口请求的URL - url: https://api.shasta.trongrid.io - # 官网域名+查询交易明细 - domain: https://shasta.tronscan.org//#/transaction - # 私钥,波场调用API时,不管什么接口都必须要设置私钥 - hexPrivateKey: "780e0d9997862dfac8e0698c8dd457531c9c13ecf6cec377315e95c30b43c8c4" - # 说明:https://cn.developers.tron.network/reference/%E4%BB%80%E4%B9%88%E6%98%AFapi-key e3506c97-a4b6-4bf7-829a-6a5d48b112f7 - apiKey: "" - #合约币种 - contracts: - USDT: - # TNuoKL1ni8aoshfFL1ASca1Gou9RXwAzfn USDT:TXYZopYRdj2D9XRtbG411XZZ3kM5VkAeBf - address: "TNpzntv25qsy1HVWQW2jCrhWj5wad3tVcj" - accuracy: 10 - MDX: - address: "" - accuracy: 0 - DMT: - address: "" - accuracy: 0 - - blockchain: - 1: - - currencyType: 1 - name: USDT - - currencyType: 2 - name: MDX - - currencyType: 3 - name: DMT - 2: - - currencyType: 1 - name: USDT - 4: - - currencyType: 1 - name: USDT - - currencyType: 2 - name: MDX - - currencyType: 5 - name: ETH - - currencyType: 4 - name: CAKE - 5: - - currencyType: 1 - name: USDT - -# 采集开奖结果配置 -draw: - config: - configs: - - passType: 1 #链路 火币链 - currency: BTC #采集币种 BTC - url: https://api.huobi.pro/market/history/kline #采集地址 - period: 1min #采集周期 1min, 5min, 15min, 30min, ---- 60min, 4hour, 1day, 1mon, 1week, 1year - symbol: btcusdt #交易对 btcusdt, ethbtc - size: 10 #返回数据条数 1 - 2000 - - passType: 4 #链路 币安链 - currency: BTC #采集币种 BTC - url: https://api.binance.com/api/v3/klines #采集地址 - period: 1m #采集周期 #采集周期 1m, 3m, 5m, 15m, 30m, ---- 1h, 2h, 4h, 6h, 8h, 12h, 1d, 3d, 1w, 1M - symbol: BTCUSDT #交易对 - size: 10 #返回数据条数 1 - 1000 - - - - -#该应用是否启用生产者 -rocketmq: - producer: - isOnOff: on - #发送同一类消息的设置为同一个group,保证唯一,默认不需要设置,rocketmq会使用ip@pid(pid代表jvm名字)作为唯一标示 - groupName: springboot-rocketmq-producer-capiltal - #mq的nameserver地址 43.240.95.168 - namesrvAddr: 192.168.110.108:9876 - #消息最大长度 默认1024*4(4M) - maxMessageSize: 4096 - #发送消息超时时间,默认3000 - sendMsgTimeout: 3000 - #发送消息失败重试次数,默认2 - retryTimesWhenSendFailed: 2 - consumer: - isOnOff: on - groupName: springboot-rocketmq-consumer-capiltal - #mq的nameserver地址 43.240.95.168 - namesrvAddr: 192.168.110.108:9876 - #该消费者订阅的主题和tags("*"号表示订阅该主题下所有的tags),格式:topic~tag1||tag2||tag3;topic2~*; - topics: capiltal-settlement-top~*;capiltal-statistics-member-top~* - consumeThreadMin: 20 - consumeThreadMax: 64 - #设置一次消费消息的条数,默认为1条 - consumeMessageBatchMaxSize: 1 - - -#Goole Auth -auth: - secret_size: 10 - seed: g8GjEvTbW5oVSV7avLBdwIHqGlUYNzKFI7izOF8GwLDVKs2m0QN7vxRs2im5MDaNCWGmcD2rvcZx - random_number_algorithm: SHA1PRNG - window_size: 0 - redis_google_auth_key: googelAuthKey - qr_create_prefix_url: https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=otpauth://totp/%s@%s?secret=%s - -telegram: - bot: - username: capiltal_uat_bot - token: 5008414161:AAHflrbo2v0DN8hpLhZAg5gC787yxFloWlk - chatId: -665412272 \ No newline at end of file diff --git a/wjcy-system/src/main/resources/config/application-prod.yml b/wjcy-system/src/main/resources/config/application-prod.yml deleted file mode 100644 index 08396dc..0000000 --- a/wjcy-system/src/main/resources/config/application-prod.yml +++ /dev/null @@ -1,250 +0,0 @@ -#配置数据源 -spring: - datasource: - druid: - db-type: com.alibaba.druid.pool.DruidDataSource - driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy - url: jdbc:log4jdbc:mysql://mysql:3306/wjcy?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false - username: root - password: wjcy@123456 - # 初始连接数 - initial-size: 5 - # 最小连接数 - min-idle: 15 - # 最大连接数 - max-active: 30 - # 超时时间(以秒数为单位) - remove-abandoned-timeout: 180 - # 获取连接超时时间 - max-wait: 3000 - # 连接有效性检测时间 - time-between-eviction-runs-millis: 60000 - # 连接在池中最小生存的时间 - min-evictable-idle-time-millis: 300000 - # 连接在池中最大生存的时间 - max-evictable-idle-time-millis: 900000 - # 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除 - test-while-idle: true - # 指明是否在从池中取出连接前进行检验,如果检验失败, 则从池中去除连接并尝试取出另一个 - test-on-borrow: true - # 是否在归还到池中前进行检验 - test-on-return: false - # 检测连接是否有效 - validation-query: select 1 - # 配置监控统计 - webStatFilter: - enabled: true - stat-view-servlet: - enabled: true - url-pattern: /druid/* - reset-enable: false - filter: - stat: - enabled: true - # 记录慢SQL - log-slow-sql: true - slow-sql-millis: 1000 - merge-sql: true - wall: - config: - multi-statement-allow: true - slf4j: - enabled: true - statement-create-after-log-enabled: false - statement-close-after-log-enabled: false - result-set-open-after-log-enabled: false - result-set-close-after-log-enabled: false - result-set-next-after-log-enabled: false - - redis: - #数据库索引 - database: 12 - host: redis - port: 6379 - password: wjcy@123456 - #连接超时时间 - timeout: 5000 - #过期时间 1个月(60*60*24*30) - expired: 2592000 - - mvc: - view: - prefix: classpath:/templates/ - suffix: .html - thymeleaf: - cache: false - - -logging: - config: classpath:log4j2.xml - level: - me.zhengjie: debug - -#Mybatis plus 配置 -mybatis-plus: - # 映射文件所在路径 - mapper-locations: classpath*:me/zhengjie/dao/mapper/*.xml - # pojo类所在包路径 - #typeAliasesPackage: - # 开启驼峰命名规则自动转换 - configuration: - map-underscore-to-camel-case: true - log-impl: org.apache.ibatis.logging.log4j2.Log4j2Impl - global-config: - db-config: - # 配置表明前缀,例如表设计时表名为tb_manager,对应entity为Manager - #table-prefix: tb_ - #逻辑已删除值 - logic-delete-value: 1 - #逻辑未删除值 - logic-not-delete-value: 0 - # 是否开启like查询,即对 stirng 字段是否使用 like,默认不开启 - column-like: true - -# 登录相关配置 -login: - # 登录缓存 - cache-enable: true - # 是否限制单用户登录 - single-login: false - # 验证码 - login-code: - # 验证码类型配置 查看 LoginProperties 类 - code-type: arithmetic - # 登录图形验证码有效时间/分钟 - expiration: 2 - # 验证码高度 - width: 111 - # 验证码宽度 - height: 36 - # 内容长度 - length: 2 - # 字体名称,为空则使用默认字体 - font-name: - # 字体大小 - font-size: 25 - -#jwt -jwt: - header: Authorization - # 令牌前缀 - token-start-with: Bearer - # 必须使用最少88位的Base64对该令牌进行编码 - base64-secret: ZmQ0ZGI5NjQ0MDQwY2I4MjMxY2Y3ZmI3MjdhN2ZmMjNhODViOTg1ZGE0NTBjMGM4NDA5NzYxMjdjOWMwYWRmZTBlZjlhNGY3ZTg4Y2U3YTE1ODVkZDU5Y2Y3OGYwZWE1NzUzNWQ2YjFjZDc0NGMxZWU2MmQ3MjY1NzJmNTE0MzI= - # 令牌过期时间 此处单位/毫秒 ,默认4小时,可在此网站生成 https://www.convertworld.com/zh-hans/time/milliseconds.html - token-validity-in-seconds: 14400000 - # 在线用户key - online-key: online-token- - # 验证码 - code-key: code-key- - # token 续期检查时间范围(默认30分钟,单位毫秒),在token即将过期的一段时间内用户操作了,则给用户的token续期 - detect: 1800000 - # 续期时间范围,默认1小时,单位毫秒 - renew: 3600000 - -#是否允许生成代码,生产环境设置为false -generator: - enabled: true - -#是否开启 swagger-ui -swagger: - enabled: true - -# IP 本地解析 -ip: - local-parsing: true - -# 文件存储路径 -file: - mac: - path: ~/file/ - avatar: ~/avatar/ - linux: - path: /home/luckyDraw/file/ - avatar: /home/luckyDraw/avatar/ - windows: - path: C:\luckyDraw\file\ - avatar: C:\luckyDraw\avatar\ - # 文件大小 /M - maxSize: 100 - avatarMaxSize: 5 - - -system: - imgPath: /home/work/wjcy/file - # 静态资源访问路径(返回前端时添加) - fileVisitAddr: http://img.com - #文件上传接口后缀,用来放行xss过滤 - uploadSuffix: file/uploadFile - # 单文件上传大小限制,单位 :MB - maxFileSize: 10 - # 视频单文件上传限制,单位 :MB - maxVideoFileSize: 25 - # ip库文件的绝对路径 window 就是指到resource下的ip2region下 - ip2regionDbPath: /home/work/wjcy/wjcy-system/src/main/resources/ip2region/ip2region.db - # 多语言文件路径 - languagePath: /home/work/wjcy/wjcy-system/language - -config: - # 放掉的api 校验token huijia@biying123 - https://md5jiami.51240.com/ - apiToken: "e6f5e41ca6b103070ff89c812a36eaec" - #文件上传前缀(首位+'/' 末尾不加'/'),用来放行静态资源访问权限(图片,音频等) - uploadPrefix: /capital - # 图片上传保存路径(注意格式,首尾带‘/’) key:图片上传类型 value: - uploadImgPath: - # 用户头像修改 - 1: /wjcy/img/ - 2: /wjcy/rotation/ - 3: /wjcy/article/ - 4: /wjcy/currency/ - # 提现审核提示音 - 5: /wjcy/tones/ - # 聊天室默认头像 - 6: /wjcy/chat/head/ - # 聊天室会员上传的图片 - 7: /wjcy/chat/img/ - # 聊天室会员上传视频 - 8: /wjcy/chat/video/ - 9: /wjcy/promotion/ - # excel - 10: /wjcy/excel/ - # 支持文件上传的文件格式 - sustainImgFormat: - - img - - jpg - - png - - mp3 - - pem - - jpeg - - gif - - JPG - - JPEG - - PNG - - AVI - - mov - - rmvb - - rm - - FLV - - mp4 - - 3GP - - zip - - xlsx - -# Goole Auth -auth: - secret_size: 10 - seed: g8GjEvTbW5oVSV7avLBdwIHqGlUYNzKFI7izOF8GwLDVKs2m0QN7vxRs2im5MDaNCWGmcD2rvcZx - random_number_algorithm: SHA1PRNG - window_size: 0 - redis_google_auth_key: googelAuthKey - qr_create_prefix_url: https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=otpauth://totp/%s@%s?secret=%s - -#敦煌api 请求参数 -dh: - access_token: 0QkUo9opYCcmB0UMzqK2XKFFNDDvlpmpRYyDkcVJ - buy_order_url: http://api.dhgate.com/dop/router - buy_order_method: dh.buyer.order.place - buy_order_v: 2.0 - pay_order_url: http://api.dhgate.com/dop/router - pay_order_method: dh.buyer.order.pay - pay_order_v: 1.0 \ No newline at end of file diff --git a/wjcy-system/src/main/resources/config/application-xxs.yml b/wjcy-system/src/main/resources/config/application-xxs.yml deleted file mode 100644 index 7471b8b..0000000 --- a/wjcy-system/src/main/resources/config/application-xxs.yml +++ /dev/null @@ -1,417 +0,0 @@ -#配置数据源 -spring: - datasource: - druid: - db-type: com.alibaba.druid.pool.DruidDataSource - driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy - url: jdbc:log4jdbc:mysql://120.77.145.59:3306/jlt_capiltal?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false - username: root - password: 416909 - # 初始连接数 - initial-size: 5 - # 最小连接数 - min-idle: 15 - # 最大连接数 - max-active: 30 - # 超时时间(以秒数为单位) - remove-abandoned-timeout: 180 - # 获取连接超时时间 - max-wait: 3000 - # 连接有效性检测时间 - time-between-eviction-runs-millis: 60000 - # 连接在池中最小生存的时间 - min-evictable-idle-time-millis: 300000 - # 连接在池中最大生存的时间 - max-evictable-idle-time-millis: 900000 - # 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除 - test-while-idle: true - # 指明是否在从池中取出连接前进行检验,如果检验失败, 则从池中去除连接并尝试取出另一个 - test-on-borrow: true - # 是否在归还到池中前进行检验 - test-on-return: false - # 检测连接是否有效 - validation-query: select 1 - # 配置监控统计 - webStatFilter: - enabled: true - stat-view-servlet: - enabled: true - url-pattern: /druid/* - reset-enable: false - filter: - stat: - enabled: true - # 记录慢SQL - log-slow-sql: true - slow-sql-millis: 1000 - merge-sql: true - wall: - config: - multi-statement-allow: true - slf4j: - enabled: true - statement-create-after-log-enabled: false - statement-close-after-log-enabled: false - result-set-open-after-log-enabled: false - result-set-close-after-log-enabled: false - result-set-next-after-log-enabled: false - - redis: - #数据库索引 - database: 12 - host: 120.77.145.59 - port: 6379 - password: 416909 - #连接超时时间 - timeout: 5000 - #过期时间 1个月(60*60*24*30) - expired: 2592000 - - mvc: - view: - prefix: classpath:/templates/ - suffix: .html - thymeleaf: - cache: false - - -logging: - config: classpath:log4j2.xml - level: - me.zhengjie: debug - -#Mybatis plus 配置 -mybatis-plus: - # 映射文件所在路径 - mapper-locations: classpath*:me/zhengjie/dao/mapper/*.xml - # pojo类所在包路径 - #typeAliasesPackage: - # 开启驼峰命名规则自动转换 - configuration: - map-underscore-to-camel-case: true - log-impl: org.apache.ibatis.logging.log4j2.Log4j2Impl - global-config: - db-config: - # 配置表明前缀,例如表设计时表名为tb_manager,对应entity为Manager - #table-prefix: tb_ - #逻辑已删除值 - logic-delete-value: 1 - #逻辑未删除值 - logic-not-delete-value: 0 - # 是否开启like查询,即对 stirng 字段是否使用 like,默认不开启 - column-like: true - -# 登录相关配置 -login: - # 登录缓存 - cache-enable: true - # 是否限制单用户登录 - single-login: false - # 验证码 - login-code: - # 验证码类型配置 查看 LoginProperties 类 - code-type: arithmetic - # 登录图形验证码有效时间/分钟 - expiration: 2 - # 验证码高度 - width: 111 - # 验证码宽度 - height: 36 - # 内容长度 - length: 2 - # 字体名称,为空则使用默认字体 - font-name: - # 字体大小 - font-size: 25 - -#jwt -jwt: - header: Authorization - # 令牌前缀 - token-start-with: Bearer - # 必须使用最少88位的Base64对该令牌进行编码 - base64-secret: ZmQ0ZGI5NjQ0MDQwY2I4MjMxY2Y3ZmI3MjdhN2ZmMjNhODViOTg1ZGE0NTBjMGM4NDA5NzYxMjdjOWMwYWRmZTBlZjlhNGY3ZTg4Y2U3YTE1ODVkZDU5Y2Y3OGYwZWE1NzUzNWQ2YjFjZDc0NGMxZWU2MmQ3MjY1NzJmNTE0MzI= - # 令牌过期时间 此处单位/毫秒 ,默认4小时,可在此网站生成 https://www.convertworld.com/zh-hans/time/milliseconds.html - token-validity-in-seconds: 14400000 - # 在线用户key - online-key: online-token- - # 验证码 - code-key: code-key- - # token 续期检查时间范围(默认30分钟,单位毫秒),在token即将过期的一段时间内用户操作了,则给用户的token续期 - detect: 1800000 - # 续期时间范围,默认1小时,单位毫秒 - renew: 3600000 - -#是否允许生成代码,生产环境设置为false -generator: - enabled: true - -#是否开启 swagger-ui -swagger: - enabled: true - -# IP 本地解析 -ip: - local-parsing: true - -# 文件存储路径 -file: - mac: - path: ~/file/ - avatar: ~/avatar/ - linux: - path: /home/luckyDraw/file/ - avatar: /home/luckyDraw/avatar/ - windows: - path: C:\luckyDraw\file\ - avatar: C:\luckyDraw\avatar\ - # 文件大小 /M - maxSize: 100 - avatarMaxSize: 5 - - -system: - imgPath: /home/waguda/capiltal/file/ - # 静态资源访问路径(返回前端时添加) - fileVisitAddr: http://img.com - #文件上传接口后缀,用来放行xss过滤 - uploadSuffix: file/uploadFile - # 单文件上传大小限制,单位 :MB - maxFileSize: 10 - # 视频单文件上传限制,单位 :MB - maxVideoFileSize: 25 - # ip库文件的绝对路径 window 就是指到resource下的ip2region下 - ip2regionDbPath: /home/work/services/capiltal/capiltal-system/ip2region/ip2region.db - # 多语言文件路径 - languagePath: /home/waguda/capiltal/language - wsUrl: ws://192.168.110.99:8110 - # 百度翻译 APPID - baiduAppId: 20211116001000718 - # 百度翻译privateKey - baiduPrivateKey: jSDxw0_QkRnbRdRT0rKY - -config: - # 放掉的api 校验token huijia@biying123 - https://md5jiami.51240.com/ - apiToken: "e6f5e41ca6b103070ff89c812a36eaec" - #文件上传前缀(首位+'/' 末尾不加'/'),用来放行静态资源访问权限(图片,音频等) - uploadPrefix: /capital - # 图片上传保存路径(注意格式,首尾带‘/’) key:图片上传类型 value: - uploadImgPath: - # 用户头像修改 - 1: /capital/img/ - 2: /capital/rotation/ - 3: /capital/article/ - 4: /capital/currency/ - # 提现审核提示音 - 5: /capital/tones/ - # 聊天室默认头像 - 6: /capital/chat/head/ - # 聊天室会员上传的图片 - 7: /capital/chat/img/ - # 聊天室会员上传视频 - 8: /capital/chat/video/ - 9: /capital/promotion/ - # 平台UBB 富文本 - 10: /capital/platUBB/ - # 支持文件上传的文件格式 - sustainImgFormat: - - img - - jpg - - png - - mp3 - - pem - - jpeg - - gif - - JPG - - JPEG - - PNG - - AVI - - mov - - rmvb - - rm - - FLV - - mp4 - - 3GP - - zip - -web3j: - # web3j 区块链信息 - linkAddress: - #火币 - - name: HECO - # 服务实现类全限定类名 - serverName: "me.zhengjie.web3j.service.impl.ETHBlockchainServiceImpl" - # rpc 连接地址 - url: https://http-testnet.hecochain.com - # 官网域名+查询交易明细 - domain: https://testnet.hecoinfo.com/tx - # 链路Id,必须以 0x开头 - chainId: "0x100" - #合约币种 - contracts: - USDT: - address: "0x425a2d7c3df8a7872f05405dc6e34b6d9cd714be" - accuracy: 18 - MDX: - address: "0x30e552B5Ce0495A55b9138343dD88d6457a6C66b" - accuracy: 18 - DMT: - address: "0x4da2F416aa79fB0BeCA3D6cf6EB6Fe86b4a747CF" - accuracy: 18 - - # ok链 - - name: OKEX - # 服务实现类全限定类名 - serverName: "me.zhengjie.web3j.service.impl.ETHBlockchainServiceImpl" - # rpc 连接地址 - url: https://exchaintestrpc.okex.org - # 官网域名+查询交易明细 - domain: https://www.oklink.com/zh-cn/oec-test/tx - # 链路Id,必须以 0x开头 - chainId: "0x41" - #合约币种 - contracts: - USDT: - address: "0x1328bB18fe06647878d04fcB94BA5474c85C7616" - accuracy: 18 - MDX: - address: "" - accuracy: 0 - DMT: - address: "" - accuracy: 0 - - # 币安链 - - name: BSC - # 服务实现类全限定类名 - serverName: "me.zhengjie.web3j.service.impl.ETHBlockchainServiceImpl" - # rpc 连接地址 https://data-seed-prebsc-1-s1.binance.org:8545/ https://data-seed-prebsc-2-s3.binance.org:8545 - url: https://data-seed-prebsc-1-s1.binance.org:8545/ - # 官网域名+查询交易明细 - domain: https://testnet.bscscan.com/tx - # 链路Id,必须以 0x开头 - chainId: "0x61" - #合约币种 - contracts: - USDT: - # address: "0x3D39e763d2942816c96E783bb53C7c5DB44AFFF3" - address: "0xA12327AaE5C6CCcf816bAC49136f050FeFe89CB6" - accuracy: 18 - MDX: - address: "0x79CA70F863c4273Bb276F37381e1aD2096b77CeE" - accuracy: 18 - ETH: - address: "0x19E6689Bb9CF7Ef04AFf57B77562E4C943c415cD" - accuracy: 18 - CAKE: - address: "0xeBb3CD5EF4a5875AEfcf02CeAaa77Ac8A164523f" - accuracy: 18 - - # 波场 - - name: TRON - # 服务实现类全限定类名 - serverName: "me.zhengjie.web3j.service.impl.TronBlockchainServiceImpl" - # rpc 连接地址, 可选: mainnet、shasta、nile,或其他节点(例:47.252.19.181) - network: shasta - # http接口请求的URL - url: https://api.shasta.trongrid.io - # 官网域名+查询交易明细 - domain: https://shasta.tronscan.org//#/transaction - # 私钥,波场调用API时,不管什么接口都必须要设置私钥 - hexPrivateKey: "780e0d9997862dfac8e0698c8dd457531c9c13ecf6cec377315e95c30b43c8c4" - # 说明:https://cn.developers.tron.network/reference/%E4%BB%80%E4%B9%88%E6%98%AFapi-key e3506c97-a4b6-4bf7-829a-6a5d48b112f7 - apiKey: "" - #合约币种 - contracts: - USDT: - # TNuoKL1ni8aoshfFL1ASca1Gou9RXwAzfn USDT:TXYZopYRdj2D9XRtbG411XZZ3kM5VkAeBf - address: "TNpzntv25qsy1HVWQW2jCrhWj5wad3tVcj" - accuracy: 10 - MDX: - address: "" - accuracy: 0 - DMT: - address: "" - accuracy: 0 - - blockchain: - 1: - - currencyType: 1 - name: USDT - - currencyType: 2 - name: MDX - - currencyType: 3 - name: DMT - 2: - - currencyType: 1 - name: USDT - 4: - - currencyType: 1 - name: USDT - - currencyType: 2 - name: MDX - - currencyType: 5 - name: ETH - - currencyType: 4 - name: CAKE - 5: - - currencyType: 1 - name: USDT - -# 采集开奖结果配置 -draw: - config: - configs: - - passType: 1 #链路 火币链 - currency: BTC #采集币种 BTC - url: https://api.huobi.pro/market/history/kline #采集地址 - period: 1min #采集周期 1min, 5min, 15min, 30min, ---- 60min, 4hour, 1day, 1mon, 1week, 1year - symbol: btcusdt #交易对 btcusdt, ethbtc - size: 120 #返回数据条数 1 - 2000 - - passType: 4 #链路 币安链 - currency: BTC #采集币种 BTC - url: https://api.binance.com/api/v3/klines #采集地址 - period: 1m #采集周期 #采集周期 1m, 3m, 5m, 15m, 30m, ---- 1h, 2h, 4h, 6h, 8h, 12h, 1d, 3d, 1w, 1M - symbol: BTCUSDT #交易对 - size: 120 #返回数据条数 1 - 1000 - -#该应用是否启用生产者 -rocketmq: - producer: - isOnOff: on - #发送同一类消息的设置为同一个group,保证唯一,默认不需要设置,rocketmq会使用ip@pid(pid代表jvm名字)作为唯一标示 - groupName: springboot-rocketmq-producer-capiltal - #mq的nameserver地址 - namesrvAddr: 120.77.145.59:9876 - #消息最大长度 默认1024*4(4M) - maxMessageSize: 4096 - #发送消息超时时间,默认3000 - sendMsgTimeout: 3000 - #发送消息失败重试次数,默认2 - retryTimesWhenSendFailed: 2 - consumer: - isOnOff: on - groupName: springboot-rocketmq-consumer-capiltal - #mq的nameserver地址 43.240.95.168 - namesrvAddr: 120.77.145.59:9876 - #该消费者订阅的主题和tags("*"号表示订阅该主题下所有的tags),格式:topic~tag1||tag2||tag3;topic2~*; - topics: capiltal-settlement-top~* - consumeThreadMin: 20 - consumeThreadMax: 64 - #设置一次消费消息的条数,默认为1条 - consumeMessageBatchMaxSize: 1 - -# Goole Auth -auth: - secret_size: 10 - seed: g8GjEvTbW5oVSV7avLBdwIHqGlUYNzKFI7izOF8GwLDVKs2m0QN7vxRs2im5MDaNCWGmcD2rvcZx - random_number_algorithm: SHA1PRNG - window_size: 0 - redis_google_auth_key: googelAuthKey - qr_create_prefix_url: https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=otpauth://totp/%s@%s?secret=%s - -#telegram: -# bot: -# username: capiltal_uat_bot -# token: 5008414161:AAHflrbo2v0DN8hpLhZAg5gC787yxFloWlk -# chatId: -665412272 \ No newline at end of file diff --git a/wjcy-system/src/main/resources/config/application.yml b/wjcy-system/src/main/resources/config/application.yml deleted file mode 100644 index bf5a2ad..0000000 --- a/wjcy-system/src/main/resources/config/application.yml +++ /dev/null @@ -1,56 +0,0 @@ -server: - port: 8008 - -spring: - cache: - type: redis - freemarker: - check-template-location: false - profiles: - active: dev - jackson: - time-zone: GMT+8 - data: - redis: - repositories: - enabled: false - - #配置 Jpa - jpa: - properties: - hibernate: - ddl-auto: none - dialect: org.hibernate.dialect.MySQL5InnoDBDialect - open-in-view: true - -# 开启security功能,配置访问账号密码 -management: - security: - enabled: true -security: - username: admin - userpassword: capiltal&xxs&123 - -task: - pool: - # 核心线程池大小 - core-pool-size: 10 - # 最大线程数 - max-pool-size: 30 - # 活跃时间 - keep-alive-seconds: 60 - # 队列容量 - queue-capacity: 50 - -#七牛云 -qiniu: - # 文件大小 /M - max-size: 15 - -#邮箱验证码有效时间/秒 -code: - expiration: 300 - -#密码加密传输,前端公钥加密,后端私钥解密 -rsa: - private_key: MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9pB6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZUBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3tTbklZkD2A== diff --git a/wjcy-system/src/main/resources/generator.properties b/wjcy-system/src/main/resources/generator.properties deleted file mode 100644 index 2ed9370..0000000 --- a/wjcy-system/src/main/resources/generator.properties +++ /dev/null @@ -1,27 +0,0 @@ -#数据库类型转Java类型 -tinyint=Integer -smallint=Integer -mediumint=Integer -int=Integer -integer=Integer - -bigint=Long - -float=Float - -double=Double - -decimal=BigDecimal - -bit=Boolean - -char=String -varchar=String -tinytext=String -text=String -mediumtext=String -longtext=String - -date=Timestamp -datetime=Timestamp -timestamp=Timestamp \ No newline at end of file diff --git a/wjcy-system/src/main/resources/ip2region/ip2region.db b/wjcy-system/src/main/resources/ip2region/ip2region.db deleted file mode 100644 index 43e1daf59a7bf34977adc6be925e5ea0d4a2cd22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6502265 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�ZN#(; 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

C^1@uO@)hd^>{0T4!hQQQK>{Yzv8p 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


_HHoRuj76gEAgH-a(cO`?q5PQoL;THC9}>5j*PH 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�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

_rNo4EzN@O)%Lp|vA>Y) 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

bfuHw;=s@#(B@U{;3*O!8>4Ag# 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

)Y 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%0Dwy@V8GUL#0h$LX}r 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%0AWqzSoOf~J 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 z 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
$vyv2b%B0gn50} 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 poA!{0h5=lHkr&T}$WyD(wCQ~3ZU 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
p+qarmFOlz9 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 #-BH_eyuy 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