1
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -16,7 +16,8 @@ out/
|
||||
/ruoyi-common/target/
|
||||
/ruoyi-system/target/
|
||||
/ruoyi-quartz/target/
|
||||
/ruoyi-generator/target/s
|
||||
/ruoyi-generator/target/
|
||||
/ruoyi-framework/target/
|
||||
/ruoyi-admin/target/
|
||||
/erp_client_sb/target/
|
||||
target /
|
||||
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@@ -9,5 +9,5 @@
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="ms-21" project-jdk-type="JavaSDK" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK" />
|
||||
</project>
|
||||
381
.idea/workspace.xml
generated
381
.idea/workspace.xml
generated
@@ -5,11 +5,354 @@
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="71d19dd6-7472-4ebf-b309-b7afee3f99de" name="更改" comment="1">
|
||||
<change beforePath="$PROJECT_DIR$/.gitignore" beforeDir="false" afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/misc.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/erp_client_sb/src/main/java/com/tashow/erp/service/impl/Alibaba1688ServiceImpl.java" beforeDir="false" afterPath="$PROJECT_DIR$/erp_client_sb/src/main/java/com/tashow/erp/service/impl/Alibaba1688ServiceImpl.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/data/erp-cache.db" beforeDir="false" afterPath="$PROJECT_DIR$/data/erp-cache.db" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/data/erp-cache.db-shm" beforeDir="false" afterPath="$PROJECT_DIR$/data/erp-cache.db-shm" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/data/erp-cache.db-wal" beforeDir="false" afterPath="$PROJECT_DIR$/data/erp-cache.db-wal" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/electron-vue-template/src/renderer/App.vue" beforeDir="false" afterPath="$PROJECT_DIR$/electron-vue-template/src/renderer/App.vue" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/electron-vue-template/src/renderer/components/amazon/AmazonDashboard.vue" beforeDir="false" afterPath="$PROJECT_DIR$/electron-vue-template/src/renderer/components/amazon/AmazonDashboard.vue" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/electron-vue-template/src/renderer/components/rakuten/RakutenDashboard.vue" beforeDir="false" afterPath="$PROJECT_DIR$/electron-vue-template/src/renderer/components/rakuten/RakutenDashboard.vue" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/electron-vue-template/src/renderer/components/zebra/ZebraDashboard.vue" beforeDir="false" afterPath="$PROJECT_DIR$/electron-vue-template/src/renderer/components/zebra/ZebraDashboard.vue" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/erp_client_sb/src/main/java/com/tashow/erp/controller/AuthController.java" beforeDir="false" afterPath="$PROJECT_DIR$/erp_client_sb/src/main/java/com/tashow/erp/controller/AuthController.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/erp_client_sb/src/main/java/com/tashow/erp/controller/RakutenController.java" beforeDir="false" afterPath="$PROJECT_DIR$/erp_client_sb/src/main/java/com/tashow/erp/controller/RakutenController.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/erp_client_sb/src/main/java/com/tashow/erp/model/RakutenProduct.java" beforeDir="false" afterPath="$PROJECT_DIR$/erp_client_sb/src/main/java/com/tashow/erp/model/RakutenProduct.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/erp_client_sb/src/main/java/com/tashow/erp/service/IAuthService.java" beforeDir="false" afterPath="$PROJECT_DIR$/erp_client_sb/src/main/java/com/tashow/erp/service/IAuthService.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/erp_client_sb/src/main/java/com/tashow/erp/test/SeleniumWithProfile.java" beforeDir="false" afterPath="$PROJECT_DIR$/erp_client_sb/src/main/java/com/tashow/erp/test/SeleniumWithProfile.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/erp_client_sb/src/main/java/com/tashow/erp/utils/PersistentDriverManager.java" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/erp_client_sb/src/main/java/com/tashow/erp/utils/StealthSelenium.java" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/erp_client_sb/src/main/java/com/tashow/erp/utils/RakutenProxyUtil.java" beforeDir="false" afterPath="$PROJECT_DIR$/erp_client_sb/src/main/java/com/tashow/erp/utils/RakutenProxyUtil.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/pom.xml" beforeDir="false" afterPath="$PROJECT_DIR$/pom.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/AdvancedSliderCaptchaHandler.java" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ClientAccountController.java" beforeDir="false" afterPath="$PROJECT_DIR$/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ClientAccountController.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ClientMonitorController.java" beforeDir="false" afterPath="$PROJECT_DIR$/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ClientMonitorController.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-admin/src/main/java/com/ruoyi/web/service/IClientMonitorService.java" beforeDir="false" afterPath="$PROJECT_DIR$/ruoyi-admin/src/main/java/com/ruoyi/web/service/IClientMonitorService.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/ClientMonitorServiceImpl.java" beforeDir="false" afterPath="$PROJECT_DIR$/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/ClientMonitorServiceImpl.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/api.properties" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/annotation/Anonymous.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/annotation/DataScope.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/annotation/DataSource.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/annotation/Excel$ColumnType.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/annotation/Excel$Type.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/annotation/Excel.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/annotation/Excels.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/annotation/Log.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/annotation/RateLimiter.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/annotation/RepeatSubmit.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/annotation/Sensitive.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/config/FileUploadConfig.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/config/Qiniu.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/config/RuoYiConfig.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/config/serializer/SensitiveJsonSerializer.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/constant/CacheConstants.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/constant/Constants.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/constant/GenConstants.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/constant/HttpStatus.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/constant/ScheduleConstants$Status.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/constant/ScheduleConstants.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/constant/UserConstants.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/core/controller/BaseController$1.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/core/controller/BaseController.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/core/domain/AjaxResult.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/core/domain/BaseEntity.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/core/domain/R.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/core/domain/TreeEntity.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/core/domain/TreeSelect.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/core/domain/entity/SysDept.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/core/domain/entity/SysDictData.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/core/domain/entity/SysDictType.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/core/domain/entity/SysMenu.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/core/domain/entity/SysRole.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/core/domain/entity/SysUser.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/core/domain/model/LoginBody.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/core/domain/model/LoginUser.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/core/domain/model/RegisterBody.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/core/page/PageDomain.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/core/page/TableDataInfo.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/core/page/TableSupport.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/core/redis/RedisCache.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/core/text/CharsetKit.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/core/text/Convert.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/core/text/StrFormatter.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/enums/BusinessStatus.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/enums/BusinessType.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/enums/DataSourceType.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/enums/DesensitizedType.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/enums/HttpMethod.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/enums/LimitType.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/enums/OperatorType.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/enums/QiniuZone.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/enums/UserStatus.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/exception/DemoModeException.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/exception/GlobalException.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/exception/ServiceException.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/exception/UtilException.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/exception/base/BaseException.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/exception/file/FileException.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/exception/file/FileSizeLimitExceededException.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/exception/file/FileUploadException.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/exception/file/InvalidExtensionException$InvalidFlashExtensionException.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/exception/file/InvalidExtensionException$InvalidImageExtensionException.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/exception/file/InvalidExtensionException$InvalidMediaExtensionException.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/exception/file/InvalidExtensionException$InvalidVideoExtensionException.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/exception/file/InvalidExtensionException.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/exception/job/TaskException$Code.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/exception/job/TaskException.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/exception/user/BlackListException.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/exception/user/CaptchaException.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/exception/user/CaptchaExpireException.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/exception/user/UserException.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/exception/user/UserNotExistsException.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/exception/user/UserPasswordNotMatchException.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/filter/PropertyPreExcludeFilter.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/filter/RepeatableFilter.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/filter/RepeatedlyRequestWrapper$1.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/filter/RepeatedlyRequestWrapper.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/filter/XssFilter.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/filter/XssHttpServletRequestWrapper$1.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/filter/XssHttpServletRequestWrapper.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/Arith.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/DateUtils.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/DesensitizedUtil.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/DictUtils.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/ExceptionUtil.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/LogUtils.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/MessageUtils.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/PageUtils.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/SecurityUtils.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/ServletUtils.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/StringUtils.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/Threads.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/bean/BeanUtils.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/bean/BeanValidators.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/file/FileTypeUtils.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/file/FileUploadUtils.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/file/FileUtils.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/file/ImageUtils.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/file/MimeTypeUtils.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/html/EscapeUtil.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/html/HTMLFilter.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/http/HttpHelper.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/http/HttpUtils$TrustAnyHostnameVerifier.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/http/HttpUtils$TrustAnyTrustManager.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/http/HttpUtils.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/ip/AddressUtils.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/ip/IpUtils.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/poi/ExcelHandlerAdapter.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/poi/ExcelUtil.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/reflect/ReflectUtils.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/sign/Base64.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/sign/Md5Utils.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/spring/SpringUtils.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/sql/SqlUtil.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/uuid/IdUtils.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/uuid/Seq.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/uuid/UUID$Holder.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/utils/uuid/UUID.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/xss/Xss.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/com/ruoyi/common/xss/XssValidator.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/classes/shop.properties" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-common/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/aspectj/DataScopeAspect.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/aspectj/DataSourceAspect.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/aspectj/LogAspect.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/aspectj/RateLimiterAspect.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/config/ApplicationConfig.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/config/CaptchaConfig.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/config/CorsInterceptor.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/config/DruidConfig$1.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/config/DruidConfig.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/config/FilterConfig.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/config/I18nConfig.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/config/InterceptorConfig.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/config/KaptchaTextCreator.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/config/MyBatisConfig.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/config/RedisConfig.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/config/ResourcesConfig.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/config/SecurityConfig.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/config/ServerConfig.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/config/ThreadPoolConfig$1.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/config/ThreadPoolConfig.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/config/properties/DruidProperties.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/config/properties/PermitAllUrlProperties.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/datasource/DynamicDataSource.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/manager/AsyncManager.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/manager/ShutdownManager.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/manager/factory/AsyncFactory$1.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/manager/factory/AsyncFactory$2.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/manager/factory/AsyncFactory.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/security/context/AuthenticationContextHolder.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/security/context/PermissionContextHolder.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/web/domain/Server.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/web/domain/server/Cpu.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/web/domain/server/Jvm.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/web/domain/server/Mem.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/web/domain/server/Sys.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/web/domain/server/SysFile.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/web/exception/GlobalExceptionHandler.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/web/service/PermissionService.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/web/service/SysLoginService.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/web/service/SysPasswordService.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/web/service/SysPermissionService.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/web/service/SysRegisterService.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/web/service/TokenService.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/classes/com/ruoyi/framework/web/service/UserDetailsServiceImpl.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-framework/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/classes/com/ruoyi/generator/config/GenConfig.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/classes/com/ruoyi/generator/controller/GenController.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/classes/com/ruoyi/generator/domain/GenTable.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/classes/com/ruoyi/generator/domain/GenTableColumn.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/classes/com/ruoyi/generator/mapper/GenTableColumnMapper.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/classes/com/ruoyi/generator/mapper/GenTableMapper.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/classes/com/ruoyi/generator/service/GenTableColumnServiceImpl.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/classes/com/ruoyi/generator/service/GenTableServiceImpl.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/classes/com/ruoyi/generator/service/IGenTableColumnService.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/classes/com/ruoyi/generator/service/IGenTableService.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/classes/com/ruoyi/generator/util/GenUtils.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/classes/com/ruoyi/generator/util/VelocityInitializer.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/classes/com/ruoyi/generator/util/VelocityUtils.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/classes/generator.yml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/classes/mapper/generator/GenTableColumnMapper.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/classes/mapper/generator/GenTableMapper.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/classes/vm/java/controller.java.vm" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/classes/vm/java/domain.java.vm" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/classes/vm/java/mapper.java.vm" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/classes/vm/java/service.java.vm" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/classes/vm/java/serviceImpl.java.vm" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/classes/vm/java/sub-domain.java.vm" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/classes/vm/js/api.js.vm" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/classes/vm/sql/sql.vm" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/classes/vm/vue/index-tree.vue.vm" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/classes/vm/vue/index.vue.vm" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/classes/vm/vue/v3/index-tree.vue.vm" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/classes/vm/vue/v3/index.vue.vm" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/classes/vm/xml/mapper.xml.vm" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-generator/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-quartz/target/classes/com/ruoyi/quartz/controller/SysJobController.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-quartz/target/classes/com/ruoyi/quartz/controller/SysJobLogController.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-quartz/target/classes/com/ruoyi/quartz/domain/SysJob.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-quartz/target/classes/com/ruoyi/quartz/domain/SysJobLog.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-quartz/target/classes/com/ruoyi/quartz/mapper/SysJobLogMapper.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-quartz/target/classes/com/ruoyi/quartz/mapper/SysJobMapper.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-quartz/target/classes/com/ruoyi/quartz/service/ISysJobLogService.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-quartz/target/classes/com/ruoyi/quartz/service/ISysJobService.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-quartz/target/classes/com/ruoyi/quartz/service/impl/SysJobLogServiceImpl.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-quartz/target/classes/com/ruoyi/quartz/service/impl/SysJobServiceImpl.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-quartz/target/classes/com/ruoyi/quartz/task/RyTask.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-quartz/target/classes/com/ruoyi/quartz/util/AbstractQuartzJob.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-quartz/target/classes/com/ruoyi/quartz/util/CronUtils.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-quartz/target/classes/com/ruoyi/quartz/util/JobInvokeUtil.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-quartz/target/classes/com/ruoyi/quartz/util/QuartzDisallowConcurrentExecution.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-quartz/target/classes/com/ruoyi/quartz/util/QuartzJobExecution.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-quartz/target/classes/com/ruoyi/quartz/util/ScheduleUtils.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-quartz/target/classes/mapper/quartz/SysJobLogMapper.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-quartz/target/classes/mapper/quartz/SysJobMapper.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-quartz/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-quartz/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/src/main/java/com/ruoyi/system/mapper/ClientMonitorMapper.java" beforeDir="false" afterPath="$PROJECT_DIR$/ruoyi-system/src/main/java/com/ruoyi/system/mapper/ClientMonitorMapper.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/src/main/resources/mapper/system/ClientMonitorMapper.xml" beforeDir="false" afterPath="$PROJECT_DIR$/ruoyi-system/src/main/resources/mapper/system/ClientMonitorMapper.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/domain/ClientAccount.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/domain/ClientAuthInfo.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/domain/ClientAuthKey.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/domain/ClientDataReport.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/domain/ClientDevice.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/domain/ClientErrorReport.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/domain/ClientEventLog.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/domain/ClientInfo.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/domain/RefreshToken.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/domain/SysCache.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/domain/SysConfig.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/domain/SysLogininfor.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/domain/SysNotice.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/domain/SysOperLog.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/domain/SysPost.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/domain/SysRoleDept.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/domain/SysRoleMenu.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/domain/SysUserOnline.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/domain/SysUserPost.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/domain/SysUserRole.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/domain/vo/MetaVo.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/domain/vo/RouterVo.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/mapper/ClientAccountMapper.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/mapper/ClientDeviceMapper.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/mapper/ClientEventLogMapper.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/mapper/ClientInfoMapper.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/mapper/ClientMonitorMapper.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/mapper/RefreshTokenMapper.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/mapper/SysConfigMapper.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/mapper/SysDeptMapper.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/mapper/SysDictDataMapper.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/mapper/SysDictTypeMapper.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/mapper/SysLogininforMapper.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/mapper/SysMenuMapper.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/mapper/SysNoticeMapper.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/mapper/SysOperLogMapper.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/mapper/SysPostMapper.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/mapper/SysRoleDeptMapper.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/mapper/SysRoleMapper.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/mapper/SysRoleMenuMapper.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/mapper/SysUserMapper.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/mapper/SysUserPostMapper.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/mapper/SysUserRoleMapper.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/service/ISysConfigService.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/service/ISysDeptService.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/service/ISysDictDataService.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/service/ISysDictTypeService.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/service/ISysLogininforService.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/service/ISysMenuService.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/service/ISysNoticeService.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/service/ISysOperLogService.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/service/ISysPostService.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/service/ISysRoleService.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/service/ISysUserOnlineService.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/service/ISysUserService.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/service/impl/SysConfigServiceImpl.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/service/impl/SysDeptServiceImpl.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/service/impl/SysDictDataServiceImpl.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/service/impl/SysLogininforServiceImpl.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/service/impl/SysMenuServiceImpl.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/service/impl/SysNoticeServiceImpl.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/service/impl/SysOperLogServiceImpl.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/service/impl/SysPostServiceImpl.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/service/impl/SysRoleServiceImpl.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/com/ruoyi/system/service/impl/SysUserServiceImpl.class" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/mapper/system/ClientAccountMapper.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/mapper/system/ClientDeviceMapper.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/mapper/system/ClientEventLogMapper.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/mapper/system/ClientInfoMapper.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/mapper/system/ClientMonitorMapper.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/mapper/system/ClientMonitorMapper.xml.bak" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/mapper/system/RefreshTokenMapper.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/mapper/system/SysConfigMapper.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/mapper/system/SysDeptMapper.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/mapper/system/SysDictDataMapper.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/mapper/system/SysDictTypeMapper.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/mapper/system/SysLogininforMapper.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/mapper/system/SysMenuMapper.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/mapper/system/SysNoticeMapper.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/mapper/system/SysOperLogMapper.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/mapper/system/SysPostMapper.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/mapper/system/SysRoleDeptMapper.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/mapper/system/SysRoleMapper.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/mapper/system/SysRoleMenuMapper.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/mapper/system/SysUserMapper.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/mapper/system/SysUserPostMapper.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/classes/mapper/system/SysUserRoleMapper.xml" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/ruoyi-system/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst" beforeDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
@@ -48,6 +391,7 @@
|
||||
"Spring Boot.ErpClientSbApplication.executor": "Debug",
|
||||
"Spring Boot.RuoYiApplication.executor": "Debug",
|
||||
"git-widget-placeholder": "master",
|
||||
"last_opened_file_path": "C:/Users/ZiJIe/Desktop/wox/RuoYi-Vue",
|
||||
"node.js.detected.package.eslint": "true",
|
||||
"node.js.detected.package.tslint": "true",
|
||||
"node.js.selected.package.eslint": "(autodetect)",
|
||||
@@ -61,6 +405,11 @@
|
||||
<component name="ReactorSettings">
|
||||
<option name="notificationShown" value="true" />
|
||||
</component>
|
||||
<component name="RecentsManager">
|
||||
<key name="CopyFile.RECENT_KEYS">
|
||||
<recent name="C:\Users\ZiJIe\Desktop\wox\RuoYi-Vue" />
|
||||
</key>
|
||||
</component>
|
||||
<component name="RunDashboard">
|
||||
<option name="configurationTypes">
|
||||
<set>
|
||||
@@ -94,6 +443,10 @@
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
<list>
|
||||
<item itemvalue="Spring Boot.ErpClientSbApplication" />
|
||||
<item itemvalue="Spring Boot.RuoYiApplication" />
|
||||
</list>
|
||||
</component>
|
||||
<component name="SharedIndexes">
|
||||
<attachedChunks>
|
||||
@@ -225,12 +578,31 @@
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1758619552979</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="15" />
|
||||
<task id="LOCAL-00015" summary="1">
|
||||
<option name="closed" value="true" />
|
||||
<created>1758683139068</created>
|
||||
<option name="number" value="00015" />
|
||||
<option name="presentableId" value="LOCAL-00015" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1758683139068</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="16" />
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
<option name="version" value="3" />
|
||||
</component>
|
||||
<component name="Vcs.Log.Tabs.Properties">
|
||||
<option name="TAB_STATES">
|
||||
<map>
|
||||
<entry key="MAIN">
|
||||
<value>
|
||||
<State />
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</component>
|
||||
<component name="VcsManagerConfiguration">
|
||||
<MESSAGE value="1" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="1" />
|
||||
@@ -241,7 +613,6 @@
|
||||
<line-breakpoint enabled="true" type="javascript">
|
||||
<url>file://$PROJECT_DIR$/electron-vue-template/src/renderer/components/common/AccountManager.vue</url>
|
||||
<line>34</line>
|
||||
<properties lambdaOrdinal="-1" />
|
||||
<option name="timeStamp" value="8" />
|
||||
</line-breakpoint>
|
||||
</breakpoints>
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -150,6 +150,12 @@ async function handleLoginSuccess(data: { token: string; permissions?: string })
|
||||
}
|
||||
|
||||
async function logout() {
|
||||
|
||||
const token = await authApi.getToken()
|
||||
if (token) {
|
||||
await authApi.logout(token)
|
||||
}
|
||||
|
||||
await authApi.deleteTokenCache()
|
||||
// 清理前端状态
|
||||
isAuthenticated.value = false
|
||||
@@ -158,7 +164,8 @@ async function logout() {
|
||||
showAuthDialog.value = true
|
||||
showDeviceDialog.value = false
|
||||
|
||||
// 关闭SSE连接
|
||||
// 关闭SSE连接`-+++++++
|
||||
|
||||
SSEManager.disconnect()
|
||||
}
|
||||
|
||||
|
||||
@@ -269,7 +269,7 @@ onMounted(async () => {
|
||||
<div class="body-layout">
|
||||
<!-- 左侧步骤栏 -->
|
||||
<aside class="steps-sidebar">
|
||||
<div class="steps-title">查询步骤:</div>
|
||||
<div class="steps-title">操作流程:</div>
|
||||
<div class="steps-flow">
|
||||
<!-- 1 -->
|
||||
<div class="flow-item">
|
||||
@@ -408,7 +408,7 @@ onMounted(async () => {
|
||||
.main-container { background: #fff; border-radius: 4px; padding: 15px; box-shadow: 0 2px 4px rgba(0,0,0,0.05); height: 100%; display: flex; flex-direction: column; }
|
||||
.body-layout { display: flex; gap: 12px; height: 100%; }
|
||||
.steps-sidebar { width: 220px; background: #fff; border: 1px solid #ebeef5; border-radius: 6px; padding: 10px; height: 100%; flex-shrink: 0; }
|
||||
.steps-title { font-size: 14px; font-weight: 600; color: #303133; margin-bottom: 8px; }
|
||||
.steps-title { font-size: 14px; font-weight: 600; color: #303133; margin-bottom: 8px; text-align: left; }
|
||||
.steps-flow { position: relative; }
|
||||
.steps-flow:before { content: ''; position: absolute; left: 12px; top: 0; bottom: 0; width: 2px; background: #e5e7eb; }
|
||||
.flow-item { position: relative; display: grid; grid-template-columns: 24px 1fr; gap: 10px; padding: 8px 0; }
|
||||
|
||||
@@ -30,19 +30,6 @@ const progressStarted = ref(false)
|
||||
const progressPercentage = ref(0)
|
||||
const totalProducts = ref(0)
|
||||
const processedProducts = ref(0)
|
||||
// 进度头部文案(展示在进度条上方)
|
||||
const successCount = computed(() =>
|
||||
allProducts.value.filter(
|
||||
(p: any) => p && p.mapRecognitionLink && String(p.mapRecognitionLink).trim() !== ''
|
||||
).length
|
||||
)
|
||||
const progressHeader = computed(() => {
|
||||
if (!progressStarted.value) return ''
|
||||
if (progressPercentage.value >= 100) {
|
||||
return `数据获取完成(成功获取 ${successCount.value} 个) 左侧操作栏点击“导出数据”按钮,可导出为Excel文件`
|
||||
}
|
||||
return '数据获取中'
|
||||
})
|
||||
|
||||
// 左侧步骤栏进度
|
||||
const activeStep = computed(() => {
|
||||
@@ -79,20 +66,33 @@ function openRakutenUpload() {
|
||||
uploadInputRef.value?.click()
|
||||
}
|
||||
|
||||
function parseSkuPrices(product: any) {
|
||||
if (!product.skuPrice) return []
|
||||
function parseSkuPrices(input: any) {
|
||||
try {
|
||||
let skuStr = product.skuPrice
|
||||
if (typeof skuStr === 'string') {
|
||||
skuStr = skuStr.replace(/(\d+(?:\.\d+)?):"/g, '"$1":"')
|
||||
skuStr = JSON.parse(skuStr)
|
||||
let skuSource: any = input
|
||||
if (input && typeof input === 'object') {
|
||||
skuSource = input.skuPriceJson ?? input.skuPrice
|
||||
}
|
||||
return Object.keys(skuStr).map(p => parseFloat(p)).filter(n => !isNaN(n)).sort((a, b) => a - b)
|
||||
if (!skuSource) return []
|
||||
if (typeof skuSource === 'string') {
|
||||
skuSource = skuSource.replace(/(\d+(?:\.\d+)?):"/g, '"$1":"')
|
||||
skuSource = JSON.parse(skuSource)
|
||||
}
|
||||
if (!skuSource || typeof skuSource !== 'object') return []
|
||||
return Object.keys(skuSource)
|
||||
.map(p => parseFloat(p))
|
||||
.filter(n => !isNaN(n))
|
||||
.sort((a, b) => a - b)
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
function needsSearch(product: any) {
|
||||
const hasParsedPrices = Array.isArray(product?.skuPrices) && product.skuPrices.length > 0
|
||||
const hasRawPrices = !!(product?.skuPriceJson || product?.skuPrice)
|
||||
return !(hasParsedPrices || hasRawPrices)
|
||||
}
|
||||
|
||||
async function loadLatest() {
|
||||
const resp = await rakutenApi.getLatestProducts()
|
||||
allProducts.value = (resp.products || []).map(p => ({...p, skuPrices: parseSkuPrices(p)}))
|
||||
@@ -101,16 +101,18 @@ async function loadLatest() {
|
||||
|
||||
async function searchProductInternal(product: any) {
|
||||
if (!product || !product.imgUrl) return
|
||||
if (product.mapRecognitionLink && String(product.mapRecognitionLink).trim() !== '') return
|
||||
if (!needsSearch(product)) return
|
||||
const res = await rakutenApi.search1688(product.imgUrl, currentBatchId.value)
|
||||
const data = res
|
||||
const skuJson = (data as any)?.skuPriceJson ?? (data as any)?.skuPrice
|
||||
Object.assign(product, {
|
||||
mapRecognitionLink: data.mapRecognitionLink,
|
||||
freight: data.freight,
|
||||
median: data.median,
|
||||
weight: data.weight,
|
||||
skuPrice: data.skuPrice,
|
||||
skuPrices: parseSkuPrices(data),
|
||||
skuPriceJson: skuJson,
|
||||
skuPrice: skuJson,
|
||||
skuPrices: parseSkuPrices({ skuPriceJson: skuJson }),
|
||||
image1688Url: data.mapRecognitionLink,
|
||||
detailUrl1688: data.mapRecognitionLink,
|
||||
})
|
||||
@@ -163,36 +165,9 @@ async function onDrop(e: DragEvent) {
|
||||
await processFile(file)
|
||||
}
|
||||
|
||||
async function searchSingleShop() {
|
||||
const shop = singleShopName.value.trim()
|
||||
if (!shop) return
|
||||
|
||||
// 重置进度与状态
|
||||
progressStarted.value = true
|
||||
progressPercentage.value = 0
|
||||
totalProducts.value = 0
|
||||
processedProducts.value = 0
|
||||
loading.value = true
|
||||
tableLoading.value = true
|
||||
currentBatchId.value = `RAKUTEN_${Date.now()}`
|
||||
try {
|
||||
const resp = await rakutenApi.getProducts({shopName: shop, batchId: currentBatchId.value})
|
||||
allProducts.value = (resp.products || []).filter((p: any) => p.originalShopName === shop).map(p => ({ ...p, skuPrices: parseSkuPrices(p) }))
|
||||
statusType.value = 'info'
|
||||
statusMessage.value = `店铺 ${shop} 共 ${allProducts.value.length} 条,点击“获取数据”开始识图`
|
||||
singleShopName.value = ''
|
||||
} catch (e: any) {
|
||||
statusMessage.value = e?.message || '查询失败'
|
||||
statusType.value = 'error'
|
||||
} finally {
|
||||
loading.value = false
|
||||
tableLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 点击“获取数据”触发识图
|
||||
// 点击“获取数据
|
||||
async function handleStartSearch() {
|
||||
// 如果存在待解析文件,先请求后端解析再进入识图
|
||||
if (pendingFile.value) {
|
||||
try {
|
||||
loading.value = true
|
||||
@@ -216,10 +191,19 @@ async function handleStartSearch() {
|
||||
tableLoading.value = false
|
||||
}
|
||||
}
|
||||
const items = allProducts.value.filter(p => p && p.imgUrl && !p.mapRecognitionLink)
|
||||
const items = allProducts.value.filter(p => p && p.imgUrl && needsSearch(p))
|
||||
if (allProducts.value.length > 0 && items.length === 0) {
|
||||
progressStarted.value = true
|
||||
totalProducts.value = allProducts.value.length
|
||||
processedProducts.value = totalProducts.value
|
||||
progressPercentage.value = 100
|
||||
statusType.value = 'success'
|
||||
statusMessage.value = ''
|
||||
return
|
||||
}
|
||||
if (items.length === 0) {
|
||||
statusType.value = 'warning'
|
||||
statusMessage.value = '没有可识图的商品,请先导入或查询店铺'
|
||||
statusMessage.value = '没有可处理的商品,请先导入或查询店铺'
|
||||
return
|
||||
}
|
||||
await startBatch1688Search(items)
|
||||
@@ -235,7 +219,7 @@ function stopTask() {
|
||||
}
|
||||
|
||||
async function startBatch1688Search(products: any[]) {
|
||||
const items = (products || []).filter(p => p && p.imgUrl && !p.mapRecognitionLink)
|
||||
const items = (products || []).filter(p => p && p.imgUrl && needsSearch(p))
|
||||
if (items.length === 0) {
|
||||
progressPercentage.value = 100
|
||||
statusType.value = 'success'
|
||||
@@ -319,7 +303,7 @@ onMounted(loadLatest)
|
||||
<div class="body-layout">
|
||||
<!-- 左侧步骤栏 -->
|
||||
<aside class="steps-sidebar">
|
||||
<div class="steps-title">查询步骤:</div>
|
||||
<div class="steps-title">操作流程:</div>
|
||||
|
||||
<div class="steps-flow">
|
||||
<!-- Step 1 导入乐天店铺 -->
|
||||
@@ -399,12 +383,8 @@ onMounted(loadLatest)
|
||||
<!-- 数据显示区域 -->
|
||||
<div class="table-container">
|
||||
<div class="table-section">
|
||||
<!-- 表格上方进度条(移动到表格容器内部) -->
|
||||
<!-- 表格上方进度条 -->
|
||||
<div v-if="progressStarted" class="progress-head">
|
||||
<div class="progress-title">
|
||||
<span v-if="progressPercentage>=100" class="ok-badge">●</span>
|
||||
<span class="title-text">{{ progressHeader }}</span>
|
||||
</div>
|
||||
<div class="progress-section">
|
||||
<div class="progress-box">
|
||||
<div class="progress-container">
|
||||
@@ -519,7 +499,7 @@ onMounted(loadLatest)
|
||||
|
||||
.body-layout { display: flex; gap: 12px; height: 100%; }
|
||||
.steps-sidebar { width: 220px; background: #fff; border: 1px solid #ebeef5; border-radius: 6px; padding: 10px; height: 100%; flex-shrink: 0; }
|
||||
.steps-title { font-size: 14px; font-weight: 600; color: #303133; margin-bottom: 8px; }
|
||||
.steps-title { font-size: 14px; font-weight: 600; color: #303133; margin-bottom: 8px; text-align: left; }
|
||||
|
||||
/* 卡片式步骤,与示例一致 */
|
||||
.steps-flow { position: relative; }
|
||||
@@ -568,43 +548,12 @@ onMounted(loadLatest)
|
||||
.btn-blue:disabled { background: #a6c8ff; border-color: #a6c8ff; color: #fff; }
|
||||
.w100 { width: 100%; }
|
||||
.steps-sidebar :deep(.el-button + .el-button) { margin-left: 0; }
|
||||
|
||||
.import-section {
|
||||
margin-bottom: 10px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.import-controls {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
gap: 20px;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.single-input {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
|
||||
.action-buttons {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.progress-section { margin: 12px 12px 6px 12px; }
|
||||
.progress-section { margin: 0px 12px 0px 12px; }
|
||||
.progress-box { padding: 4px 0; }
|
||||
.progress-container { display: flex; align-items: center; gap: 8px; }
|
||||
.progress-bar { flex: 1; height: 6px; background: #e3eeff; border-radius: 999px; overflow: hidden; }
|
||||
.progress-fill { height: 100%; background: #1677FF; border-radius: 999px; transition: width 0.3s ease; }
|
||||
.progress-text { font-size: 13px; color: #1677FF; font-weight: 500; min-width: 44px; text-align: right; }
|
||||
.progress-head { padding: 8px 12px 0 12px; }
|
||||
.progress-title { display:flex; align-items:center; gap:8px; color:#606266; font-size: 13px; margin-bottom: 6px; }
|
||||
.progress-title .ok-badge { color: #52c41a; font-size: 12px; }
|
||||
.progress-title .title-text { color:#303133; font-weight:600; }
|
||||
|
||||
.current-status {
|
||||
font-size: 12px;
|
||||
|
||||
@@ -7,7 +7,7 @@ type Shop = { id: string; shopName: string }
|
||||
|
||||
const accounts = ref<BanmaAccount[]>([])
|
||||
const accountId = ref<number>()
|
||||
const isCollapsed = ref(false)
|
||||
// 收起功能移除
|
||||
|
||||
const shopList = ref<Shop[]>([])
|
||||
const selectedShops = ref<string[]>([])
|
||||
@@ -220,10 +220,9 @@ async function removeCurrentAccount() {
|
||||
<template>
|
||||
<div class="zebra-root">
|
||||
<div class="layout">
|
||||
<aside :class="['aside', { collapsed: isCollapsed }]">
|
||||
<aside class="aside">
|
||||
<div class="aside-header">
|
||||
<span>操作流程</span>
|
||||
<el-button link @click="isCollapsed = !isCollapsed">{{ isCollapsed ? '展开' : '收起' }}</el-button>
|
||||
</div>
|
||||
<div class="aside-steps">
|
||||
<section class="step step-accounts">
|
||||
@@ -428,7 +427,7 @@ export default {
|
||||
.layout { background: #fff; border-radius: 4px; padding: 12px; box-shadow: 0 2px 4px rgba(0,0,0,0.05); height: 100%; display: grid; grid-template-columns: 220px 1fr; gap: 12px; }
|
||||
.aside { border: 1px solid #ebeef5; border-radius: 4px; padding: 10px; display: flex; flex-direction: column; transition: width 0.2s ease; }
|
||||
.aside.collapsed { width: 56px; overflow: hidden; }
|
||||
.aside-header { display: flex; justify-content: space-between; align-items: center; font-weight: 600; color: #606266; margin-bottom: 8px; }
|
||||
.aside-header { display: flex; justify-content: flex-start; align-items: center; font-weight: 600; color: #606266; margin-bottom: 8px; }
|
||||
.aside-steps { position: relative; }
|
||||
.step { display: grid; grid-template-columns: 24px 1fr; gap: 10px; position: relative; padding: 8px 0; }
|
||||
.step + .step { border-top: 1px dashed #ebeef5; }
|
||||
|
||||
@@ -67,6 +67,12 @@ public class AuthController {
|
||||
return ResponseEntity.ok(result);
|
||||
}
|
||||
|
||||
@PostMapping("/logout")
|
||||
public ResponseEntity<?> logout(@RequestBody Map<String, Object> data) {
|
||||
authService.logout();
|
||||
return ResponseEntity.ok(Map.of("code", 0, "message", "退出成功"));
|
||||
}
|
||||
|
||||
@GetMapping("/check-username")
|
||||
public ResponseEntity<?> checkUsername(@RequestParam String username) {
|
||||
if (username == null || username.trim().isEmpty()) {
|
||||
|
||||
@@ -79,12 +79,8 @@ public class RakutenController {
|
||||
log.info("采集完成: {}, 数量: {}", currentShopName, fresh.size());
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 处理新采集的数据,存储并生成 sessionId
|
||||
List<RakutenProduct> newProducts = allProducts.stream().filter(p -> !skippedShops.contains(p.getOriginalShopName())).toList();
|
||||
|
||||
if (!newProducts.isEmpty()) {
|
||||
// 使用已有 sessionId 保存
|
||||
rakutenCacheService.saveProductsWithSessionId(newProducts, batchId);
|
||||
}
|
||||
// 4. 上报缓存数据使用情况
|
||||
|
||||
@@ -29,7 +29,7 @@ public class RakutenProduct {
|
||||
private Double freight;
|
||||
private Double median;
|
||||
private String weight;
|
||||
|
||||
private String skuPriceJson;
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RakutenProduct{" +
|
||||
|
||||
@@ -32,6 +32,8 @@ public interface IAuthService {
|
||||
*/
|
||||
String getClientId();
|
||||
|
||||
void logout();
|
||||
|
||||
/**
|
||||
* 验证token
|
||||
*/
|
||||
|
||||
@@ -6,7 +6,6 @@ import java.util.regex.Pattern;
|
||||
|
||||
public class SeleniumWithProfile {
|
||||
private static final Pattern WEIGHT_PATTERN = Pattern.compile("\"(?:unitWeight|weight)\":(\\d+(?:\\.\\d+)?)");
|
||||
|
||||
public static void main(String[] args) {
|
||||
String uuid = "";
|
||||
try {
|
||||
|
||||
1
pom.xml
1
pom.xml
@@ -229,7 +229,6 @@
|
||||
<module>ruoyi-quartz</module>
|
||||
<module>ruoyi-generator</module>
|
||||
<module>ruoyi-common</module>
|
||||
<module>untitled</module>
|
||||
</modules>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
|
||||
@@ -1,394 +0,0 @@
|
||||
package com.ruoyi.web.controller.common;
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.interactions.Actions;
|
||||
import org.openqa.selenium.support.ui.WebDriverWait;
|
||||
import org.openqa.selenium.support.ui.ExpectedConditions;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* 高级滑块验证码处理器
|
||||
* 支持多种滑块类型和重试机制
|
||||
*/
|
||||
public class AdvancedSliderCaptchaHandler {
|
||||
private final WebDriver driver;
|
||||
private final WebDriverWait wait;
|
||||
private final Actions actions;
|
||||
private final Random random;
|
||||
private static final int MAX_RETRY_ATTEMPTS = 3;
|
||||
private static final Duration WAIT_TIMEOUT = Duration.ofSeconds(15);
|
||||
|
||||
// 人类行为参数
|
||||
private static final int MIN_CLICK_HOLD_DURATION = 300;
|
||||
private static final int MAX_CLICK_HOLD_DURATION = 800;
|
||||
private static final int MIN_MOVE_DURATION = 1000;
|
||||
private static final int MAX_MOVE_DURATION = 2000;
|
||||
private static final double OVERSHOOT_FACTOR = 1.05; // 5%的过冲概率
|
||||
|
||||
public AdvancedSliderCaptchaHandler(WebDriver driver) {
|
||||
this.driver = driver;
|
||||
this.wait = new WebDriverWait(driver, WAIT_TIMEOUT.toSeconds());
|
||||
this.actions = new Actions(driver);
|
||||
this.random = new Random();
|
||||
}
|
||||
public boolean handleAnyCaptcha() {
|
||||
for (int attempt = 1; attempt <= MAX_RETRY_ATTEMPTS; attempt++) {
|
||||
System.out.println("第 " + attempt + " 次尝试处理验证码");
|
||||
|
||||
CaptchaType captchaType = detectCaptchaType();
|
||||
if (captchaType == CaptchaType.NONE) {
|
||||
System.out.println("未检测到验证码");
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean success = processCaptchaByType(captchaType);
|
||||
if (success) {
|
||||
System.out.println("验证码处理成功");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (attempt < MAX_RETRY_ATTEMPTS) {
|
||||
waitBeforeRetry();
|
||||
}
|
||||
}
|
||||
|
||||
System.err.println("验证码处理失败,已达到最大重试次数");
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测验证码类型
|
||||
*/
|
||||
private CaptchaType detectCaptchaType() {
|
||||
try {
|
||||
if (isElementPresent(By.id("nc_1_n1z"))) {
|
||||
return CaptchaType.ALIBABA_SLIDER;
|
||||
}
|
||||
|
||||
// 检测通用滑块
|
||||
if (isElementPresent(By.className("btn_slide")) ||
|
||||
isElementPresent(By.className("slider-btn"))) {
|
||||
return CaptchaType.GENERIC_SLIDER;
|
||||
}
|
||||
|
||||
// 检测其他常见滑块选择器
|
||||
String[] commonSelectors = {
|
||||
".captcha-slider-btn",
|
||||
".slide-verify-slider-mask-item",
|
||||
".slider_bg .slider_btn"
|
||||
};
|
||||
|
||||
for (String selector : commonSelectors) {
|
||||
if (isElementPresent(By.cssSelector(selector))) {
|
||||
return CaptchaType.GENERIC_SLIDER;
|
||||
}
|
||||
}
|
||||
|
||||
return CaptchaType.NONE;
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("检测验证码类型时发生错误: " + e.getMessage());
|
||||
return CaptchaType.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据验证码类型进行处理
|
||||
*/
|
||||
private boolean processCaptchaByType(CaptchaType type) {
|
||||
switch (type) {
|
||||
case ALIBABA_SLIDER:
|
||||
return handleAlibabaSlider();
|
||||
case GENERIC_SLIDER:
|
||||
return handleGenericSlider();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理阿里云滑块验证码
|
||||
*/
|
||||
private boolean handleAlibabaSlider() {
|
||||
try {
|
||||
WebElement sliderButton = wait.until(
|
||||
ExpectedConditions.elementToBeClickable(By.id("nc_1_n1z"))
|
||||
);
|
||||
WebElement sliderTrack = driver.findElement(By.id("nc_1_n1t"));
|
||||
|
||||
int moveDistance = calculateMoveDistance(sliderTrack, sliderButton);
|
||||
return performSmartSlide(sliderButton, moveDistance);
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("处理阿里云滑块失败: " + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理通用滑块验证码
|
||||
*/
|
||||
private boolean handleGenericSlider() {
|
||||
try {
|
||||
List<WebElement> sliderButtons = driver.findElements(By.className("btn_slide"));
|
||||
if (sliderButtons.isEmpty()) {
|
||||
sliderButtons = driver.findElements(By.className("slider-btn"));
|
||||
}
|
||||
|
||||
if (sliderButtons.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WebElement sliderButton = sliderButtons.get(0);
|
||||
WebElement sliderTrack = findSliderTrack(sliderButton);
|
||||
|
||||
if (sliderTrack == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int moveDistance = calculateMoveDistance(sliderTrack, sliderButton);
|
||||
System.out.println("处理通用滑块失败: ");
|
||||
return performSmartSlide(sliderButton, moveDistance);
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("处理通用滑块失败: " + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 智能滑动算法
|
||||
*/
|
||||
// private boolean performSmartSlide(WebElement sliderButton, int totalDistance) {
|
||||
// try {
|
||||
// actions.clickAndHold(sliderButton).perform();
|
||||
// Thread.sleep(50 + random.nextInt(200));
|
||||
//
|
||||
// int moved = 0;
|
||||
// int segments = 20 + random.nextInt(5);
|
||||
//
|
||||
// for (int i = 0; i < segments && moved < totalDistance; i++) {
|
||||
// double progress = (double) i / segments;
|
||||
// int stepSize = (int) (totalDistance * getBezierValue(progress) - moved);
|
||||
//
|
||||
// if (stepSize > 0 && moved + stepSize <= totalDistance) {
|
||||
// int yOffset = (int) (Math.sin(progress * Math.PI * 2) * 2);
|
||||
// actions.moveByOffset(stepSize, yOffset).perform();
|
||||
// moved += stepSize;
|
||||
//
|
||||
// }
|
||||
// }
|
||||
// if (moved < totalDistance) {
|
||||
// actions.moveByOffset(totalDistance - moved, 0).perform();
|
||||
// }
|
||||
//
|
||||
// Thread.sleep(50 + random.nextInt(200));
|
||||
// actions.release().perform();
|
||||
//
|
||||
// return waitForVerificationResult();
|
||||
//
|
||||
// } catch (Exception e) {
|
||||
// System.err.println("智能滑动失败: " + e.getMessage());
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* 贝塞尔曲线值计算
|
||||
*/
|
||||
private double getBezierValue(double t) {
|
||||
return t * t * (3.0 - 2.0 * t);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算移动距离
|
||||
*/
|
||||
private int calculateMoveDistance(WebElement track, WebElement button) {
|
||||
int trackWidth = track.getSize().getWidth() + 100;
|
||||
int buttonWidth = button.getSize().getWidth();
|
||||
return Math.max(trackWidth - buttonWidth - 5, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找滑块轨道
|
||||
*/
|
||||
private WebElement findSliderTrack(WebElement button) {
|
||||
try {
|
||||
return button.findElement(By.xpath("./parent::*"));
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 等待验证结果
|
||||
*/
|
||||
private boolean waitForVerificationResult() {
|
||||
try {
|
||||
Thread.sleep(2000);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查元素是否存在
|
||||
*/
|
||||
private boolean isElementPresent(By locator) {
|
||||
try {
|
||||
driver.findElement(locator);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重试前等待
|
||||
*/
|
||||
private void waitBeforeRetry() {
|
||||
try {
|
||||
Thread.sleep(2000 + random.nextInt(3000));
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证码类型枚举
|
||||
*/
|
||||
private enum CaptchaType {
|
||||
NONE,
|
||||
ALIBABA_SLIDER,
|
||||
GENERIC_SLIDER
|
||||
}
|
||||
|
||||
private boolean performSmartSlide(WebElement sliderButton, int totalDistance) {
|
||||
try {
|
||||
// 模拟人类点击前的短暂思考时间
|
||||
randomSleep(MIN_CLICK_HOLD_DURATION, MAX_CLICK_HOLD_DURATION);
|
||||
|
||||
// 点击并按住滑块
|
||||
actions.clickAndHold(sliderButton).perform();
|
||||
|
||||
// 生成更自然的移动轨迹
|
||||
List<MoveStep> moveSteps = generateHumanLikeTrajectory(totalDistance);
|
||||
|
||||
// 执行移动步骤
|
||||
long startTime = System.currentTimeMillis();
|
||||
long currentTime = startTime;
|
||||
long endTime = startTime + randomLong(MIN_MOVE_DURATION, MAX_MOVE_DURATION);
|
||||
|
||||
for (MoveStep step : moveSteps) {
|
||||
// 根据时间进度执行步骤,使整体移动速度更自然
|
||||
while (currentTime < endTime * step.timeProgress) {
|
||||
actions.moveByOffset(step.xOffset, step.yOffset).perform();
|
||||
currentTime = System.currentTimeMillis();
|
||||
|
||||
// 微小的随机停顿
|
||||
if (random.nextDouble() < 0.1) {
|
||||
Thread.sleep(random.nextInt(50));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 随机过冲然后回退,更像人类操作
|
||||
if (random.nextDouble() < OVERSHOOT_FACTOR) {
|
||||
int overshoot = random.nextInt(5) + 5;
|
||||
actions.moveByOffset(overshoot, 0).perform();
|
||||
Thread.sleep(random.nextInt(100) + 50);
|
||||
actions.moveByOffset(-overshoot, 0).perform();
|
||||
}
|
||||
|
||||
// 释放前的随机延迟
|
||||
randomSleep(100, 300);
|
||||
actions.release().perform();
|
||||
|
||||
// 模拟验证过程中的等待
|
||||
randomSleep(500, 1500);
|
||||
|
||||
return waitForVerificationResult();
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("智能滑动失败: " + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成更接近人类行为的滑动轨迹
|
||||
*/
|
||||
private List<MoveStep> generateHumanLikeTrajectory(int totalDistance) {
|
||||
java.util.List<MoveStep> steps = new java.util.ArrayList<>();
|
||||
|
||||
// 总步数 - 随机但合理的范围
|
||||
int totalSteps = random.nextInt(15) + 25;
|
||||
|
||||
// 计算每个时间点的进度(0-1之间)
|
||||
double[] timeProgress = new double[totalSteps];
|
||||
for (int i = 0; i < totalSteps; i++) {
|
||||
timeProgress[i] = (double) i / totalSteps;
|
||||
}
|
||||
|
||||
// 生成更自然的S型速度曲线(开始和结束较慢,中间较快)
|
||||
double[] distanceProgress = new double[totalSteps];
|
||||
for (int i = 0; i < totalSteps; i++) {
|
||||
double t = timeProgress[i];
|
||||
// 使用改进的S型曲线函数
|
||||
distanceProgress[i] = t * t * t * (t * (t * 6 - 15) + 10);
|
||||
}
|
||||
|
||||
// 计算每一步的偏移量
|
||||
for (int i = 0; i < totalSteps; i++) {
|
||||
double currentDistance = i == 0 ?
|
||||
distanceProgress[i] * totalDistance :
|
||||
(distanceProgress[i] - distanceProgress[i-1]) * totalDistance;
|
||||
|
||||
// 添加小幅度的垂直偏移,模拟人类手部颤抖
|
||||
int yOffset = random.nextInt(3) - 1; // -1, 0, 1
|
||||
|
||||
steps.add(new MoveStep(
|
||||
(int) Math.round(currentDistance),
|
||||
yOffset,
|
||||
timeProgress[i]
|
||||
));
|
||||
}
|
||||
|
||||
return steps;
|
||||
}
|
||||
|
||||
/**
|
||||
* 随机睡眠一段时间
|
||||
*/
|
||||
private void randomSleep(int min, int max) throws InterruptedException {
|
||||
Thread.sleep(random.nextInt(max - min + 1) + min);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成随机长整型数
|
||||
*/
|
||||
private long randomLong(long min, long max) {
|
||||
return min + (long) (random.nextDouble() * (max - min));
|
||||
}
|
||||
|
||||
/**
|
||||
* 移动步骤类 - 封装每一步的移动信息
|
||||
*/
|
||||
private static class MoveStep {
|
||||
final int xOffset;
|
||||
final int yOffset;
|
||||
final double timeProgress;
|
||||
|
||||
MoveStep(int xOffset, int yOffset, double timeProgress) {
|
||||
this.xOffset = xOffset;
|
||||
this.yOffset = yOffset;
|
||||
this.timeProgress = timeProgress;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -198,7 +198,6 @@ public class ClientAccountController extends BaseController {
|
||||
Map<String, Object> claims = Jwts.parser().setSigningKey(jwtRsaKeyService.getPublicKey()).parseClaimsJws(token).getBody();
|
||||
String username = (String) claims.getOrDefault("sub", claims.get("subject"));
|
||||
String tokenClientId = (String) claims.get("clientId");
|
||||
|
||||
if (username == null || tokenClientId == null || !tokenClientId.equals(clientId)) {
|
||||
throw new RuntimeException("会话不匹配");
|
||||
}
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
package com.ruoyi.web.controller.monitor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.ruoyi.common.annotation.Anonymous;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@@ -12,8 +8,8 @@ import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
import com.ruoyi.system.domain.*;
|
||||
import com.ruoyi.web.service.IClientMonitorService;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.web.service.IClientMonitorService;
|
||||
|
||||
/**
|
||||
* 客户端监控控制器
|
||||
@@ -111,18 +107,7 @@ public class ClientMonitorController extends BaseController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户端心跳API
|
||||
*/
|
||||
@PostMapping("/api/heartbeat")
|
||||
public AjaxResult clientHeartbeat(@RequestBody Map<String, Object> heartbeatData) {
|
||||
try {
|
||||
clientMonitorService.recordHeartbeat(heartbeatData);
|
||||
return AjaxResult.success();
|
||||
} catch (Exception e) {
|
||||
return AjaxResult.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 客户端错误上报API
|
||||
@@ -170,66 +155,6 @@ public class ClientMonitorController extends BaseController {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取客户端日志内容
|
||||
*/
|
||||
@GetMapping("/logs/{clientId}")
|
||||
public AjaxResult getClientLogs(@PathVariable String clientId) {
|
||||
try {
|
||||
return AjaxResult.success(clientMonitorService.getClientLogs(clientId));
|
||||
} catch (Exception e) {
|
||||
return AjaxResult.error("获取客户端日志失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载客户端日志文件
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('monitor:client:list')")
|
||||
@GetMapping("/logs/{clientId}/download")
|
||||
public void downloadClientLogs(@PathVariable String clientId, HttpServletResponse response) {
|
||||
try {
|
||||
clientMonitorService.downloadClientLogs(clientId, response);
|
||||
} catch (Exception e) {
|
||||
logger.error("下载客户端日志失败: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户端日志上传接口
|
||||
*/
|
||||
@PostMapping("/logs/upload")
|
||||
public AjaxResult uploadClientLogs(@RequestBody Map<String, Object> logData) {
|
||||
try {
|
||||
clientMonitorService.saveClientLogs(logData);
|
||||
return AjaxResult.success();
|
||||
} catch (Exception e) {
|
||||
return AjaxResult.error("保存客户端日志失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 客户端日志批量上传接口
|
||||
*/
|
||||
@PostMapping("/logs/batchUpload")
|
||||
public AjaxResult batchUploadClientLogs(@RequestBody Map<String, Object> batchLogData) {
|
||||
try {
|
||||
String clientId = (String) batchLogData.get("clientId");
|
||||
List<String> logEntries = (List<String>) batchLogData.get("logEntries");
|
||||
|
||||
if (clientId == null || logEntries == null || logEntries.isEmpty()) {
|
||||
return AjaxResult.error("无效的批量日志数据");
|
||||
}
|
||||
|
||||
clientMonitorService.saveBatchClientLogs(clientId, logEntries);
|
||||
return AjaxResult.success();
|
||||
} catch (Exception e) {
|
||||
return AjaxResult.error("批量保存客户端日志失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 清理过期数据
|
||||
*/
|
||||
|
||||
@@ -2,11 +2,7 @@ package com.ruoyi.web.service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.ruoyi.system.domain.ClientInfo;
|
||||
import com.ruoyi.system.domain.ClientErrorReport;
|
||||
import com.ruoyi.system.domain.ClientDataReport;
|
||||
import com.ruoyi.system.domain.ClientEventLog;
|
||||
import com.ruoyi.system.domain.*;
|
||||
|
||||
/**
|
||||
* 客户端监控服务接口
|
||||
@@ -16,144 +12,117 @@ import com.ruoyi.system.domain.ClientEventLog;
|
||||
public interface IClientMonitorService {
|
||||
|
||||
/**
|
||||
* 查询客户端信息列表
|
||||
* 查询客户端设备列表
|
||||
*/
|
||||
public List<ClientInfo> selectClientInfoList(ClientInfo clientInfo);
|
||||
List<ClientDevice> selectClientDeviceList(String username);
|
||||
|
||||
/**
|
||||
* 查询客户端错误报告列表
|
||||
*/
|
||||
public List<Map<String, Object>> selectClientErrorList(ClientErrorReport clientErrorReport);
|
||||
List<Map<String, Object>> selectClientErrorList(ClientErrorReport clientErrorReport);
|
||||
|
||||
/**
|
||||
* 查询客户端事件日志列表
|
||||
*/
|
||||
public List<ClientEventLog> selectClientEventLogList(ClientEventLog clientEventLog);
|
||||
List<ClientEventLog> selectClientEventLogList(ClientEventLog clientEventLog);
|
||||
|
||||
/**
|
||||
* 查询客户端数据采集报告列表
|
||||
*/
|
||||
public List<ClientDataReport> selectClientDataReportList(ClientDataReport clientDataReport);
|
||||
List<ClientDataReport> selectClientDataReportList(ClientDataReport clientDataReport);
|
||||
|
||||
/**
|
||||
* 查询在线客户端数量
|
||||
*/
|
||||
public int selectOnlineClientCount();
|
||||
int selectOnlineClientCount();
|
||||
|
||||
/**
|
||||
* 检查客户端是否在线
|
||||
*/
|
||||
boolean isClientOnline(String clientId);
|
||||
|
||||
/**
|
||||
* 获取在线客户端ID列表
|
||||
*/
|
||||
List<String> getOnlineClientIds();
|
||||
|
||||
/**
|
||||
* 查询客户端总数
|
||||
*/
|
||||
public int selectTotalClientCount();
|
||||
|
||||
/**
|
||||
* 新增客户端信息
|
||||
*/
|
||||
public int insertClientInfo(ClientInfo clientInfo);
|
||||
|
||||
/**
|
||||
* 新增客户端错误报告
|
||||
*/
|
||||
public int insertClientError(ClientErrorReport clientErrorReport);
|
||||
|
||||
/**
|
||||
* 新增客户端事件日志
|
||||
*/
|
||||
public int insertClientEventLog(ClientEventLog clientEventLog);
|
||||
|
||||
/**
|
||||
* 新增客户端数据采集报告
|
||||
*/
|
||||
public int insertDataReport(ClientDataReport clientDataReport);
|
||||
int selectTotalClientCount();
|
||||
|
||||
/**
|
||||
* 获取客户端统计数据
|
||||
*/
|
||||
public Map<String, Object> getClientStatistics();
|
||||
Map<String, Object> getClientStatistics();
|
||||
|
||||
/**
|
||||
* 获取客户端活跃趋势
|
||||
*/
|
||||
public Map<String, Object> getClientActiveTrend();
|
||||
Map<String, Object> getClientActiveTrend();
|
||||
|
||||
/**
|
||||
* 获取数据采集类型分布
|
||||
*/
|
||||
public Map<String, Object> getDataTypeDistribution();
|
||||
Map<String, Object> getDataTypeDistribution();
|
||||
|
||||
/**
|
||||
* 获取近7天在线客户端趋势
|
||||
* 获取在线客户端趋势
|
||||
*/
|
||||
public Map<String, Object> getOnlineClientTrend();
|
||||
Map<String, Object> getOnlineClientTrend();
|
||||
|
||||
/**
|
||||
* 客户端认证
|
||||
*/
|
||||
public Map<String, Object> authenticateClient(String authKey, Map<String, Object> clientInfo);
|
||||
Map<String, Object> authenticateClient(String authKey, Map<String, Object> clientInfo);
|
||||
|
||||
/**
|
||||
* 记录客户端心跳
|
||||
* 记录错误报告
|
||||
*/
|
||||
public void recordHeartbeat(Map<String, Object> heartbeatData);
|
||||
void recordErrorReport(Map<String, Object> errorData);
|
||||
|
||||
/**
|
||||
* 记录客户端错误
|
||||
* 记录数据报告
|
||||
*/
|
||||
public void recordErrorReport(Map<String, Object> errorData);
|
||||
/**
|
||||
* 记录客户端数据采集报告
|
||||
*/
|
||||
public void recordDataReport(Map<String, Object> dataReport);
|
||||
void recordDataReport(Map<String, Object> dataReport);
|
||||
|
||||
/**
|
||||
* 获取客户端详细信息
|
||||
*/
|
||||
public Map<String, Object> getClientDetail(String clientId);
|
||||
Map<String, Object> getClientDetail(String clientId);
|
||||
|
||||
/**
|
||||
* 获取客户端版本分布
|
||||
* 获取版本分布
|
||||
*/
|
||||
public List<Map<String, Object>> getVersionDistribution();
|
||||
List<Map<String, Object>> getVersionDistribution();
|
||||
|
||||
/**
|
||||
* 记录1688风控监控数据
|
||||
* 插入客户端错误报告
|
||||
*/
|
||||
public void recordAlibaba1688MonitorData(Map<String, Object> monitorData);
|
||||
int insertClientError(ClientErrorReport clientErrorReport);
|
||||
|
||||
/**
|
||||
* 查询1688风控监控数据列表
|
||||
* 插入客户端设备
|
||||
*/
|
||||
public List<Map<String, Object>> selectAlibaba1688MonitorList(Map<String, Object> params);
|
||||
int insertClientDevice(ClientDevice clientDevice);
|
||||
|
||||
/**
|
||||
* 获取1688风控数据统计
|
||||
* 插入客户端事件日志
|
||||
*/
|
||||
public Map<String, Object> getAlibaba1688Statistics();
|
||||
int insertClientEventLog(ClientEventLog clientEventLog);
|
||||
|
||||
/**
|
||||
* 获取客户端日志内容
|
||||
* 插入数据报告
|
||||
*/
|
||||
public Map<String, Object> getClientLogs(String clientId);
|
||||
int insertDataReport(ClientDataReport clientDataReport);
|
||||
|
||||
/**
|
||||
* 下载客户端日志文件
|
||||
* 查询客户端信息列表
|
||||
*/
|
||||
public void downloadClientLogs(String clientId, javax.servlet.http.HttpServletResponse response);
|
||||
|
||||
/**
|
||||
* 保存客户端日志
|
||||
*/
|
||||
public void saveClientLogs(Map<String, Object> logData);
|
||||
|
||||
/**
|
||||
* 批量保存客户端日志
|
||||
*
|
||||
* @param clientId 客户端ID
|
||||
* @param logEntries 日志条目列表
|
||||
*/
|
||||
public void saveBatchClientLogs(String clientId, List<String> logEntries);
|
||||
List<ClientInfo> selectClientInfoList(ClientInfo clientInfo);
|
||||
|
||||
/**
|
||||
* 清理过期数据
|
||||
*/
|
||||
public void cleanExpiredData();
|
||||
void cleanExpiredData();
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import com.ruoyi.system.domain.*;
|
||||
import com.ruoyi.common.core.redis.RedisCache;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
@@ -21,6 +20,7 @@ import org.slf4j.LoggerFactory;
|
||||
import com.ruoyi.web.service.IClientAccountService;
|
||||
import com.ruoyi.web.service.IClientMonitorService;
|
||||
import com.ruoyi.system.mapper.ClientMonitorMapper;
|
||||
import com.ruoyi.system.mapper.ClientDeviceMapper;
|
||||
|
||||
/**
|
||||
* 客户端监控服务实现
|
||||
@@ -36,10 +36,11 @@ public class ClientMonitorServiceImpl implements IClientMonitorService {
|
||||
private ClientMonitorMapper clientMonitorMapper;
|
||||
|
||||
@Autowired
|
||||
private IClientAccountService clientAccountService;
|
||||
private ClientDeviceMapper clientDeviceMapper;
|
||||
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
private IClientAccountService clientAccountService;
|
||||
|
||||
|
||||
// 线程池用于异步处理日志记录
|
||||
private final ExecutorService logExecutor = new ThreadPoolExecutor(
|
||||
@@ -52,22 +53,17 @@ public class ClientMonitorServiceImpl implements IClientMonitorService {
|
||||
private final AtomicLong apiCallCounter = new AtomicLong(0);
|
||||
|
||||
/**
|
||||
* 查询客户端信息列表 - 增强Redis在线状态
|
||||
* 查询设备列表 - 基于ClientDevice表
|
||||
*/
|
||||
@Override
|
||||
public List<ClientInfo> selectClientInfoList(ClientInfo clientInfo) {
|
||||
logApiCallAsync("selectClientInfoList", null);
|
||||
List<ClientInfo> clientList = clientMonitorMapper.selectClientInfoList(clientInfo);
|
||||
|
||||
// 使用Redis检查并更新在线状态
|
||||
if (clientList != null) {
|
||||
for (ClientInfo client : clientList) {
|
||||
boolean isOnline = isClientOnline(client.getClientId());
|
||||
client.setOnline(isOnline ? "1" : "0");
|
||||
public List<ClientDevice> selectClientDeviceList(String username) {
|
||||
logApiCallAsync("selectClientDeviceList", null);
|
||||
if (username != null && !username.isEmpty()) {
|
||||
return clientDeviceMapper.selectByUsername(username);
|
||||
} else {
|
||||
return clientMonitorMapper.selectOnlineDevices();
|
||||
}
|
||||
}
|
||||
return clientList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询客户端错误报告列表
|
||||
@@ -97,36 +93,25 @@ public class ClientMonitorServiceImpl implements IClientMonitorService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询在线客户端数量 - 基于Redis TTL
|
||||
* 查询在线客户端数量 - 基于数据库
|
||||
*/
|
||||
@Override
|
||||
public int selectOnlineClientCount() {
|
||||
logApiCallAsync("selectOnlineClientCount", null);
|
||||
try {
|
||||
// 通过Redis检查所有心跳key
|
||||
Collection<String> heartbeatKeys = redisCache.keys("client:heartbeat:*");
|
||||
int onlineCount = heartbeatKeys != null ? heartbeatKeys.size() : 0;
|
||||
System.out.println("Redis在线客户端数量: " + onlineCount + ", keys: " + heartbeatKeys);
|
||||
return onlineCount;
|
||||
} catch (Exception e) {
|
||||
System.err.println("Redis查询在线客户端失败: " + e.getMessage());
|
||||
// Redis查询失败时使用数据库备用方案
|
||||
return clientMonitorMapper.selectOnlineClientCount();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查客户端是否在线 - 基于Redis TTL
|
||||
* 检查客户端是否在线 - 基于数据库
|
||||
*/
|
||||
@Override
|
||||
public boolean isClientOnline(String clientId) {
|
||||
if (clientId == null || clientId.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
String heartbeatKey = "client:heartbeat:" + clientId;
|
||||
boolean isOnline = redisCache.hasKey(heartbeatKey);
|
||||
System.out.println("检查客户端在线状态: " + clientId + " -> " + isOnline);
|
||||
return isOnline;
|
||||
ClientInfo clientInfo = clientMonitorMapper.selectClientInfoByClientId(clientId);
|
||||
return clientInfo != null && "1".equals(clientInfo.getOnline());
|
||||
} catch (Exception e) {
|
||||
System.err.println("检查客户端在线状态失败: " + e.getMessage());
|
||||
return false;
|
||||
@@ -134,17 +119,17 @@ public class ClientMonitorServiceImpl implements IClientMonitorService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取在线客户端列表 - 基于Redis TTL
|
||||
* 获取在线客户端列表 - 基于数据库
|
||||
*/
|
||||
@Override
|
||||
public List<String> getOnlineClientIds() {
|
||||
try {
|
||||
Collection<String> heartbeatKeys = redisCache.keys("client:heartbeat:*");
|
||||
ClientInfo queryParam = new ClientInfo();
|
||||
queryParam.setOnline("1");
|
||||
List<ClientInfo> onlineClients = clientMonitorMapper.selectClientInfoList(queryParam);
|
||||
List<String> onlineClientIds = new ArrayList<>();
|
||||
if (heartbeatKeys != null) {
|
||||
for (String key : heartbeatKeys) {
|
||||
String clientId = key.replace("client:heartbeat:", "");
|
||||
onlineClientIds.add(clientId);
|
||||
}
|
||||
for (ClientInfo client : onlineClients) {
|
||||
onlineClientIds.add(client.getClientId());
|
||||
}
|
||||
return onlineClientIds;
|
||||
} catch (Exception e) {
|
||||
@@ -443,40 +428,6 @@ public class ClientMonitorServiceImpl implements IClientMonitorService {
|
||||
private void recordClientAuth(String username, String authKey, String clientId, Map<String, Object> clientInfo, String accessToken) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录客户端心跳 - 使用Redis TTL机制
|
||||
*/
|
||||
@Override
|
||||
public void recordHeartbeat(Map<String, Object> heartbeatData) {
|
||||
try {
|
||||
String clientId = (String) heartbeatData.get("clientId");
|
||||
if (clientId == null || clientId.isEmpty()) {
|
||||
System.err.println("心跳记录失败: clientId为空");
|
||||
return;
|
||||
}
|
||||
|
||||
// 使用Redis TTL记录心跳,600秒TTL(10分钟)
|
||||
String heartbeatKey = "client:heartbeat:" + clientId;
|
||||
Map<String, Object> clientData = new HashMap<>();
|
||||
clientData.put("clientId", clientId);
|
||||
clientData.put("timestamp", System.currentTimeMillis());
|
||||
clientData.put("cpuUsage", parseDouble(heartbeatData.get("cpuUsage"), 0.0));
|
||||
clientData.put("memoryUsage", parseDouble(heartbeatData.get("memoryUsage"), 0.0));
|
||||
clientData.put("diskUsage", parseDouble(heartbeatData.get("diskUsage"), 0.0));
|
||||
clientData.put("networkStatus", heartbeatData.getOrDefault("networkStatus", "normal"));
|
||||
|
||||
// 设置Redis key,TTL为600秒
|
||||
redisCache.setCacheObject(heartbeatKey, clientData, 600, TimeUnit.SECONDS);
|
||||
System.out.println("心跳记录成功: " + heartbeatKey + ", TTL: 600秒");
|
||||
|
||||
// 只在数据库中更新基本信息(减少频率)
|
||||
clientMonitorMapper.updateClientOnlineStatus(clientId, "1");
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("记录心跳失败: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 安全解析Double值
|
||||
*/
|
||||
@@ -662,27 +613,6 @@ public class ClientMonitorServiceImpl implements IClientMonitorService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理过期客户端数据和日志
|
||||
*/
|
||||
public void cleanExpiredData() {
|
||||
try {
|
||||
// 删除7天前的心跳记录(将离线状态的客户端设为离线)
|
||||
clientMonitorMapper.updateExpiredClientsOffline();
|
||||
|
||||
// 删除30天前的错误报告
|
||||
clientMonitorMapper.deleteExpiredErrorReports();
|
||||
|
||||
|
||||
|
||||
// 删除7天前的事件日志
|
||||
clientMonitorMapper.deleteExpiredEventLogs();
|
||||
|
||||
logger.info("✅ 清理过期数据完成");
|
||||
} catch (Exception e) {
|
||||
logger.error("清理过期数据失败: {}", e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 优雅关闭线程池
|
||||
@@ -726,303 +656,10 @@ public class ClientMonitorServiceImpl implements IClientMonitorService {
|
||||
return distribution;
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录1688爬取风控监控数据
|
||||
*/
|
||||
@Override
|
||||
public void recordAlibaba1688MonitorData(Map<String, Object> monitorData) {
|
||||
// 记录API调用日志
|
||||
logApiCall("recordAlibaba1688MonitorData", "记录1688爬取风控数据");
|
||||
|
||||
try {
|
||||
// 获取客户端ID
|
||||
String clientId = (String) monitorData.get("clientId");
|
||||
|
||||
// 如果没有客户端ID,则使用系统用户名生成
|
||||
if (clientId == null || clientId.isEmpty()) {
|
||||
clientId = "user";
|
||||
monitorData.put("clientId", clientId);
|
||||
}
|
||||
|
||||
// 尝试查找已有客户端信息,如果没有则不进行严格验证
|
||||
ClientInfo authInfo = null;
|
||||
try {
|
||||
authInfo = clientMonitorMapper.selectClientInfoByClientId(clientId);
|
||||
} catch (Exception e) {
|
||||
// 查询失败时忽略,允许匿名上报
|
||||
}
|
||||
|
||||
// 如果客户端不存在,创建一个简单的客户端记录
|
||||
if (authInfo == null) {
|
||||
ClientInfo newClientInfo = new ClientInfo();
|
||||
newClientInfo.setClientId(clientId);
|
||||
newClientInfo.setUsername((String) monitorData.getOrDefault("username", "user"));
|
||||
newClientInfo.setIpAddress((String) monitorData.get("ipAddress"));
|
||||
newClientInfo.setHostname((String) monitorData.get("hostname"));
|
||||
newClientInfo.setStatus("0");
|
||||
newClientInfo.setAuthTime(DateUtils.getNowDate());
|
||||
newClientInfo.setLastActiveTime(DateUtils.getNowDate());
|
||||
newClientInfo.setOnline("1");
|
||||
|
||||
// 添加系统信息
|
||||
newClientInfo.setOsName((String) monitorData.get("osName"));
|
||||
newClientInfo.setOsVersion((String) monitorData.get("osVersion"));
|
||||
newClientInfo.setJavaVersion((String) monitorData.get("javaVersion"));
|
||||
newClientInfo.setAppVersion((String) monitorData.get("appVersion"));
|
||||
|
||||
try {
|
||||
clientMonitorMapper.insertClientInfo(newClientInfo);
|
||||
} catch (Exception e) {
|
||||
// 插入失败时忽略,可能是因为主键冲突(客户端已存在)
|
||||
logger.warn("插入客户端信息失败,可能客户端已存在: {}", e.getMessage());
|
||||
}
|
||||
} else {
|
||||
// 更新现有客户端的活跃状态
|
||||
try {
|
||||
authInfo.setLastActiveTime(DateUtils.getNowDate());
|
||||
authInfo.setOnline("1");
|
||||
if (monitorData.get("ipAddress") != null) {
|
||||
authInfo.setIpAddress((String) monitorData.get("ipAddress"));
|
||||
}
|
||||
// 更新系统信息
|
||||
if (monitorData.get("osName") != null) {
|
||||
authInfo.setOsName((String) monitorData.get("osName"));
|
||||
}
|
||||
if (monitorData.get("osVersion") != null) {
|
||||
authInfo.setOsVersion((String) monitorData.get("osVersion"));
|
||||
}
|
||||
if (monitorData.get("javaVersion") != null) {
|
||||
authInfo.setJavaVersion((String) monitorData.get("javaVersion"));
|
||||
}
|
||||
if (monitorData.get("appVersion") != null) {
|
||||
authInfo.setAppVersion((String) monitorData.get("appVersion"));
|
||||
}
|
||||
clientMonitorMapper.updateClientInfo(authInfo);
|
||||
} catch (Exception e) {
|
||||
logger.warn("更新客户端信息失败: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 设置当前时间
|
||||
monitorData.put("createTime", DateUtils.getNowDate());
|
||||
|
||||
// 插入监控数据
|
||||
clientMonitorMapper.insertAlibaba1688MonitorData(monitorData);
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("处理1688爬取风控监控数据失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询1688爬取风控监控数据列表
|
||||
*/
|
||||
@Override
|
||||
public List<Map<String, Object>> selectAlibaba1688MonitorList(Map<String, Object> params) {
|
||||
// 记录API调用日志
|
||||
logApiCall("selectAlibaba1688MonitorList", null);
|
||||
return clientMonitorMapper.selectAlibaba1688MonitorList(params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取客户端日志内容
|
||||
*/
|
||||
@Override
|
||||
public Map<String, Object> getClientLogs(String clientId) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
|
||||
try {
|
||||
// 构建日志文件路径
|
||||
String logDir = System.getProperty("user.dir") + "/logs/clients/";
|
||||
String logFilePath = logDir + clientId + ".txt";
|
||||
|
||||
File logFile = new File(logFilePath);
|
||||
if (logFile.exists()) {
|
||||
// 读取日志文件内容
|
||||
StringBuilder content = new StringBuilder();
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader(logFile, StandardCharsets.UTF_8))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
content.append(line).append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
result.put("content", content.toString());
|
||||
result.put("lastUpdate", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(logFile.lastModified())));
|
||||
} else {
|
||||
result.put("content", "暂无日志文件");
|
||||
result.put("lastUpdate", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
|
||||
}
|
||||
|
||||
// 记录API调用日志
|
||||
logApiCall("getClientLogs", "客户端ID: " + clientId);
|
||||
|
||||
} catch (Exception e) {
|
||||
result.put("content", "读取日志文件失败: " + e.getMessage());
|
||||
result.put("lastUpdate", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载客户端日志文件
|
||||
*/
|
||||
@Override
|
||||
public void downloadClientLogs(String clientId, HttpServletResponse response) {
|
||||
try {
|
||||
// 构建日志文件路径
|
||||
String logDir = System.getProperty("user.dir") + "/logs/clients/";
|
||||
String logFilePath = logDir + clientId + ".txt";
|
||||
|
||||
File logFile = new File(logFilePath);
|
||||
if (!logFile.exists()) {
|
||||
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置响应头
|
||||
response.setContentType("text/plain;charset=UTF-8");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=\"client_" + clientId + "_logs.txt\"");
|
||||
response.setContentLength((int) logFile.length());
|
||||
|
||||
// 输出文件内容
|
||||
try (FileInputStream fis = new FileInputStream(logFile);
|
||||
OutputStream os = response.getOutputStream()) {
|
||||
|
||||
byte[] buffer = new byte[4096];
|
||||
int bytesRead;
|
||||
while ((bytesRead = fis.read(buffer)) != -1) {
|
||||
os.write(buffer, 0, bytesRead);
|
||||
}
|
||||
os.flush();
|
||||
}
|
||||
|
||||
// 记录API调用日志
|
||||
logApiCall("downloadClientLogs", "客户端ID: " + clientId);
|
||||
|
||||
} catch (Exception e) {
|
||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存客户端日志
|
||||
*/
|
||||
@Override
|
||||
public void saveClientLogs(Map<String, Object> logData) {
|
||||
try {
|
||||
String clientId = (String) logData.get("clientId");
|
||||
String logContent = (String) logData.get("logContent");
|
||||
|
||||
if (clientId == null || logContent == null) {
|
||||
throw new RuntimeException("缺少必要的日志参数");
|
||||
}
|
||||
|
||||
// 创建日志目录
|
||||
String logDir = System.getProperty("user.dir") + "/logs/clients/";
|
||||
File dir = new File(logDir);
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs();
|
||||
}
|
||||
|
||||
// 写入日志文件
|
||||
String logFilePath = logDir + clientId + ".txt";
|
||||
try (FileWriter writer = new FileWriter(logFilePath, StandardCharsets.UTF_8, true)) {
|
||||
writer.write(logContent);
|
||||
writer.flush();
|
||||
}
|
||||
|
||||
// 记录API调用日志
|
||||
logApiCall("saveClientLogs", "客户端ID: " + clientId + ", 日志长度: " + logContent.length());
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("保存客户端日志失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量保存客户端日志
|
||||
*/
|
||||
@Override
|
||||
public void saveBatchClientLogs(String clientId, List<String> logEntries) {
|
||||
try {
|
||||
if (clientId == null || logEntries == null || logEntries.isEmpty()) {
|
||||
throw new RuntimeException("缺少必要的日志参数");
|
||||
}
|
||||
|
||||
// 创建日志目录
|
||||
String logDir = System.getProperty("user.dir") + "/logs/clients/";
|
||||
File dir = new File(logDir);
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs();
|
||||
}
|
||||
|
||||
// 写入日志文件
|
||||
String logFilePath = logDir + clientId + ".txt";
|
||||
try (FileWriter writer = new FileWriter(logFilePath, StandardCharsets.UTF_8, true)) {
|
||||
for (String logEntry : logEntries) {
|
||||
if (logEntry != null && !logEntry.isEmpty()) {
|
||||
writer.write(logEntry);
|
||||
writer.write(System.lineSeparator());
|
||||
}
|
||||
}
|
||||
writer.flush();
|
||||
}
|
||||
|
||||
// 记录API调用日志
|
||||
logApiCall("saveBatchClientLogs", "客户端ID: " + clientId + ", 日志条目数: " + logEntries.size());
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("批量保存客户端日志失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取1688爬取风控数据统计
|
||||
*/
|
||||
@Override
|
||||
public Map<String, Object> getAlibaba1688Statistics() {
|
||||
// 记录API调用日志
|
||||
logApiCall("getAlibaba1688Statistics", null);
|
||||
|
||||
// 获取统计数据
|
||||
Map<String, Object> stats = clientMonitorMapper.selectAlibaba1688Statistics();
|
||||
if (stats == null) {
|
||||
stats = new HashMap<>();
|
||||
}
|
||||
|
||||
// 如果没有数据,设置默认值
|
||||
if (!stats.containsKey("totalEvents")) {
|
||||
stats.put("totalEvents", 0);
|
||||
}
|
||||
if (!stats.containsKey("mobileBlockedCount")) {
|
||||
stats.put("mobileBlockedCount", 0);
|
||||
}
|
||||
if (!stats.containsKey("desktopBlockedCount")) {
|
||||
stats.put("desktopBlockedCount", 0);
|
||||
}
|
||||
if (!stats.containsKey("avgMobileDuration")) {
|
||||
stats.put("avgMobileDuration", 0);
|
||||
}
|
||||
if (!stats.containsKey("avgDesktopDuration")) {
|
||||
stats.put("avgDesktopDuration", 0);
|
||||
}
|
||||
if (!stats.containsKey("uniqueIpCount")) {
|
||||
stats.put("uniqueIpCount", 0);
|
||||
}
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从客户端信息中获取IP地址
|
||||
*/
|
||||
private String getClientIp(Map<String, Object> clientInfo) {
|
||||
return clientInfo != null && clientInfo.containsKey("ipAddress")
|
||||
? (String) clientInfo.get("ipAddress")
|
||||
: "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成会话令牌
|
||||
@@ -1043,8 +680,8 @@ public class ClientMonitorServiceImpl implements IClientMonitorService {
|
||||
* 新增客户端信息
|
||||
*/
|
||||
@Override
|
||||
public int insertClientInfo(ClientInfo clientInfo) {
|
||||
return clientMonitorMapper.insertClientInfo(clientInfo);
|
||||
public int insertClientDevice(ClientDevice clientDevice) {
|
||||
return clientDeviceMapper.insert(clientDevice);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1062,4 +699,37 @@ public class ClientMonitorServiceImpl implements IClientMonitorService {
|
||||
public int insertDataReport(ClientDataReport clientDataReport) {
|
||||
return clientMonitorMapper.insertDataReport(clientDataReport);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询客户端信息列表
|
||||
*/
|
||||
@Override
|
||||
public List<ClientInfo> selectClientInfoList(ClientInfo clientInfo) {
|
||||
return clientMonitorMapper.selectClientInfoList(clientInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理过期数据
|
||||
*/
|
||||
@Override
|
||||
public void cleanExpiredData() {
|
||||
try {
|
||||
// 清理过期的客户端(设置为离线状态)
|
||||
clientMonitorMapper.updateExpiredClientsOffline();
|
||||
|
||||
// 清理过期的设备(设置为离线状态)
|
||||
clientMonitorMapper.updateExpiredDevicesOffline();
|
||||
|
||||
// 删除过期的错误报告
|
||||
clientMonitorMapper.deleteExpiredErrorReports();
|
||||
|
||||
// 删除过期的事件日志
|
||||
clientMonitorMapper.deleteExpiredEventLogs();
|
||||
|
||||
logger.info("过期数据清理完成");
|
||||
} catch (Exception e) {
|
||||
logger.error("清理过期数据失败: {}", e.getMessage(), e);
|
||||
throw new RuntimeException("清理过期数据失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
api.datacenterId=1
|
||||
api.workerId=1
|
||||
api.domainName=http://xxx.com
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user